alicezetion 1.8.7 → 1.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/.cache/replit/modules/{nodejs-20:v25-20240206-fdbd396.res → nodejs-20:v28-20240213-3f08513.res} +1 -1
  2. package/.cache/replit/modules/replit:v5-20240209-9e3a339.res +1 -0
  3. package/.cache/typescript/5.3/node_modules/.package-lock.json +32 -3
  4. package/.cache/typescript/5.3/node_modules/@types/prop-types/LICENSE +21 -0
  5. package/.cache/typescript/5.3/node_modules/@types/prop-types/README.md +15 -0
  6. package/.cache/typescript/5.3/node_modules/@types/prop-types/index.d.ts +98 -0
  7. package/.cache/typescript/5.3/node_modules/@types/prop-types/package.json +35 -0
  8. package/.cache/typescript/5.3/node_modules/@types/react/LICENSE +21 -0
  9. package/.cache/typescript/5.3/node_modules/@types/react/README.md +15 -0
  10. package/.cache/typescript/5.3/node_modules/@types/react/canary.d.ts +112 -0
  11. package/.cache/typescript/5.3/node_modules/@types/react/experimental.d.ts +126 -0
  12. package/.cache/typescript/5.3/node_modules/@types/react/global.d.ts +158 -0
  13. package/.cache/typescript/5.3/node_modules/@types/react/index.d.ts +4351 -0
  14. package/.cache/typescript/5.3/node_modules/@types/react/jsx-dev-runtime.d.ts +13 -0
  15. package/.cache/typescript/5.3/node_modules/@types/react/jsx-runtime.d.ts +13 -0
  16. package/.cache/typescript/5.3/node_modules/@types/react/package.json +206 -0
  17. package/.cache/typescript/5.3/node_modules/@types/react/ts5.0/canary.d.ts +112 -0
  18. package/.cache/typescript/5.3/node_modules/@types/react/ts5.0/experimental.d.ts +126 -0
  19. package/.cache/typescript/5.3/node_modules/@types/react/ts5.0/global.d.ts +158 -0
  20. package/.cache/typescript/5.3/node_modules/@types/react/ts5.0/index.d.ts +4333 -0
  21. package/.cache/typescript/5.3/node_modules/@types/react/ts5.0/jsx-dev-runtime.d.ts +12 -0
  22. package/.cache/typescript/5.3/node_modules/@types/react/ts5.0/jsx-runtime.d.ts +12 -0
  23. package/.cache/typescript/5.3/node_modules/@types/scheduler/LICENSE +21 -0
  24. package/.cache/typescript/5.3/node_modules/@types/scheduler/README.md +15 -0
  25. package/.cache/typescript/5.3/node_modules/@types/scheduler/index.d.ts +30 -0
  26. package/.cache/typescript/5.3/node_modules/@types/scheduler/package.json +30 -0
  27. package/.cache/typescript/5.3/node_modules/@types/scheduler/tracing.d.ts +127 -0
  28. package/.cache/typescript/5.3/node_modules/csstype/LICENSE +19 -0
  29. package/.cache/typescript/5.3/node_modules/csstype/README.md +277 -0
  30. package/.cache/typescript/5.3/node_modules/csstype/index.d.ts +21297 -0
  31. package/.cache/typescript/5.3/node_modules/csstype/index.js.flow +6612 -0
  32. package/.cache/typescript/5.3/node_modules/csstype/package.json +66 -0
  33. package/.cache/typescript/5.3/node_modules/types-registry/index.json +1 -1
  34. package/.cache/typescript/5.3/node_modules/types-registry/package.json +2 -2
  35. package/.cache/typescript/5.3/package-lock.json +34 -4
  36. package/.cache/typescript/5.3/package.json +1 -1
  37. package/leiamnash/listenMqtt.js +823 -814
  38. package/package.json +1 -1
  39. package/.cache/replit/modules/replit:v4-20240206-fdbd396.res +0 -1
@@ -10,834 +10,843 @@ const EventEmitter = require('events');
10
10
  const identity = function () { };
11
11
 
12
12
  const topics = [
13
- "/legacy_web",
14
- "/webrtc",
15
- "/rtc_multi",
16
- "/onevc",
17
- "/br_sr", //Notification
18
- //Need to publish /br_sr right after this
19
- "/sr_res",
20
- "/t_ms",
21
- "/thread_typing",
22
- "/orca_typing_notifications",
23
- "/notify_disconnect",
24
- //Need to publish /messenger_sync_create_queue right after this
25
- "/orca_presence",
26
- //Will receive /sr_res right here.
27
-
28
- "/legacy_web_mtouch"
29
- // "/inbox",
30
- // "/mercury",
31
- // "/messaging_events",
32
- // "/orca_message_notifications",
33
- // "/pp",
34
- // "/webrtc_response",
13
+ "/legacy_web",
14
+ "/webrtc",
15
+ "/rtc_multi",
16
+ "/onevc",
17
+ "/br_sr", //Notification
18
+ //Need to publish /br_sr right after this
19
+ "/sr_res",
20
+ "/t_ms",
21
+ "/thread_typing",
22
+ "/orca_typing_notifications",
23
+ "/notify_disconnect",
24
+ //Need to publish /messenger_sync_create_queue right after this
25
+ "/orca_presence",
26
+ //Will receive /sr_res right here.
27
+
28
+ "/legacy_web_mtouch"
29
+ // "/inbox",
30
+ // "/mercury",
31
+ // "/messaging_events",
32
+ // "/orca_message_notifications",
33
+ // "/pp",
34
+ // "/webrtc_response",
35
35
  ];
36
36
 
37
37
  function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
38
- //Don't really know what this does but I think it's for the active state?
39
- //TODO: Move to ctx when implemented
40
- const chatOn = ctx.globalOptions.online;
41
- const foreground = false;
42
-
43
- const sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
44
- const username = {
45
- u: ctx.i_userID || ctx.userID,
46
- s: sessionID,
47
- chat_on: chatOn,
48
- fg: foreground,
49
- d: utils.getGUID(),
50
- ct: "websocket",
51
- //App id from facebook
52
- aid: "219994525426954",
53
- mqtt_sid: "",
54
- cp: 3,
55
- ecp: 10,
56
- st: [],
57
- pm: [],
58
- dc: "",
59
- no_auto_fg: true,
60
- gas: null,
61
- pack: [],
62
- a: ctx.globalOptions.userAgent,
63
- aids: null
64
- };
65
- const cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
66
-
67
- let host;
68
- if (ctx.mqttEndpoint) {
69
- host = `${ctx.mqttEndpoint}&sid=${sessionID}`;
70
- } else if (ctx.region) {
71
- host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}`;
72
- } else {
73
- host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}`;
74
- }
75
-
76
- const options = {
77
- clientId: "mqttwsclient",
78
- protocolId: 'MQIsdp',
79
- protocolVersion: 3,
80
- username: JSON.stringify(username),
81
- clean: true,
82
- wsOptions: {
83
- headers: {
84
- 'Cookie': cookies,
85
- 'Origin': 'https://www.facebook.com',
86
- 'User-Agent': ctx.globalOptions.userAgent,
87
- 'Referer': 'https://www.facebook.com/',
88
- 'Host': new URL(host).hostname //'edge-chat.facebook.com'
89
- },
90
- origin: 'https://www.facebook.com',
91
- protocolVersion: 13
92
- },
93
- keepalive: 10,
94
- reschedulePings: false
95
- };
96
-
97
- if (typeof ctx.globalOptions.proxy != "undefined") {
98
- const agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
99
- options.wsOptions.agent = agent;
100
- }
101
-
102
- ctx.mqttClient = new mqtt.Client(_ => websocket(host, options.wsOptions), options);
103
-
104
- const mqttClient = ctx.mqttClient;
105
-
106
- mqttClient.on('error', function (err) {
107
- log.error("listenMqtt", err);
108
- mqttClient.end();
109
- if (ctx.globalOptions.autoReconnect) {
110
- listenMqtt(defaultFuncs, api, ctx, globalCallback);
111
- } else {
112
- globalCallback({
113
- type: "stop_listen",
114
- error: "Connection refused: Server unavailable"
115
- }, null);
116
- }
117
- });
118
-
119
- mqttClient.on('close', function () {
120
-
121
- });
122
-
123
- mqttClient.on('connect', function () {
124
- topics.forEach(function (topicsub) {
125
- mqttClient.subscribe(topicsub);
126
- });
127
-
128
- let topic;
129
- const queue = {
130
- sync_api_version: 10,
131
- max_deltas_able_to_process: 1000,
132
- delta_batch_size: 500,
133
- encoding: "JSON",
134
- entity_fbid: ctx.i_userID || ctx.userID
135
- };
136
-
137
- if (ctx.syncToken) {
138
- topic = "/messenger_sync_get_diffs";
139
- queue.last_seq_id = ctx.lastSeqId;
140
- queue.sync_token = ctx.syncToken;
141
- } else {
142
- topic = "/messenger_sync_create_queue";
143
- queue.initial_titan_sequence_id = ctx.lastSeqId;
144
- queue.device_params = null;
145
- }
146
-
147
- mqttClient.publish(topic, JSON.stringify(queue), { qos: 1, retain: false });
148
- // set status online
149
- // fix by NTKhang
150
- mqttClient.publish("/foreground_state", JSON.stringify({ foreground: chatOn }), { qos: 1 });
151
- mqttClient.publish("/set_client_settings", JSON.stringify({ make_user_available_when_in_foreground: true }), { qos: 1 });
152
-
153
- const rTimeout = setTimeout(function () {
154
- mqttClient.end();
155
- listenMqtt(defaultFuncs, api, ctx, globalCallback);
156
- }, 5000);
157
-
158
- ctx.tmsWait = function () {
159
- clearTimeout(rTimeout);
160
- ctx.globalOptions.emitReady ? globalCallback({
161
- type: "ready",
162
- error: null
163
- }) : "";
164
- delete ctx.tmsWait;
165
- };
166
-
167
- });
168
-
169
- mqttClient.on('message', function (topic, message, _packet) {
170
- let jsonMessage = Buffer.isBuffer(message) ? Buffer.from(message).toString() : message;
171
- try {
172
- jsonMessage = JSON.parse(jsonMessage);
173
- }
174
- catch (e) {
175
- jsonMessage = {};
176
- }
177
-
178
- if (jsonMessage.type === "jewel_requests_add") {
179
- globalCallback(null, {
180
- type: "friend_request_received",
181
- actorFbId: jsonMessage.from.toString(),
182
- timestamp: Date.now().toString()
183
- });
184
- }
185
- else if (jsonMessage.type === "jewel_requests_remove_old") {
186
- globalCallback(null, {
187
- type: "friend_request_cancel",
188
- actorFbId: jsonMessage.from.toString(),
189
- timestamp: Date.now().toString()
190
- });
191
- }
192
- else if (topic === "/t_ms") {
193
- if (ctx.tmsWait && typeof ctx.tmsWait == "function") {
194
- ctx.tmsWait();
195
- }
196
-
197
- if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
198
- ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
199
- ctx.syncToken = jsonMessage.syncToken;
200
- }
201
-
202
- if (jsonMessage.lastIssuedSeqId) {
203
- ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
204
- }
205
-
206
- //If it contains more than 1 delta
207
- for (const i in jsonMessage.deltas) {
208
- const delta = jsonMessage.deltas[i];
209
- parseDelta(defaultFuncs, api, ctx, globalCallback, { "delta": delta });
210
- }
211
- } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
212
- const typ = {
213
- type: "typ",
214
- isTyping: !!jsonMessage.state,
215
- from: jsonMessage.sender_fbid.toString(),
216
- threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
217
- };
218
- (function () { globalCallback(null, typ); })();
219
- } else if (topic === "/orca_presence") {
220
- if (!ctx.globalOptions.updatePresence) {
221
- for (const i in jsonMessage.list) {
222
- const data = jsonMessage.list[i];
223
- const userID = data["u"];
224
-
225
- const presence = {
226
- type: "presence",
227
- userID: userID.toString(),
228
- //Convert to ms
229
- timestamp: data["l"] * 1000,
230
- statuses: data["p"]
231
- };
232
- (function () { globalCallback(null, presence); })();
233
- }
234
- }
235
- }
236
-
237
- });
38
+ //Don't really know what this does but I think it's for the active state?
39
+ //TODO: Move to ctx when implemented
40
+ const chatOn = ctx.globalOptions.online;
41
+ const foreground = false;
42
+
43
+ const sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
44
+ const username = {
45
+ u: ctx.i_userID || ctx.userID,
46
+ s: sessionID,
47
+ chat_on: chatOn,
48
+ fg: foreground,
49
+ d: utils.getGUID(),
50
+ ct: "websocket",
51
+ //App id from facebook
52
+ aid: "219994525426954",
53
+ mqtt_sid: "",
54
+ cp: 3,
55
+ ecp: 10,
56
+ st: [],
57
+ pm: [],
58
+ dc: "",
59
+ no_auto_fg: true,
60
+ gas: null,
61
+ pack: [],
62
+ a: ctx.globalOptions.userAgent,
63
+ aids: null
64
+ };
65
+ const cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
66
+
67
+ let host;
68
+ if (ctx.mqttEndpoint) {
69
+ host = `${ctx.mqttEndpoint}&sid=${sessionID}`;
70
+ } else if (ctx.region) {
71
+ host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}`;
72
+ } else {
73
+ host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}`;
74
+ }
75
+
76
+ const options = {
77
+ clientId: "mqttwsclient",
78
+ protocolId: 'MQIsdp',
79
+ protocolVersion: 3,
80
+ username: JSON.stringify(username),
81
+ clean: true,
82
+ wsOptions: {
83
+ headers: {
84
+ 'Cookie': cookies,
85
+ 'Origin': 'https://www.facebook.com',
86
+ 'User-Agent': ctx.globalOptions.userAgent,
87
+ 'Referer': 'https://www.facebook.com/',
88
+ 'Host': new URL(host).hostname //'edge-chat.facebook.com'
89
+ },
90
+ origin: 'https://www.facebook.com',
91
+ protocolVersion: 13
92
+ },
93
+ keepalive: 10,
94
+ reschedulePings: false
95
+ };
96
+
97
+ if (typeof ctx.globalOptions.proxy != "undefined") {
98
+ const agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
99
+ options.wsOptions.agent = agent;
100
+ }
101
+
102
+ ctx.mqttClient = new mqtt.Client(_ => websocket(host, options.wsOptions), options);
103
+
104
+ const mqttClient = ctx.mqttClient;
105
+
106
+ mqttClient.on('error', function (err) {
107
+ log.error("listenMqtt", err);
108
+ mqttClient.end();
109
+ if (ctx.globalOptions.autoReconnect) {
110
+ listenMqtt(defaultFuncs, api, ctx, globalCallback);
111
+ } else {
112
+ utils.checkLiveCookie(ctx, defaultFuncs)
113
+ .then(res => {
114
+ globalCallback({
115
+ type: "stop_listen",
116
+ error: "Connection refused: Server unavailable"
117
+ }, null);
118
+ })
119
+ .catch(err => {
120
+ globalCallback({
121
+ type: "account_inactive",
122
+ error: "Maybe your account is blocked by facebook, please login and check at https://facebook.com"
123
+ }, null);
124
+ });
125
+ }
126
+ });
127
+
128
+ mqttClient.on('close', function () {
129
+
130
+ });
131
+
132
+ mqttClient.on('connect', function () {
133
+ topics.forEach(function (topicsub) {
134
+ mqttClient.subscribe(topicsub);
135
+ });
136
+
137
+ let topic;
138
+ const queue = {
139
+ sync_api_version: 10,
140
+ max_deltas_able_to_process: 1000,
141
+ delta_batch_size: 500,
142
+ encoding: "JSON",
143
+ entity_fbid: ctx.i_userID || ctx.userID
144
+ };
145
+
146
+ if (ctx.syncToken) {
147
+ topic = "/messenger_sync_get_diffs";
148
+ queue.last_seq_id = ctx.lastSeqId;
149
+ queue.sync_token = ctx.syncToken;
150
+ } else {
151
+ topic = "/messenger_sync_create_queue";
152
+ queue.initial_titan_sequence_id = ctx.lastSeqId;
153
+ queue.device_params = null;
154
+ }
155
+
156
+ mqttClient.publish(topic, JSON.stringify(queue), { qos: 1, retain: false });
157
+ // set status online
158
+ // fix by NTKhang
159
+ mqttClient.publish("/foreground_state", JSON.stringify({ foreground: chatOn }), { qos: 1 });
160
+ mqttClient.publish("/set_client_settings", JSON.stringify({ make_user_available_when_in_foreground: true }), { qos: 1 });
161
+
162
+ const rTimeout = setTimeout(function () {
163
+ mqttClient.end();
164
+ listenMqtt(defaultFuncs, api, ctx, globalCallback);
165
+ }, 5000);
166
+
167
+ ctx.tmsWait = function () {
168
+ clearTimeout(rTimeout);
169
+ ctx.globalOptions.emitReady ? globalCallback({
170
+ type: "ready",
171
+ error: null
172
+ }) : "";
173
+ delete ctx.tmsWait;
174
+ };
175
+
176
+ });
177
+
178
+ mqttClient.on('message', function (topic, message, _packet) {
179
+ let jsonMessage = Buffer.isBuffer(message) ? Buffer.from(message).toString() : message;
180
+ try {
181
+ jsonMessage = JSON.parse(jsonMessage);
182
+ }
183
+ catch (e) {
184
+ jsonMessage = {};
185
+ }
186
+
187
+ if (jsonMessage.type === "jewel_requests_add") {
188
+ globalCallback(null, {
189
+ type: "friend_request_received",
190
+ actorFbId: jsonMessage.from.toString(),
191
+ timestamp: Date.now().toString()
192
+ });
193
+ }
194
+ else if (jsonMessage.type === "jewel_requests_remove_old") {
195
+ globalCallback(null, {
196
+ type: "friend_request_cancel",
197
+ actorFbId: jsonMessage.from.toString(),
198
+ timestamp: Date.now().toString()
199
+ });
200
+ }
201
+ else if (topic === "/t_ms") {
202
+ if (ctx.tmsWait && typeof ctx.tmsWait == "function") {
203
+ ctx.tmsWait();
204
+ }
205
+
206
+ if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
207
+ ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
208
+ ctx.syncToken = jsonMessage.syncToken;
209
+ }
210
+
211
+ if (jsonMessage.lastIssuedSeqId) {
212
+ ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
213
+ }
214
+
215
+ //If it contains more than 1 delta
216
+ for (const i in jsonMessage.deltas) {
217
+ const delta = jsonMessage.deltas[i];
218
+ parseDelta(defaultFuncs, api, ctx, globalCallback, { "delta": delta });
219
+ }
220
+ } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
221
+ const typ = {
222
+ type: "typ",
223
+ isTyping: !!jsonMessage.state,
224
+ from: jsonMessage.sender_fbid.toString(),
225
+ threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
226
+ };
227
+ (function () { globalCallback(null, typ); })();
228
+ } else if (topic === "/orca_presence") {
229
+ if (!ctx.globalOptions.updatePresence) {
230
+ for (const i in jsonMessage.list) {
231
+ const data = jsonMessage.list[i];
232
+ const userID = data["u"];
233
+
234
+ const presence = {
235
+ type: "presence",
236
+ userID: userID.toString(),
237
+ //Convert to ms
238
+ timestamp: data["l"] * 1000,
239
+ statuses: data["p"]
240
+ };
241
+ (function () { globalCallback(null, presence); })();
242
+ }
243
+ }
244
+ }
245
+
246
+ });
238
247
 
239
248
  }
240
249
 
241
250
  function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
242
- if (v.delta.class == "NewMessage") {
243
- //Not tested for pages
244
- if (ctx.globalOptions.pageID &&
245
- ctx.globalOptions.pageID != v.queue
246
- )
247
- return;
248
-
249
- (function resolveAttachmentUrl(i) {
250
- if (i == (v.delta.attachments || []).length) {
251
- let fmtMsg;
252
- try {
253
- fmtMsg = utils.formatDeltaMessage(v);
254
- } catch (err) {
255
- return globalCallback({
256
- error: "Problem parsing message object. Please open an issue at https://github.com/ntkhang03/fb-chat-api/issues.",
257
- detail: err,
258
- res: v,
259
- type: "parse_error"
260
- });
261
- }
262
- if (fmtMsg) {
263
- if (ctx.globalOptions.autoMarkDelivery) {
264
- markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
265
- }
266
- }
267
- return !ctx.globalOptions.selfListen &&
268
- (fmtMsg.senderID === ctx.i_userID || fmtMsg.senderID === ctx.userID) ?
269
- undefined :
270
- (function () { globalCallback(null, fmtMsg); })();
271
- } else {
272
- if (v.delta.attachments[i].mercury.attach_type == "photo") {
273
- api.resolvePhotoUrl(
274
- v.delta.attachments[i].fbid,
275
- (err, url) => {
276
- if (!err)
277
- v.delta.attachments[
278
- i
279
- ].mercury.metadata.url = url;
280
- return resolveAttachmentUrl(i + 1);
281
- }
282
- );
283
- } else {
284
- return resolveAttachmentUrl(i + 1);
285
- }
286
- }
287
- })(0);
288
- }
289
-
290
- if (v.delta.class == "ClientPayload") {
291
- const clientPayload = utils.decodeClientPayload(
292
- v.delta.payload
293
- );
294
-
295
- if (clientPayload && clientPayload.deltas) {
296
- for (const i in clientPayload.deltas) {
297
- const delta = clientPayload.deltas[i];
298
- if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
299
- (function () {
300
- globalCallback(null, {
301
- type: "message_reaction",
302
- threadID: (delta.deltaMessageReaction.threadKey
303
- .threadFbId ?
304
- delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey
305
- .otherUserFbId).toString(),
306
- messageID: delta.deltaMessageReaction.messageId,
307
- reaction: delta.deltaMessageReaction.reaction,
308
- senderID: delta.deltaMessageReaction.senderId == 0 ? delta.deltaMessageReaction.userId.toString() : delta.deltaMessageReaction.senderId.toString(),
309
- userID: (delta.deltaMessageReaction.userId || delta.deltaMessageReaction.senderId).toString()
310
- });
311
- })();
312
- } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
313
- (function () {
314
- globalCallback(null, {
315
- type: "message_unsend",
316
- threadID: (delta.deltaRecallMessageData.threadKey.threadFbId ?
317
- delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey
318
- .otherUserFbId).toString(),
319
- messageID: delta.deltaRecallMessageData.messageID,
320
- senderID: delta.deltaRecallMessageData.senderID.toString(),
321
- deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
322
- timestamp: delta.deltaRecallMessageData.timestamp
323
- });
324
- })();
325
- } else if (delta.deltaRemoveMessage && !!ctx.globalOptions.listenEvents) {
326
- (function () {
327
- globalCallback(null, {
328
- type: "message_self_delete",
329
- threadID: (delta.deltaRemoveMessage.threadKey.threadFbId ?
330
- delta.deltaRemoveMessage.threadKey.threadFbId : delta.deltaRemoveMessage.threadKey
331
- .otherUserFbId).toString(),
332
- messageID: delta.deltaRemoveMessage.messageIds.length == 1 ? delta.deltaRemoveMessage.messageIds[0] : delta.deltaRemoveMessage.messageIds,
333
- senderID: api.getCurrentUserID(),
334
- deletionTimestamp: delta.deltaRemoveMessage.deletionTimestamp,
335
- timestamp: delta.deltaRemoveMessage.timestamp
336
- });
337
- })();
338
- }
339
- else if (delta.deltaMessageReply) {
340
- //Mention block - #1
341
- let mdata =
342
- delta.deltaMessageReply.message === undefined ? [] :
343
- delta.deltaMessageReply.message.data === undefined ? [] :
344
- delta.deltaMessageReply.message.data.prng === undefined ? [] :
345
- JSON.parse(delta.deltaMessageReply.message.data.prng);
346
- let m_id = mdata.map(u => u.i);
347
- let m_offset = mdata.map(u => u.o);
348
- let m_length = mdata.map(u => u.l);
349
-
350
- const mentions = {};
351
-
352
- for (let i = 0; i < m_id.length; i++) {
353
- mentions[m_id[i]] = (delta.deltaMessageReply.message.body || "").substring(
354
- m_offset[i],
355
- m_offset[i] + m_length[i]
356
- );
357
- }
358
- //Mention block - 1#
359
- const callbackToReturn = {
360
- type: "message_reply",
361
- threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ?
362
- delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey
363
- .otherUserFbId).toString(),
364
- messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
365
- senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId.toString(),
366
- attachments: delta.deltaMessageReply.message.attachments.map(function (att) {
367
- const mercury = JSON.parse(att.mercuryJSON);
368
- Object.assign(att, mercury);
369
- return att;
370
- }).map(att => {
371
- let x;
372
- try {
373
- x = utils._formatAttachment(att);
374
- } catch (ex) {
375
- x = att;
376
- x.error = ex;
377
- x.type = "unknown";
378
- }
379
- return x;
380
- }),
381
- body: delta.deltaMessageReply.message.body || "",
382
- isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
383
- mentions: mentions,
384
- timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
385
- participantIDs: (delta.deltaMessageReply.message.messageMetadata.cid.canonicalParticipantFbids || []).map(e => e.toString())
386
- };
387
-
388
- if (delta.deltaMessageReply.repliedToMessage) {
389
- //Mention block - #2
390
- mdata =
391
- delta.deltaMessageReply.repliedToMessage === undefined ? [] :
392
- delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
393
- delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
394
- JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
395
- m_id = mdata.map(u => u.i);
396
- m_offset = mdata.map(u => u.o);
397
- m_length = mdata.map(u => u.l);
398
-
399
- const rmentions = {};
400
-
401
- for (let i = 0; i < m_id.length; i++) {
402
- rmentions[m_id[i]] = (delta.deltaMessageReply.repliedToMessage.body || "").substring(
403
- m_offset[i],
404
- m_offset[i] + m_length[i]
405
- );
406
- }
407
- //Mention block - 2#
408
- callbackToReturn.messageReply = {
409
- threadID: (delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ?
410
- delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey
411
- .otherUserFbId).toString(),
412
- messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
413
- senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
414
- attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function (att) {
415
- const mercury = JSON.parse(att.mercuryJSON);
416
- Object.assign(att, mercury);
417
- return att;
418
- }).map(att => {
419
- let x;
420
- try {
421
- x = utils._formatAttachment(att);
422
- } catch (ex) {
423
- x = att;
424
- x.error = ex;
425
- x.type = "unknown";
426
- }
427
- return x;
428
- }),
429
- body: delta.deltaMessageReply.repliedToMessage.body || "",
430
- isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
431
- mentions: rmentions,
432
- timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp
433
- };
434
- } else if (delta.deltaMessageReply.replyToMessageId) {
435
- return defaultFuncs
436
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
437
- "av": ctx.globalOptions.pageID,
438
- "queries": JSON.stringify({
439
- "o0": {
440
- //Using the same doc_id as forcedFetch
441
- "doc_id": "2848441488556444",
442
- "query_params": {
443
- "thread_and_message_id": {
444
- "thread_id": callbackToReturn.threadID,
445
- "message_id": delta.deltaMessageReply.replyToMessageId.id
446
- }
447
- }
448
- }
449
- })
450
- })
451
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
452
- .then((resData) => {
453
- if (resData[resData.length - 1].error_results > 0) {
454
- throw resData[0].o0.errors;
455
- }
456
-
457
- if (resData[resData.length - 1].successful_results === 0) {
458
- throw { error: "forcedFetch: there was no successful_results", res: resData };
459
- }
460
-
461
- const fetchData = resData[0].o0.data.message;
462
-
463
- const mobj = {};
464
- for (const n in fetchData.message.ranges) {
465
- mobj[fetchData.message.ranges[n].entity.id] = (fetchData.message.text || "").substr(fetchData.message.ranges[n].offset, fetchData.message.ranges[n].length);
466
- }
467
-
468
- callbackToReturn.messageReply = {
469
- threadID: callbackToReturn.threadID,
470
- messageID: fetchData.message_id,
471
- senderID: fetchData.message_sender.id.toString(),
472
- attachments: fetchData.message.blob_attachment.map(att => {
473
- let x;
474
- try {
475
- x = utils._formatAttachment({
476
- blob_attachment: att
477
- });
478
- } catch (ex) {
479
- x = att;
480
- x.error = ex;
481
- x.type = "unknown";
482
- }
483
- return x;
484
- }),
485
- body: fetchData.message.text || "",
486
- isGroup: callbackToReturn.isGroup,
487
- mentions: mobj,
488
- timestamp: parseInt(fetchData.timestamp_precise)
489
- };
490
- })
491
- .catch((err) => {
492
- log.error("forcedFetch", err);
493
- })
494
- .finally(function () {
495
- if (ctx.globalOptions.autoMarkDelivery) {
496
- markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
497
- }
498
- !ctx.globalOptions.selfListen &&
499
- (callbackToReturn.senderID === ctx.i_userID || callbackToReturn.senderID === ctx.userID) ?
500
- undefined :
501
- (function () { globalCallback(null, callbackToReturn); })();
502
- });
503
- } else {
504
- callbackToReturn.delta = delta;
505
- }
506
-
507
- if (ctx.globalOptions.autoMarkDelivery) {
508
- markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
509
- }
510
-
511
- return !ctx.globalOptions.selfListen &&
512
- (callbackToReturn.senderID === ctx.i_userID || callbackToReturn.senderID === ctx.userID) ?
513
- undefined :
514
- (function () { globalCallback(null, callbackToReturn); })();
515
- }
516
- }
517
- return;
518
- }
519
- }
520
-
521
- if (v.delta.class !== "NewMessage" &&
522
- !ctx.globalOptions.listenEvents
523
- )
524
- return;
525
-
526
- switch (v.delta.class) {
527
- case "ReadReceipt":
528
- var fmtMsg;
529
- try {
530
- fmtMsg = utils.formatDeltaReadReceipt(v.delta);
531
- }
532
- catch (err) {
533
- return globalCallback({
534
- error: "Problem parsing message object. Please open an issue at https://github.com/ntkhang03/fb-chat-api/issues.",
535
- detail: err,
536
- res: v.delta,
537
- type: "parse_error"
538
- });
539
- }
540
- return (function () { globalCallback(null, fmtMsg); })();
541
- case "AdminTextMessage":
542
- switch (v.delta.type) {
543
- case "change_thread_theme":
544
- case "change_thread_nickname":
545
- case "change_thread_icon":
546
- case "change_thread_admins":
547
- case "group_poll":
548
- case "joinable_group_link_mode_change":
549
- case "magic_words":
550
- case "change_thread_approval_mode":
551
- case "messenger_call_log":
552
- case "participant_joined_group_call":
553
- var fmtMsg;
554
- try {
555
- fmtMsg = utils.formatDeltaEvent(v.delta);
556
- }
557
- catch (err) {
558
- return globalCallback({
559
- error: "Problem parsing message object. Please open an issue at https://github.com/ntkhang03/fb-chat-api/issues.",
560
- detail: err,
561
- res: v.delta,
562
- type: "parse_error"
563
- });
564
- }
565
- return (function () { globalCallback(null, fmtMsg); })();
566
- default:
567
- return;
568
- }
569
- //For group images
570
- case "ForcedFetch":
571
- if (!v.delta.threadKey) return;
572
- var mid = v.delta.messageId;
573
- var tid = v.delta.threadKey.threadFbId;
574
- if (mid && tid) {
575
- const form = {
576
- "av": ctx.globalOptions.pageID,
577
- "queries": JSON.stringify({
578
- "o0": {
579
- //This doc_id is valid as of March 25, 2020
580
- "doc_id": "2848441488556444",
581
- "query_params": {
582
- "thread_and_message_id": {
583
- "thread_id": tid.toString(),
584
- "message_id": mid
585
- }
586
- }
587
- }
588
- })
589
- };
590
-
591
- defaultFuncs
592
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
593
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
594
- .then((resData) => {
595
- if (resData[resData.length - 1].error_results > 0) {
596
- throw resData[0].o0.errors;
597
- }
598
-
599
- if (resData[resData.length - 1].successful_results === 0) {
600
- throw { error: "forcedFetch: there was no successful_results", res: resData };
601
- }
602
-
603
- const fetchData = resData[0].o0.data.message;
604
-
605
- if (utils.getType(fetchData) == "Object") {
606
- log.info("forcedFetch", fetchData);
607
- switch (fetchData.__typename) {
608
- case "ThreadImageMessage":
609
- (!ctx.globalOptions.selfListenEvent && (fetchData.message_sender.id.toString() === ctx.i_userID || fetchData.message_sender.id.toString() === ctx.userID)) || !ctx.loggedIn ?
610
- undefined :
611
- (function () {
612
- globalCallback(null, {
613
- type: "event",
614
- threadID: utils.formatID(tid.toString()),
615
- messageID: fetchData.message_id,
616
- logMessageType: "log:thread-image",
617
- logMessageData: {
618
- attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
619
- width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
620
- height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
621
- url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
622
- },
623
- logMessageBody: fetchData.snippet,
624
- timestamp: fetchData.timestamp_precise,
625
- author: fetchData.message_sender.id
626
- });
627
- })();
628
- break;
629
- case "UserMessage":
630
- log.info("ff-Return", {
631
- type: "message",
632
- senderID: utils.formatID(fetchData.message_sender.id),
633
- body: fetchData.message.text || "",
634
- threadID: utils.formatID(tid.toString()),
635
- messageID: fetchData.message_id,
636
- attachments: [{
637
- type: "share",
638
- ID: fetchData.extensible_attachment.legacy_attachment_id,
639
- url: fetchData.extensible_attachment.story_attachment.url,
640
-
641
- title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
642
- description: fetchData.extensible_attachment.story_attachment.description.text,
643
- source: fetchData.extensible_attachment.story_attachment.source,
644
-
645
- image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
646
- width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
647
- height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
648
- playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
649
- duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
650
-
651
- subattachments: fetchData.extensible_attachment.subattachments,
652
- properties: fetchData.extensible_attachment.story_attachment.properties
653
- }],
654
- mentions: {},
655
- timestamp: parseInt(fetchData.timestamp_precise),
656
- participantIDs: (fetchData.participants || (fetchData.messageMetadata ? fetchData.messageMetadata.cid ? fetchData.messageMetadata.cid.canonicalParticipantFbids : fetchData.messageMetadata.participantIds : []) || []),
657
- isGroup: (fetchData.message_sender.id != tid.toString())
658
- });
659
- globalCallback(null, {
660
- type: "message",
661
- senderID: utils.formatID(fetchData.message_sender.id),
662
- body: fetchData.message.text || "",
663
- threadID: utils.formatID(tid.toString()),
664
- messageID: fetchData.message_id,
665
- attachments: [{
666
- type: "share",
667
- ID: fetchData.extensible_attachment.legacy_attachment_id,
668
- url: fetchData.extensible_attachment.story_attachment.url,
669
-
670
- title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
671
- description: fetchData.extensible_attachment.story_attachment.description.text,
672
- source: fetchData.extensible_attachment.story_attachment.source,
673
-
674
- image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
675
- width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
676
- height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
677
- playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
678
- duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
679
-
680
- subattachments: fetchData.extensible_attachment.subattachments,
681
- properties: fetchData.extensible_attachment.story_attachment.properties
682
- }],
683
- mentions: {},
684
- timestamp: parseInt(fetchData.timestamp_precise),
685
- participantIDs: (fetchData.participants || (fetchData.messageMetadata ? fetchData.messageMetadata.cid ? fetchData.messageMetadata.cid.canonicalParticipantFbids : fetchData.messageMetadata.participantIds : []) || []),
686
- isGroup: (fetchData.message_sender.id != tid.toString())
687
- });
688
- }
689
- } else {
690
- log.error("forcedFetch", fetchData);
691
- }
692
- })
693
- .catch((err) => {
694
- log.error("forcedFetch", err);
695
- });
696
- }
697
- break;
698
- case "ThreadName":
699
- case "ParticipantsAddedToGroupThread":
700
- case "ParticipantLeftGroupThread":
701
- case "ApprovalQueue":
702
- var formattedEvent;
703
- try {
704
- formattedEvent = utils.formatDeltaEvent(v.delta);
705
- } catch (err) {
706
- return globalCallback({
707
- error: "Problem parsing message object. Please open an issue at https://github.com/ntkhang03/fb-chat-api/issues.",
708
- detail: err,
709
- res: v.delta,
710
- type: "parse_error"
711
- });
712
- }
713
- return (!ctx.globalOptions.selfListenEvent && (formattedEvent.author.toString() === ctx.i_userID || formattedEvent.author.toString() === ctx.userID)) || !ctx.loggedIn ?
714
- undefined :
715
- (function () { globalCallback(null, formattedEvent); })();
716
- }
251
+ if (v.delta.class == "NewMessage") {
252
+ //Not tested for pages
253
+ if (ctx.globalOptions.pageID &&
254
+ ctx.globalOptions.pageID != v.queue
255
+ )
256
+ return;
257
+
258
+ (function resolveAttachmentUrl(i) {
259
+ if (i == (v.delta.attachments || []).length) {
260
+ let fmtMsg;
261
+ try {
262
+ fmtMsg = utils.formatDeltaMessage(v);
263
+ } catch (err) {
264
+ return globalCallback({
265
+ error: "Problem parsing message object. Please open an issue at https://github.com/ntkhang03/fb-chat-api/issues.",
266
+ detail: err,
267
+ res: v,
268
+ type: "parse_error"
269
+ });
270
+ }
271
+ if (fmtMsg) {
272
+ if (ctx.globalOptions.autoMarkDelivery) {
273
+ markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
274
+ }
275
+ }
276
+ return !ctx.globalOptions.selfListen &&
277
+ (fmtMsg.senderID === ctx.i_userID || fmtMsg.senderID === ctx.userID) ?
278
+ undefined :
279
+ (function () { globalCallback(null, fmtMsg); })();
280
+ } else {
281
+ if (v.delta.attachments[i].mercury.attach_type == "photo") {
282
+ api.resolvePhotoUrl(
283
+ v.delta.attachments[i].fbid,
284
+ (err, url) => {
285
+ if (!err)
286
+ v.delta.attachments[
287
+ i
288
+ ].mercury.metadata.url = url;
289
+ return resolveAttachmentUrl(i + 1);
290
+ }
291
+ );
292
+ } else {
293
+ return resolveAttachmentUrl(i + 1);
294
+ }
295
+ }
296
+ })(0);
297
+ }
298
+
299
+ if (v.delta.class == "ClientPayload") {
300
+ const clientPayload = utils.decodeClientPayload(
301
+ v.delta.payload
302
+ );
303
+
304
+ if (clientPayload && clientPayload.deltas) {
305
+ for (const i in clientPayload.deltas) {
306
+ const delta = clientPayload.deltas[i];
307
+ if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
308
+ (function () {
309
+ globalCallback(null, {
310
+ type: "message_reaction",
311
+ threadID: (delta.deltaMessageReaction.threadKey
312
+ .threadFbId ?
313
+ delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey
314
+ .otherUserFbId).toString(),
315
+ messageID: delta.deltaMessageReaction.messageId,
316
+ reaction: delta.deltaMessageReaction.reaction,
317
+ senderID: delta.deltaMessageReaction.senderId == 0 ? delta.deltaMessageReaction.userId.toString() : delta.deltaMessageReaction.senderId.toString(),
318
+ userID: (delta.deltaMessageReaction.userId || delta.deltaMessageReaction.senderId).toString()
319
+ });
320
+ })();
321
+ } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
322
+ (function () {
323
+ globalCallback(null, {
324
+ type: "message_unsend",
325
+ threadID: (delta.deltaRecallMessageData.threadKey.threadFbId ?
326
+ delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey
327
+ .otherUserFbId).toString(),
328
+ messageID: delta.deltaRecallMessageData.messageID,
329
+ senderID: delta.deltaRecallMessageData.senderID.toString(),
330
+ deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
331
+ timestamp: delta.deltaRecallMessageData.timestamp
332
+ });
333
+ })();
334
+ } else if (delta.deltaRemoveMessage && !!ctx.globalOptions.listenEvents) {
335
+ (function () {
336
+ globalCallback(null, {
337
+ type: "message_self_delete",
338
+ threadID: (delta.deltaRemoveMessage.threadKey.threadFbId ?
339
+ delta.deltaRemoveMessage.threadKey.threadFbId : delta.deltaRemoveMessage.threadKey
340
+ .otherUserFbId).toString(),
341
+ messageID: delta.deltaRemoveMessage.messageIds.length == 1 ? delta.deltaRemoveMessage.messageIds[0] : delta.deltaRemoveMessage.messageIds,
342
+ senderID: api.getCurrentUserID(),
343
+ deletionTimestamp: delta.deltaRemoveMessage.deletionTimestamp,
344
+ timestamp: delta.deltaRemoveMessage.timestamp
345
+ });
346
+ })();
347
+ }
348
+ else if (delta.deltaMessageReply) {
349
+ //Mention block - #1
350
+ let mdata =
351
+ delta.deltaMessageReply.message === undefined ? [] :
352
+ delta.deltaMessageReply.message.data === undefined ? [] :
353
+ delta.deltaMessageReply.message.data.prng === undefined ? [] :
354
+ JSON.parse(delta.deltaMessageReply.message.data.prng);
355
+ let m_id = mdata.map(u => u.i);
356
+ let m_offset = mdata.map(u => u.o);
357
+ let m_length = mdata.map(u => u.l);
358
+
359
+ const mentions = {};
360
+
361
+ for (let i = 0; i < m_id.length; i++) {
362
+ mentions[m_id[i]] = (delta.deltaMessageReply.message.body || "").substring(
363
+ m_offset[i],
364
+ m_offset[i] + m_length[i]
365
+ );
366
+ }
367
+ //Mention block - 1#
368
+ const callbackToReturn = {
369
+ type: "message_reply",
370
+ threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ?
371
+ delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey
372
+ .otherUserFbId).toString(),
373
+ messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
374
+ senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId.toString(),
375
+ attachments: (delta.deltaMessageReply.message.attachments || []).map(function (att) {
376
+ const mercury = JSON.parse(att.mercuryJSON);
377
+ Object.assign(att, mercury);
378
+ return att;
379
+ }).map(att => {
380
+ let x;
381
+ try {
382
+ x = utils._formatAttachment(att);
383
+ } catch (ex) {
384
+ x = att;
385
+ x.error = ex;
386
+ x.type = "unknown";
387
+ }
388
+ return x;
389
+ }),
390
+ body: delta.deltaMessageReply.message.body || "",
391
+ isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
392
+ mentions: mentions,
393
+ timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
394
+ participantIDs: (delta.deltaMessageReply.message.messageMetadata.cid.canonicalParticipantFbids || delta.deltaMessageReply.message.participants || []).map(e => e.toString())
395
+ };
396
+
397
+ if (delta.deltaMessageReply.repliedToMessage) {
398
+ //Mention block - #2
399
+ mdata =
400
+ delta.deltaMessageReply.repliedToMessage === undefined ? [] :
401
+ delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
402
+ delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
403
+ JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
404
+ m_id = mdata.map(u => u.i);
405
+ m_offset = mdata.map(u => u.o);
406
+ m_length = mdata.map(u => u.l);
407
+
408
+ const rmentions = {};
409
+
410
+ for (let i = 0; i < m_id.length; i++) {
411
+ rmentions[m_id[i]] = (delta.deltaMessageReply.repliedToMessage.body || "").substring(
412
+ m_offset[i],
413
+ m_offset[i] + m_length[i]
414
+ );
415
+ }
416
+ //Mention block - 2#
417
+ callbackToReturn.messageReply = {
418
+ threadID: (delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ?
419
+ delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey
420
+ .otherUserFbId).toString(),
421
+ messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
422
+ senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
423
+ attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function (att) {
424
+ const mercury = JSON.parse(att.mercuryJSON);
425
+ Object.assign(att, mercury);
426
+ return att;
427
+ }).map(att => {
428
+ let x;
429
+ try {
430
+ x = utils._formatAttachment(att);
431
+ } catch (ex) {
432
+ x = att;
433
+ x.error = ex;
434
+ x.type = "unknown";
435
+ }
436
+ return x;
437
+ }),
438
+ body: delta.deltaMessageReply.repliedToMessage.body || "",
439
+ isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
440
+ mentions: rmentions,
441
+ timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp
442
+ };
443
+ } else if (delta.deltaMessageReply.replyToMessageId) {
444
+ return defaultFuncs
445
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
446
+ "av": ctx.globalOptions.pageID,
447
+ "queries": JSON.stringify({
448
+ "o0": {
449
+ //Using the same doc_id as forcedFetch
450
+ "doc_id": "2848441488556444",
451
+ "query_params": {
452
+ "thread_and_message_id": {
453
+ "thread_id": callbackToReturn.threadID,
454
+ "message_id": delta.deltaMessageReply.replyToMessageId.id
455
+ }
456
+ }
457
+ }
458
+ })
459
+ })
460
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
461
+ .then((resData) => {
462
+ if (resData[resData.length - 1].error_results > 0) {
463
+ throw resData[0].o0.errors;
464
+ }
465
+
466
+ if (resData[resData.length - 1].successful_results === 0) {
467
+ throw { error: "forcedFetch: there was no successful_results", res: resData };
468
+ }
469
+
470
+ const fetchData = resData[0].o0.data.message;
471
+
472
+ const mobj = {};
473
+ for (const n in fetchData.message.ranges) {
474
+ mobj[fetchData.message.ranges[n].entity.id] = (fetchData.message.text || "").substr(fetchData.message.ranges[n].offset, fetchData.message.ranges[n].length);
475
+ }
476
+
477
+ callbackToReturn.messageReply = {
478
+ threadID: callbackToReturn.threadID,
479
+ messageID: fetchData.message_id,
480
+ senderID: fetchData.message_sender.id.toString(),
481
+ attachments: fetchData.message.blob_attachment.map(att => {
482
+ let x;
483
+ try {
484
+ x = utils._formatAttachment({
485
+ blob_attachment: att
486
+ });
487
+ } catch (ex) {
488
+ x = att;
489
+ x.error = ex;
490
+ x.type = "unknown";
491
+ }
492
+ return x;
493
+ }),
494
+ body: fetchData.message.text || "",
495
+ isGroup: callbackToReturn.isGroup,
496
+ mentions: mobj,
497
+ timestamp: parseInt(fetchData.timestamp_precise)
498
+ };
499
+ })
500
+ .catch((err) => {
501
+ log.error("forcedFetch", err);
502
+ })
503
+ .finally(function () {
504
+ if (ctx.globalOptions.autoMarkDelivery) {
505
+ markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
506
+ }
507
+ !ctx.globalOptions.selfListen &&
508
+ (callbackToReturn.senderID === ctx.i_userID || callbackToReturn.senderID === ctx.userID) ?
509
+ undefined :
510
+ (function () { globalCallback(null, callbackToReturn); })();
511
+ });
512
+ } else {
513
+ callbackToReturn.delta = delta;
514
+ }
515
+
516
+ if (ctx.globalOptions.autoMarkDelivery) {
517
+ markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
518
+ }
519
+
520
+ return !ctx.globalOptions.selfListen &&
521
+ (callbackToReturn.senderID === ctx.i_userID || callbackToReturn.senderID === ctx.userID) ?
522
+ undefined :
523
+ (function () { globalCallback(null, callbackToReturn); })();
524
+ }
525
+ }
526
+ return;
527
+ }
528
+ }
529
+
530
+ if (v.delta.class !== "NewMessage" &&
531
+ !ctx.globalOptions.listenEvents
532
+ )
533
+ return;
534
+
535
+ switch (v.delta.class) {
536
+ case "ReadReceipt":
537
+ var fmtMsg;
538
+ try {
539
+ fmtMsg = utils.formatDeltaReadReceipt(v.delta);
540
+ }
541
+ catch (err) {
542
+ return globalCallback({
543
+ error: "Problem parsing message object. Please open an issue at https://github.com/ntkhang03/fb-chat-api/issues.",
544
+ detail: err,
545
+ res: v.delta,
546
+ type: "parse_error"
547
+ });
548
+ }
549
+ return (function () { globalCallback(null, fmtMsg); })();
550
+ case "AdminTextMessage":
551
+ switch (v.delta.type) {
552
+ case "change_thread_theme":
553
+ case "change_thread_nickname":
554
+ case "change_thread_icon":
555
+ case "change_thread_admins":
556
+ case "group_poll":
557
+ case "joinable_group_link_mode_change":
558
+ case "magic_words":
559
+ case "change_thread_approval_mode":
560
+ case "messenger_call_log":
561
+ case "participant_joined_group_call":
562
+ var fmtMsg;
563
+ try {
564
+ fmtMsg = utils.formatDeltaEvent(v.delta);
565
+ }
566
+ catch (err) {
567
+ return globalCallback({
568
+ error: "Problem parsing message object. Please open an issue at https://github.com/ntkhang03/fb-chat-api/issues.",
569
+ detail: err,
570
+ res: v.delta,
571
+ type: "parse_error"
572
+ });
573
+ }
574
+ return (function () { globalCallback(null, fmtMsg); })();
575
+ default:
576
+ return;
577
+ }
578
+ //For group images
579
+ case "ForcedFetch":
580
+ if (!v.delta.threadKey) return;
581
+ var mid = v.delta.messageId;
582
+ var tid = v.delta.threadKey.threadFbId;
583
+ if (mid && tid) {
584
+ const form = {
585
+ "av": ctx.globalOptions.pageID,
586
+ "queries": JSON.stringify({
587
+ "o0": {
588
+ //This doc_id is valid as of March 25, 2020
589
+ "doc_id": "2848441488556444",
590
+ "query_params": {
591
+ "thread_and_message_id": {
592
+ "thread_id": tid.toString(),
593
+ "message_id": mid
594
+ }
595
+ }
596
+ }
597
+ })
598
+ };
599
+
600
+ defaultFuncs
601
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
602
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
603
+ .then((resData) => {
604
+ if (resData[resData.length - 1].error_results > 0) {
605
+ throw resData[0].o0.errors;
606
+ }
607
+
608
+ if (resData[resData.length - 1].successful_results === 0) {
609
+ throw { error: "forcedFetch: there was no successful_results", res: resData };
610
+ }
611
+
612
+ const fetchData = resData[0].o0.data.message;
613
+
614
+ if (utils.getType(fetchData) == "Object") {
615
+ log.info("forcedFetch", fetchData);
616
+ switch (fetchData.__typename) {
617
+ case "ThreadImageMessage":
618
+ (!ctx.globalOptions.selfListenEvent && (fetchData.message_sender.id.toString() === ctx.i_userID || fetchData.message_sender.id.toString() === ctx.userID)) || !ctx.loggedIn ?
619
+ undefined :
620
+ (function () {
621
+ globalCallback(null, {
622
+ type: "event",
623
+ threadID: utils.formatID(tid.toString()),
624
+ messageID: fetchData.message_id,
625
+ logMessageType: "log:thread-image",
626
+ logMessageData: {
627
+ attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
628
+ width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
629
+ height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
630
+ url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
631
+ },
632
+ logMessageBody: fetchData.snippet,
633
+ timestamp: fetchData.timestamp_precise,
634
+ author: fetchData.message_sender.id
635
+ });
636
+ })();
637
+ break;
638
+ case "UserMessage":
639
+ log.info("ff-Return", {
640
+ type: "message",
641
+ senderID: utils.formatID(fetchData.message_sender.id),
642
+ body: fetchData.message.text || "",
643
+ threadID: utils.formatID(tid.toString()),
644
+ messageID: fetchData.message_id,
645
+ attachments: [{
646
+ type: "share",
647
+ ID: fetchData.extensible_attachment.legacy_attachment_id,
648
+ url: fetchData.extensible_attachment.story_attachment.url,
649
+
650
+ title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
651
+ description: fetchData.extensible_attachment.story_attachment.description.text,
652
+ source: fetchData.extensible_attachment.story_attachment.source,
653
+
654
+ image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
655
+ width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
656
+ height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
657
+ playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
658
+ duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
659
+
660
+ subattachments: fetchData.extensible_attachment.subattachments,
661
+ properties: fetchData.extensible_attachment.story_attachment.properties
662
+ }],
663
+ mentions: {},
664
+ timestamp: parseInt(fetchData.timestamp_precise),
665
+ participantIDs: (fetchData.participants || (fetchData.messageMetadata ? fetchData.messageMetadata.cid ? fetchData.messageMetadata.cid.canonicalParticipantFbids : fetchData.messageMetadata.participantIds : []) || []),
666
+ isGroup: (fetchData.message_sender.id != tid.toString())
667
+ });
668
+ globalCallback(null, {
669
+ type: "message",
670
+ senderID: utils.formatID(fetchData.message_sender.id),
671
+ body: fetchData.message.text || "",
672
+ threadID: utils.formatID(tid.toString()),
673
+ messageID: fetchData.message_id,
674
+ attachments: [{
675
+ type: "share",
676
+ ID: fetchData.extensible_attachment.legacy_attachment_id,
677
+ url: fetchData.extensible_attachment.story_attachment.url,
678
+
679
+ title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
680
+ description: fetchData.extensible_attachment.story_attachment.description.text,
681
+ source: fetchData.extensible_attachment.story_attachment.source,
682
+
683
+ image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
684
+ width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
685
+ height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
686
+ playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
687
+ duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
688
+
689
+ subattachments: fetchData.extensible_attachment.subattachments,
690
+ properties: fetchData.extensible_attachment.story_attachment.properties
691
+ }],
692
+ mentions: {},
693
+ timestamp: parseInt(fetchData.timestamp_precise),
694
+ participantIDs: (fetchData.participants || (fetchData.messageMetadata ? fetchData.messageMetadata.cid ? fetchData.messageMetadata.cid.canonicalParticipantFbids : fetchData.messageMetadata.participantIds : []) || []),
695
+ isGroup: (fetchData.message_sender.id != tid.toString())
696
+ });
697
+ }
698
+ } else {
699
+ log.error("forcedFetch", fetchData);
700
+ }
701
+ })
702
+ .catch((err) => {
703
+ log.error("forcedFetch", err);
704
+ });
705
+ }
706
+ break;
707
+ case "ThreadName":
708
+ case "ParticipantsAddedToGroupThread":
709
+ case "ParticipantLeftGroupThread":
710
+ case "ApprovalQueue":
711
+ var formattedEvent;
712
+ try {
713
+ formattedEvent = utils.formatDeltaEvent(v.delta);
714
+ } catch (err) {
715
+ return globalCallback({
716
+ error: "Problem parsing message object. Please open an issue at https://github.com/ntkhang03/fb-chat-api/issues.",
717
+ detail: err,
718
+ res: v.delta,
719
+ type: "parse_error"
720
+ });
721
+ }
722
+ return (!ctx.globalOptions.selfListenEvent && (formattedEvent.author.toString() === ctx.i_userID || formattedEvent.author.toString() === ctx.userID)) || !ctx.loggedIn ?
723
+ undefined :
724
+ (function () { globalCallback(null, formattedEvent); })();
725
+ }
717
726
  }
718
727
 
719
728
  function markDelivery(ctx, api, threadID, messageID) {
720
- if (threadID && messageID) {
721
- api.markAsDelivered(threadID, messageID, (err) => {
722
- if (err) {
723
- log.error("markAsDelivered", err);
724
- } else {
725
- if (ctx.globalOptions.autoMarkRead) {
726
- api.markAsRead(threadID, (err) => {
727
- if (err) {
728
- log.error("markAsDelivered", err);
729
- }
730
- });
731
- }
732
- }
733
- });
734
- }
729
+ if (threadID && messageID) {
730
+ api.markAsDelivered(threadID, messageID, (err) => {
731
+ if (err) {
732
+ log.error("markAsDelivered", err);
733
+ } else {
734
+ if (ctx.globalOptions.autoMarkRead) {
735
+ api.markAsRead(threadID, (err) => {
736
+ if (err) {
737
+ log.error("markAsDelivered", err);
738
+ }
739
+ });
740
+ }
741
+ }
742
+ });
743
+ }
735
744
  }
736
745
 
737
746
  function getSeqId(defaultFuncs, api, ctx, globalCallback) {
738
- const jar = ctx.jar;
739
- utils
740
- .get('https://www.facebook.com/', jar, null, ctx.globalOptions, { noRef: true })
741
- .then(utils.saveCookies(jar))
742
- .then(function (resData) {
743
- const html = resData.body;
744
- const oldFBMQTTMatch = html.match(/irisSeqID:"(.+?)",appID:219994525426954,endpoint:"(.+?)"/);
745
- let mqttEndpoint = null;
746
- let region = null;
747
- let irisSeqID = null;
748
- let noMqttData = null;
749
-
750
- if (oldFBMQTTMatch) {
751
- irisSeqID = oldFBMQTTMatch[1];
752
- mqttEndpoint = oldFBMQTTMatch[2];
753
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
754
- log.info("login", `Got this account's message region: ${region}`);
755
- } else {
756
- const newFBMQTTMatch = html.match(/{"app_id":"219994525426954","endpoint":"(.+?)","iris_seq_id":"(.+?)"}/);
757
- if (newFBMQTTMatch) {
758
- irisSeqID = newFBMQTTMatch[2];
759
- mqttEndpoint = newFBMQTTMatch[1].replace(/\\\//g, "/");
760
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
761
- log.info("login", `Got this account's message region: ${region}`);
762
- } else {
763
- const legacyFBMQTTMatch = html.match(/(\["MqttWebConfig",\[\],{fbid:")(.+?)(",appID:219994525426954,endpoint:")(.+?)(",pollingEndpoint:")(.+?)(3790])/);
764
- if (legacyFBMQTTMatch) {
765
- mqttEndpoint = legacyFBMQTTMatch[4];
766
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
767
- log.warn("login", `Cannot get sequence ID with new RegExp. Fallback to old RegExp (without seqID)...`);
768
- log.info("login", `Got this account's message region: ${region}`);
769
- log.info("login", `[Unused] Polling endpoint: ${legacyFBMQTTMatch[6]}`);
770
- } else {
771
- log.warn("login", "Cannot get MQTT region & sequence ID.");
772
- noMqttData = html;
773
- }
774
- }
775
- }
776
-
777
- ctx.lastSeqId = irisSeqID;
778
- ctx.mqttEndpoint = mqttEndpoint;
779
- ctx.region = region;
780
- if (noMqttData) {
781
- api["htmlData"] = noMqttData;
782
- }
783
-
784
- listenMqtt(defaultFuncs, api, ctx, globalCallback);
785
- })
786
- .catch(function (err) {
787
- log.error("getSeqId", err);
788
- });
747
+ const jar = ctx.jar;
748
+ utils
749
+ .get('https://www.facebook.com/', jar, null, ctx.globalOptions, { noRef: true })
750
+ .then(utils.saveCookies(jar))
751
+ .then(function (resData) {
752
+ const html = resData.body;
753
+ const oldFBMQTTMatch = html.match(/irisSeqID:"(.+?)",appID:219994525426954,endpoint:"(.+?)"/);
754
+ let mqttEndpoint = null;
755
+ let region = null;
756
+ let irisSeqID = null;
757
+ let noMqttData = null;
758
+
759
+ if (oldFBMQTTMatch) {
760
+ irisSeqID = oldFBMQTTMatch[1];
761
+ mqttEndpoint = oldFBMQTTMatch[2];
762
+ region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
763
+ log.info("login", `Got this account's message region: ${region}`);
764
+ } else {
765
+ const newFBMQTTMatch = html.match(/{"app_id":"219994525426954","endpoint":"(.+?)","iris_seq_id":"(.+?)"}/);
766
+ if (newFBMQTTMatch) {
767
+ irisSeqID = newFBMQTTMatch[2];
768
+ mqttEndpoint = newFBMQTTMatch[1].replace(/\\\//g, "/");
769
+ region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
770
+ log.info("login", `Got this account's message region: ${region}`);
771
+ } else {
772
+ const legacyFBMQTTMatch = html.match(/(\["MqttWebConfig",\[\],{fbid:")(.+?)(",appID:219994525426954,endpoint:")(.+?)(",pollingEndpoint:")(.+?)(3790])/);
773
+ if (legacyFBMQTTMatch) {
774
+ mqttEndpoint = legacyFBMQTTMatch[4];
775
+ region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
776
+ log.warn("login", `Cannot get sequence ID with new RegExp. Fallback to old RegExp (without seqID)...`);
777
+ log.info("login", `Got this account's message region: ${region}`);
778
+ log.info("login", `[Unused] Polling endpoint: ${legacyFBMQTTMatch[6]}`);
779
+ } else {
780
+ log.warn("login", "Cannot get MQTT region & sequence ID.");
781
+ noMqttData = html;
782
+ }
783
+ }
784
+ }
785
+
786
+ ctx.lastSeqId = irisSeqID;
787
+ ctx.mqttEndpoint = mqttEndpoint;
788
+ ctx.region = region;
789
+ if (noMqttData) {
790
+ api["htmlData"] = noMqttData;
791
+ }
792
+
793
+ listenMqtt(defaultFuncs, api, ctx, globalCallback);
794
+ })
795
+ .catch(function (err) {
796
+ log.error("getSeqId", err);
797
+ });
789
798
  }
790
799
 
791
800
  module.exports = function (defaultFuncs, api, ctx) {
792
- let globalCallback = identity;
793
-
794
- return function (callback) {
795
- class MessageEmitter extends EventEmitter {
796
- stopListening(callback) {
797
-
798
- callback = callback || (() => { });
799
- globalCallback = identity;
800
- if (ctx.mqttClient) {
801
- ctx.mqttClient.unsubscribe("/webrtc");
802
- ctx.mqttClient.unsubscribe("/rtc_multi");
803
- ctx.mqttClient.unsubscribe("/onevc");
804
- ctx.mqttClient.publish("/browser_close", "{}");
805
- ctx.mqttClient.end(false, function (...data) {
806
- callback(data);
807
- ctx.mqttClient = undefined;
808
- });
809
- }
810
- }
811
-
812
- async stopListeningAsync() {
813
- return new Promise((resolve) => {
814
- this.stopListening(resolve);
815
- });
816
- }
817
- }
818
-
819
- const msgEmitter = new MessageEmitter();
820
- globalCallback = (callback || function (error, message) {
821
- if (error) {
822
- return msgEmitter.emit("error", error);
823
- }
824
- msgEmitter.emit("message", message);
825
- });
826
-
827
- // Reset some stuff
828
- if (!ctx.firstListen)
829
- ctx.lastSeqId = null;
830
- ctx.syncToken = undefined;
831
- ctx.t_mqttCalled = false;
832
-
833
- if (!ctx.firstListen || !ctx.lastSeqId) {
834
- getSeqId(defaultFuncs, api, ctx, globalCallback);
835
- } else {
836
- listenMqtt(defaultFuncs, api, ctx, globalCallback);
837
- }
838
-
839
- api.stopListening = msgEmitter.stopListening;
840
- api.stopListeningAsync = msgEmitter.stopListeningAsync;
841
- return msgEmitter;
842
- };
801
+ let globalCallback = identity;
802
+
803
+ return function (callback) {
804
+ class MessageEmitter extends EventEmitter {
805
+ stopListening(callback) {
806
+
807
+ callback = callback || (() => { });
808
+ globalCallback = identity;
809
+ if (ctx.mqttClient) {
810
+ ctx.mqttClient.unsubscribe("/webrtc");
811
+ ctx.mqttClient.unsubscribe("/rtc_multi");
812
+ ctx.mqttClient.unsubscribe("/onevc");
813
+ ctx.mqttClient.publish("/browser_close", "{}");
814
+ ctx.mqttClient.end(false, function (...data) {
815
+ callback(data);
816
+ ctx.mqttClient = undefined;
817
+ });
818
+ }
819
+ }
820
+
821
+ async stopListeningAsync() {
822
+ return new Promise((resolve) => {
823
+ this.stopListening(resolve);
824
+ });
825
+ }
826
+ }
827
+
828
+ const msgEmitter = new MessageEmitter();
829
+ globalCallback = (callback || function (error, message) {
830
+ if (error) {
831
+ return msgEmitter.emit("error", error);
832
+ }
833
+ msgEmitter.emit("message", message);
834
+ });
835
+
836
+ // Reset some stuff
837
+ if (!ctx.firstListen)
838
+ ctx.lastSeqId = null;
839
+ ctx.syncToken = undefined;
840
+ ctx.t_mqttCalled = false;
841
+
842
+ if (!ctx.firstListen || !ctx.lastSeqId) {
843
+ getSeqId(defaultFuncs, api, ctx, globalCallback);
844
+ } else {
845
+ listenMqtt(defaultFuncs, api, ctx, globalCallback);
846
+ }
847
+
848
+ api.stopListening = msgEmitter.stopListening;
849
+ api.stopListeningAsync = msgEmitter.stopListeningAsync;
850
+ return msgEmitter;
851
+ };
843
852
  };