alicezetion 1.1.2 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -1
  2. package/.cache/replit/nix/env.json +1 -1
  3. package/index.js +6 -7
  4. package/leiamnash/addExternalModule.js +0 -0
  5. package/leiamnash/addUserToGroup.js +0 -0
  6. package/leiamnash/changeAdminStatus.js +0 -0
  7. package/leiamnash/changeArchivedStatus.js +0 -0
  8. package/leiamnash/changeBio.js +0 -0
  9. package/leiamnash/changeBlockedStatus.js +0 -0
  10. package/leiamnash/changeGroupImage.js +0 -0
  11. package/leiamnash/changeNickname.js +0 -0
  12. package/leiamnash/changeThreadColor.js +0 -0
  13. package/leiamnash/changeThreadEmoji.js +0 -0
  14. package/leiamnash/chat.js +4 -0
  15. package/leiamnash/createNewGroup.js +0 -0
  16. package/leiamnash/createPoll.js +0 -0
  17. package/leiamnash/deleteMessage.js +0 -0
  18. package/leiamnash/deleteThread.js +0 -0
  19. package/leiamnash/forwardAttachment.js +0 -0
  20. package/leiamnash/getCurrentUserID.js +0 -0
  21. package/leiamnash/getEmojiUrl.js +0 -0
  22. package/leiamnash/getFriendsList.js +0 -0
  23. package/leiamnash/getThreadHistory.js +0 -0
  24. package/leiamnash/getThreadHistoryDeprecated.js +0 -0
  25. package/leiamnash/getThreadInfo.js +0 -0
  26. package/leiamnash/getThreadInfoDeprecated.js +0 -0
  27. package/leiamnash/getThreadList.js +0 -0
  28. package/leiamnash/getThreadListDeprecated.js +0 -0
  29. package/leiamnash/getThreadPictures.js +0 -0
  30. package/leiamnash/getUserID.js +0 -0
  31. package/leiamnash/getUserInfo.js +0 -0
  32. package/leiamnash/handleFriendRequest.js +0 -0
  33. package/leiamnash/handleMessageRequest.js +0 -0
  34. package/leiamnash/httpGet.js +0 -0
  35. package/leiamnash/httpPost.js +0 -0
  36. package/leiamnash/listenMqtt.js +656 -666
  37. package/leiamnash/logout.js +0 -0
  38. package/leiamnash/markAsDelivered.js +0 -0
  39. package/leiamnash/markAsRead.js +0 -0
  40. package/leiamnash/markAsReadAll.js +0 -0
  41. package/leiamnash/markAsSeen.js +0 -0
  42. package/leiamnash/muteThread.js +0 -0
  43. package/leiamnash/removeUserFromGroup.js +0 -0
  44. package/leiamnash/resolvePhotoUrl.js +0 -0
  45. package/leiamnash/searchForThread.js +0 -0
  46. package/leiamnash/sendTypingIndicator.js +0 -0
  47. package/leiamnash/setMessageReaction.js +0 -0
  48. package/leiamnash/setPostReaction.js +0 -0
  49. package/leiamnash/setTitle.js +0 -0
  50. package/leiamnash/threadColors.js +0 -0
  51. package/leiamnash/unfriend.js +0 -0
  52. package/leiamnash/unsendMessage.js +0 -0
  53. package/package.json +7 -7
  54. package/replit.nix +3 -1
  55. package/utils.js +0 -0
@@ -6,682 +6,672 @@ var mqtt = require('mqtt');
6
6
  var websocket = require('websocket-stream');
7
7
  var HttpsProxyAgent = require('https-proxy-agent');
8
8
  const EventEmitter = require('events');
9
- var identity = function () { };
9
+
10
+ var identity = function() {};
10
11
  var form = {};
11
- var getSeqID = function () { };
12
-
13
- var topics = ["/legacy_web",
14
- "/webrtc",
15
- "/rtc_multi",
16
- "/onevc",
17
- "/br_sr",
18
- "/sr_res",
19
- "/t_ms",
20
- "/thread_typing",
21
- "/orca_typing_notifications",
22
- "/notify_disconnect",
23
- "/orca_presence",
24
- "/inbox",
25
- "/mercury",
26
- "/messaging_events",
27
- "/orca_message_notifications",
28
- "/pp",
29
- "/webrtc_response"
12
+ var getSeqID = function() {};
13
+
14
+ var topics = [
15
+ "/legacy_web",
16
+ "/webrtc",
17
+ "/rtc_multi",
18
+ "/onevc",
19
+ "/br_sr", //Notification
20
+ //Need to publish /br_sr right after this
21
+ "/sr_res",
22
+ "/t_ms",
23
+ "/thread_typing",
24
+ "/orca_typing_notifications",
25
+ "/notify_disconnect",
26
+ //Need to publish /messenger_sync_create_queue right after this
27
+ "/orca_presence",
28
+ //Will receive /sr_res right here.
29
+
30
+ "/inbox",
31
+ "/mercury",
32
+ "/messaging_events",
33
+ "/orca_message_notifications",
34
+ "/pp",
35
+ "/webrtc_response",
30
36
  ];
31
37
 
32
- /* [ Noti ? ]
33
- ! "/br_sr", //Notification
34
- * => Need to publish /br_sr right after this
35
-
36
- ! "/notify_disconnect",
37
- * => Need to publish /messenger_sync_create_queue right after this
38
-
39
- ! "/orca_presence",
40
- * => Will receive /sr_res right here.
41
- */
42
-
43
38
  function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
44
- //Don't really know what this does but I think it's for the active state?
45
- //TODO: Move to ctx when implemented
46
- var chatOn = ctx.globalOptions.online;
47
- var foreground = false;
48
-
49
- var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
50
- var username = {u: ctx.userID,s: sessionID,chat_on: chatOn,fg: foreground,d: utils.getGUID(),ct: "websocket",aid: "219994525426954", mqtt_sid: "",cp: 3,ecp: 10,st: [],pm: [],dc: "",no_auto_fg: true,gas: null,pack: []};
51
- var cookies = ctx.jar.getCookies('https://www.facebook.com').join("; ");
52
-
53
- var host;
54
- if (ctx.mqttEndpoint) host = `${ctx.mqttEndpoint}&sid=${sessionID}`;
55
- else if (ctx.region) host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}`;
56
- else host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}`;
57
-
58
- var options = {
59
- clientId: "mqttwsclient",
60
- protocolId: 'MQIsdp',
61
- protocolVersion: 3,
62
- username: JSON.stringify(username),
63
- clean: true,
64
- wsOptions: {
65
- headers: {
66
- 'Cookie': cookies,
67
- 'Origin': 'https://www.facebook.com',
68
- 'User-Agent': (ctx.globalOptions.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36'),
69
- 'Referer': 'https://www.facebook.com/',
70
- 'Host': new URL(host).hostname //'edge-chat.facebook.com'
71
- },
72
- origin: 'https://www.facebook.com',
73
- protocolVersion: 13
74
- },
75
- keepalive: 10,
76
- reschedulePings: true,
77
- connectTimeout: 10000,
78
- reconnectPeriod: 1000
79
- };
80
-
81
- if (typeof ctx.globalOptions.proxy != "undefined") {
82
- var agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
83
- options.wsOptions.agent = agent;
84
- }
85
-
86
- ctx.mqttClient = new mqtt.Client(_ => websocket(host, options.wsOptions), options);
87
-
88
- var mqttClient = ctx.mqttClient;
89
- mqttClient.on('error', function (err) {
90
- log.error("listenMqtt", err);
91
- mqttClient.end();
92
- if (ctx.globalOptions.autoReconnect) getSeqID();
93
- else {
94
- globalCallback({
95
- type: "stop_listen",
96
- error: "Connection refused: Server unavailable"
97
- }, null);
98
- }
99
- });
100
-
101
- mqttClient.on('connect', function () {
102
- topics.forEach(topicsub => mqttClient.subscribe(topicsub));
103
-
104
- var topic;
105
- var queue = {
106
- sync_api_version: 11,
107
- max_deltas_able_to_process: 100,
108
- delta_batch_size: 500,
109
- encoding: "JSON",
110
- entity_fbid: ctx.userID,
111
- };
112
-
113
- if (ctx.syncToken) {
114
- topic = "/messenger_sync_get_diffs";
115
- queue.last_seq_id = ctx.lastSeqId;
116
- queue.sync_token = ctx.syncToken;
117
- } else {
118
- topic = "/messenger_sync_create_queue";
119
- queue.initial_titan_sequence_id = ctx.lastSeqId;
120
- queue.device_params = null;
121
- }
122
- mqttClient.publish(topic, JSON.stringify(queue), { qos: 1, retain: false });
123
-
124
- // set status online
125
- // fix by NTKhang
126
- mqttClient.publish("/foreground_state", JSON.stringify({"foreground": chatOn}), {qos: 1});
127
-
128
- var rTimeout = setTimeout(function () {
129
- mqttClient.end();
130
- getSeqID();
131
- }, 3000);
132
-
133
- ctx.tmsWait = function () {
134
- clearTimeout(rTimeout);
135
- ctx.globalOptions.emitReady ? globalCallback({type: "ready",error: null}) : '';
136
- delete ctx.tmsWait;
137
- };
138
- });
139
-
140
- mqttClient.on('message', function (topic, message, _packet) {
141
- const jsonMessage = JSON.parse(message.toString());
142
- if (topic === "/t_ms") {
143
- if (ctx.tmsWait && typeof ctx.tmsWait == "function") ctx.tmsWait();
144
-
145
- if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
146
- ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
147
- ctx.syncToken = jsonMessage.syncToken;
148
- }
149
-
150
- if (jsonMessage.lastIssuedSeqId) ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
151
- //If it contains more than 1 delta
152
- for (var i in jsonMessage.deltas) {
153
- var delta = jsonMessage.deltas[i];
154
- parseDelta(defaultFuncs, api, ctx, globalCallback, { "delta": delta });
155
- }
156
- } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
157
- var typ = {
158
- type: "typ",
159
- isTyping: !!jsonMessage.state,
160
- from: jsonMessage.sender_fbid.toString(),
161
- threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
162
- };
163
- (function () { globalCallback(null, typ); })();
164
- } else if (topic === "/orca_presence") {
165
- if (!ctx.globalOptions.updatePresence) {
166
- for (var i in jsonMessage.list) {
167
- var data = jsonMessage.list[i];
168
- var userID = data["u"];
169
-
170
- var presence = {
171
- type: "presence",
172
- userID: userID.toString(),
173
- //Convert to ms
174
- timestamp: data["l"] * 1000,
175
- statuses: data["p"]
176
- };
177
- (function () { globalCallback(null, presence); })();
178
- }
179
- }
180
- }
181
-
182
- });
183
-
184
- process.on('SIGINT', function () {
185
- process.kill(process.pid);
186
- });
187
-
188
- process.on('exit', (code) => {
189
-
190
- });
191
-
192
- mqttClient.on('close', function () {
193
-
194
- });
195
-
196
- mqttClient.on('disconnect',function () {
197
- process.exit(7378278);
198
- });
39
+ //Don't really know what this does but I think it's for the active state?
40
+ //TODO: Move to ctx when implemented
41
+ var chatOn = ctx.globalOptions.online;
42
+ var foreground = false;
43
+
44
+ var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
45
+ var username = {
46
+ u: ctx.userID,
47
+ s: sessionID,
48
+ chat_on: chatOn,
49
+ fg: foreground,
50
+ d: utils.getGUID(),
51
+ ct: "websocket",
52
+ //App id from facebook
53
+ aid: "219994525426954",
54
+ mqtt_sid: "",
55
+ cp: 3,
56
+ ecp: 10,
57
+ st: [],
58
+ pm: [],
59
+ dc: "",
60
+ no_auto_fg: true,
61
+ gas: null,
62
+ pack: []
63
+ };
64
+ var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
65
+
66
+ var host;
67
+ if (ctx.mqttEndpoint) host = `${ctx.mqttEndpoint}&sid=${sessionID}`;
68
+ else if (ctx.region) host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}`;
69
+ else host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}`;
70
+
71
+ var options = {
72
+ clientId: "mqttwsclient",
73
+ protocolId: 'MQIsdp',
74
+ protocolVersion: 3,
75
+ username: JSON.stringify(username),
76
+ clean: true,
77
+ wsOptions: {
78
+ headers: {
79
+ 'Cookie': cookies,
80
+ 'Origin': 'https://www.facebook.com',
81
+ 'User-Agent': ctx.globalOptions.userAgent,
82
+ 'Referer': 'https://www.facebook.com/',
83
+ 'Host': new URL(host).hostname //'edge-chat.facebook.com'
84
+ },
85
+ origin: 'https://www.facebook.com',
86
+ protocolVersion: 13
87
+ },
88
+ keepalive: 10,
89
+ reschedulePings: false
90
+ };
91
+
92
+ if (typeof ctx.globalOptions.proxy != "undefined") {
93
+ var agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
94
+ options.wsOptions.agent = agent;
95
+ }
96
+
97
+ ctx.mqttClient = new mqtt.Client(_ => websocket(host, options.wsOptions), options);
98
+
99
+ var mqttClient = ctx.mqttClient;
100
+
101
+ mqttClient.on('error', function(err) {
102
+ log.error("listenMqtt", "Connection refused: Server unavailable. Exiting...");
103
+ mqttClient.end();
104
+ process.exit();
105
+ if (ctx.globalOptions.autoReconnect) getSeqID();
106
+ else {
107
+ globalCallback({ type: "stop_listen", error: "Connection refused: Server unavailable" }, null);
108
+ }
109
+ });
110
+
111
+ mqttClient.on('connect', function() {
112
+ topics.forEach(topicsub => mqttClient.subscribe(topicsub));
113
+
114
+ var topic;
115
+ var queue = {
116
+ sync_api_version: 10,
117
+ max_deltas_able_to_process: 1000,
118
+ delta_batch_size: 500,
119
+ encoding: "JSON",
120
+ entity_fbid: ctx.userID,
121
+ };
122
+
123
+ if (ctx.syncToken) {
124
+ topic = "/messenger_sync_get_diffs";
125
+ queue.last_seq_id = ctx.lastSeqId;
126
+ queue.sync_token = ctx.syncToken;
127
+ } else {
128
+ topic = "/messenger_sync_create_queue";
129
+ queue.initial_titan_sequence_id = ctx.lastSeqId;
130
+ queue.device_params = null;
131
+ }
132
+
133
+ mqttClient.publish(topic, JSON.stringify(queue), { qos: 1, retain: false });
134
+ //onbot
135
+ mqttClient.publish("/foreground_state", JSON.stringify({"foreground": chatOn}), {qos: 1});
136
+
137
+ var rTimeout = setTimeout(function() {
138
+ mqttClient.end();
139
+ getSeqID();
140
+ }, 5000);
141
+
142
+ ctx.tmsWait = function() {
143
+ clearTimeout(rTimeout);
144
+ ctx.globalOptions.emitReady ? globalCallback({
145
+ type: "ready",
146
+ error: null
147
+ }) : "";
148
+ delete ctx.tmsWait;
149
+ };
150
+ });
151
+
152
+ mqttClient.on('message', function(topic, message, _packet) {
153
+ try {
154
+ var jsonMessage = JSON.parse(message);
155
+ } catch (ex) {
156
+ return log.error("listenMqtt", "SyntaxError: Unexpected token in JSON at position 0");
157
+ }
158
+ if (topic === "/t_ms") {
159
+ if (ctx.tmsWait && typeof ctx.tmsWait == "function") ctx.tmsWait();
160
+
161
+ if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
162
+ ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
163
+ ctx.syncToken = jsonMessage.syncToken;
164
+ }
165
+
166
+ if (jsonMessage.lastIssuedSeqId) ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
167
+
168
+ //If it contains more than 1 delta
169
+ for (var i in jsonMessage.deltas) {
170
+ var delta = jsonMessage.deltas[i];
171
+ parseDelta(defaultFuncs, api, ctx, globalCallback, { "delta": delta });
172
+ }
173
+ } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
174
+ var typ = {
175
+ type: "typ",
176
+ isTyping: !!jsonMessage.state,
177
+ from: jsonMessage.sender_fbid.toString(),
178
+ threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
179
+ };
180
+ (function() { globalCallback(null, typ); })();
181
+ } else if (topic === "/orca_presence") {
182
+ if (!ctx.globalOptions.updatePresence) {
183
+ for (var i in jsonMessage.list) {
184
+ var data = jsonMessage.list[i];
185
+ var userID = data["u"];
186
+
187
+ var presence = {
188
+ type: "presence",
189
+ userID: userID.toString(),
190
+ //Convert to ms
191
+ timestamp: data["l"] * 1000,
192
+ statuses: data["p"]
193
+ };
194
+ (function() { globalCallback(null, presence); })();
195
+ }
196
+ }
197
+ }
198
+
199
+ });
200
+
201
+ mqttClient.on('close', function() {
202
+ //(function () { globalCallback("Connection closed."); })();
203
+ // client.end();
204
+ });
199
205
  }
200
206
 
201
207
  function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
202
- if (v.delta.class == "NewMessage") {
203
- //Not tested for pages
204
- if (ctx.globalOptions.pageID && ctx.globalOptions.pageID != v.queue) return;
205
-
206
- (function resolveAttachmentUrl(i) {
207
- if (v.delta.attachments && (i == v.delta.attachments.length)) {
208
- var fmtMsg;
209
- try {
210
- fmtMsg = utils.formatDeltaMessage(v);
211
- } catch (err) {
212
- return globalCallback({
213
- error: "Problem parsing message object. Please open an issue at https://github.com/VangBanLaNhat/fca-unofficial/issues.",
214
- detail: err,
215
- res: v,
216
- type: "parse_error"
217
- });
218
- }
219
-
220
- if (fmtMsg)
221
- if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
222
-
223
- return !ctx.globalOptions.selfListen && fmtMsg.senderID === ctx.userID ? undefined : (function () { globalCallback(null, fmtMsg); })();
224
- } else {
225
- if (v.delta.attachments && (v.delta.attachments[i].mercury.attach_type == "photo")) {
226
- api.resolvePhotoUrl(v.delta.attachments[i].fbid, (err, url) => {
227
- if (!err) v.delta.attachments[i].mercury.metadata.url = url;
228
- return resolveAttachmentUrl(i + 1);
229
- });
230
- } else return resolveAttachmentUrl(i + 1);
231
- }
232
- })(0);
233
- }
234
-
235
- if (v.delta.class == "ClientPayload") {
236
- var clientPayload = utils.decodeClientPayload(v.delta.payload);
237
- if (clientPayload && clientPayload.deltas) {
238
- for (var i in clientPayload.deltas) {
239
- var delta = clientPayload.deltas[i];
240
- if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
241
- (function () {
242
- globalCallback(null, {
243
- type: "message_reaction",
244
- threadID: (delta.deltaMessageReaction.threadKey.threadFbId ? delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey.otherUserFbId).toString(),
245
- messageID: delta.deltaMessageReaction.messageId,
246
- reaction: delta.deltaMessageReaction.reaction,
247
- senderID: delta.deltaMessageReaction.senderId.toString(),
248
- userID: delta.deltaMessageReaction.userId.toString()
249
- });
250
- })();
251
- } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
252
- (function () {
253
- globalCallback(null, {
254
- type: "message_unsend",
255
- threadID: (delta.deltaRecallMessageData.threadKey.threadFbId ? delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey.otherUserFbId).toString(),
256
- messageID: delta.deltaRecallMessageData.messageID,
257
- senderID: delta.deltaRecallMessageData.senderID.toString(),
258
- deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
259
- timestamp: delta.deltaRecallMessageData.timestamp
260
- });
261
- })();
262
- } else if (delta.deltaMessageReply) {
263
- //Mention block - #1
264
- var mdata =
265
- delta.deltaMessageReply.message === undefined ? [] :
266
- delta.deltaMessageReply.message.data === undefined ? [] :
267
- delta.deltaMessageReply.message.data.prng === undefined ? [] :
268
- JSON.parse(delta.deltaMessageReply.message.data.prng);
269
- var m_id = mdata.map(u => u.i);
270
- var m_offset = mdata.map(u => u.o);
271
- var m_length = mdata.map(u => u.l);
272
-
273
- var mentions = {};
274
-
275
- for (var i = 0; i < m_id.length; i++) mentions[m_id[i]] = (delta.deltaMessageReply.message.body || "").substring(m_offset[i], m_offset[i] + m_length[i]);
276
- //Mention block - 1#
277
- var callbackToReturn = {
278
- type: "message_reply",
279
- threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey.otherUserFbId).toString(),
280
- messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
281
- senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId.toString(),
282
- attachments: delta.deltaMessageReply.message.attachments.map(function (att) {
283
- var mercury = JSON.parse(att.mercuryJSON);
284
- Object.assign(att, mercury);
285
- return att;
286
- }).map(att => {
287
- var x;
288
- try {
289
- x = utils._formatAttachment(att);
290
- } catch (ex) {
291
- x = att;
292
- x.error = ex;
293
- x.type = "unknown";
294
- }
295
- return x;
296
- }),
297
- args: (delta.deltaMessageReply.message.body || "").trim().split(/\s+/),
298
- body: (delta.deltaMessageReply.message.body || ""),
299
- isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
300
- mentions: mentions,
301
- timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
302
- participantIDs: (delta.deltaMessageReply.message.participants || []).map(e => e.toString())
303
- };
304
-
305
- if (delta.deltaMessageReply.repliedToMessage) {
306
- //Mention block - #2
307
- mdata =
308
- delta.deltaMessageReply.repliedToMessage === undefined ? [] :
309
- delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
310
- delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
311
- JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
312
- m_id = mdata.map(u => u.i);
313
- m_offset = mdata.map(u => u.o);
314
- m_length = mdata.map(u => u.l);
315
-
316
- var rmentions = {};
317
-
318
- for (var i = 0; i < m_id.length; i++) rmentions[m_id[i]] = (delta.deltaMessageReply.repliedToMessage.body || "").substring(m_offset[i], m_offset[i] + m_length[i]);
319
- //Mention block - 2#
320
- callbackToReturn.messageReply = {
321
- threadID: (delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.otherUserFbId).toString(),
322
- messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
323
- senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
324
- attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function (att) {
325
- var mercury = JSON.parse(att.mercuryJSON);
326
- Object.assign(att, mercury);
327
- return att;
328
- }).map(att => {
329
- var x;
330
- try {
331
- x = utils._formatAttachment(att);
332
- } catch (ex) {
333
- x = att;
334
- x.error = ex;
335
- x.type = "unknown";
336
- }
337
- return x;
338
- }),
339
- args: (delta.deltaMessageReply.repliedToMessage.body || "").trim().split(/\s+/),
340
- body: delta.deltaMessageReply.repliedToMessage.body || "",
341
- isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
342
- mentions: rmentions,
343
- timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp,
344
- participantIDs: (delta.deltaMessageReply.repliedToMessage.participants || []).map(e => e.toString())
345
- };
346
- } else if (delta.deltaMessageReply.replyToMessageId) {
347
- return defaultFuncs
348
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
349
- "av": ctx.globalOptions.pageID,
350
- "queries": JSON.stringify({
351
- "o0": {
352
- //Using the same doc_id as forcedFetch
353
- "doc_id": "2848441488556444",
354
- "query_params": {
355
- "thread_and_message_id": {
356
- "thread_id": callbackToReturn.threadID,
357
- "message_id": delta.deltaMessageReply.replyToMessageId.id,
358
- }
359
- }
360
- }
361
- })
362
- })
363
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
364
- .then((resData) => {
365
- if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
366
- if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
367
- var fetchData = resData[0].o0.data.message;
368
- var mobj = {};
369
- for (var n in fetchData.message.ranges) mobj[fetchData.message.ranges[n].entity.id] = (fetchData.message.text || "").substr(fetchData.message.ranges[n].offset, fetchData.message.ranges[n].length);
370
-
371
- callbackToReturn.messageReply = {
372
- type: "Message",
373
- threadID: callbackToReturn.threadID,
374
- messageID: fetchData.message_id,
375
- senderID: fetchData.message_sender.id.toString(),
376
- attachments: fetchData.message.blob_attachment.map(att => {
377
- var x;
378
- try {
379
- x = utils._formatAttachment({ blob_attachment: att });
380
- } catch (ex) {
381
- x = att;
382
- x.error = ex;
383
- x.type = "unknown";
384
- }
385
- return x;
386
- }),
387
- args: (fetchData.message.text || "").trim().split(/\s+/) || [],
388
- body: fetchData.message.text || "",
389
- isGroup: callbackToReturn.isGroup,
390
- mentions: mobj,
391
- timestamp: parseInt(fetchData.timestamp_precise)
392
- };
393
- })
394
- .catch(err => log.error("forcedFetch", err))
395
- .finally(function () {
396
- if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
397
- !ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID ? undefined : (function () { globalCallback(null, callbackToReturn); })();
398
- });
399
- } else callbackToReturn.delta = delta;
400
-
401
- if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
402
-
403
- return !ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID ? undefined : (function () { globalCallback(null, callbackToReturn); })();
404
- }
405
- }
406
- return;
407
- }
408
- }
409
-
410
- if (v.delta.class !== "NewMessage" && !ctx.globalOptions.listenEvents) return;
411
- switch (v.delta.class) {
412
- case "ReadReceipt":
413
- var fmtMsg;
414
- try {
415
- fmtMsg = utils.formatDeltaReadReceipt(v.delta);
416
- } catch (err) {
417
- return globalCallback({
418
- error: "Problem parsing message object. Please open an issue at https://github.com/VangBanLaNhat/fca-unofficial/issues.",
419
- detail: err,
420
- res: v.delta,
421
- type: "parse_error"
422
- });
423
- }
424
- return (function () { globalCallback(null, fmtMsg); })();
425
- case "AdminTextMessage":
426
- switch (v.delta.type) {
427
- case "joinable_group_link_mode_change":
428
- case "magic_words":
429
- case "change_thread_theme":
430
- case "change_thread_icon":
431
- case "change_thread_nickname":
432
- case "change_thread_admins":
433
- case "change_thread_approval_mode":
434
- case "group_poll":
435
- case "messenger_call_log":
436
- case "participant_joined_group_call":
437
- var fmtMsg;
438
- try {
439
- fmtMsg = utils.formatDeltaEvent(v.delta);
440
- } catch (err) {
441
- return globalCallback({
442
- error: "Problem parsing message object. Please open an issue at https://github.com/VangBanLaNhat/fca-unofficial/issues.",
443
- detail: err,
444
- res: v.delta,
445
- type: "parse_error"
446
- });
447
- }
448
- return (function () { globalCallback(null, fmtMsg); })();
449
- default:
450
- return;
451
- }
452
- //For group images
453
- case "ForcedFetch":
454
- if (!v.delta.threadKey) return;
455
- var mid = v.delta.messageId;
456
- var tid = v.delta.threadKey.threadFbId;
457
- if (mid && tid) {
458
- const form = {
459
- "av": ctx.globalOptions.pageID,
460
- "queries": JSON.stringify({
461
- "o0": {
462
- //This doc_id is valid as of March 25, 2020
463
- "doc_id": "2848441488556444",
464
- "query_params": {
465
- "thread_and_message_id": {
466
- "thread_id": tid.toString(),
467
- "message_id": mid,
468
- }
469
- }
470
- }
471
- })
472
- };
473
-
474
- defaultFuncs
475
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
476
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
477
- .then((resData) => {
478
- if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
479
-
480
- if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
481
-
482
- var fetchData = resData[0].o0.data.message;
483
-
484
- if (utils.getType(fetchData) == "Object") {
485
- log.info("forcedFetch", fetchData);
486
- switch (fetchData.__typename) {
487
- case "ThreadImageMessage":
488
- (!ctx.globalOptions.selfListen &&
489
- fetchData.message_sender.id.toString() === ctx.userID) ||
490
- !ctx.loggedIn ?
491
- undefined :
492
- (function () {
493
- globalCallback(null, {
494
- type: "change_thread_image",
495
- threadID: utils.formatID(tid.toString()),
496
- snippet: fetchData.snippet,
497
- timestamp: fetchData.timestamp_precise,
498
- author: fetchData.message_sender.id,
499
- image: {
500
- attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
501
- width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
502
- height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
503
- url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
504
- }
505
- });
506
- })();
507
- break;
508
- case "UserMessage":
509
- log.info("ff-Return", {
510
- type: "message",
511
- senderID: utils.formatID(fetchData.message_sender.id),
512
- body: fetchData.message.text || "",
513
- threadID: utils.formatID(tid.toString()),
514
- messageID: fetchData.message_id,
515
- attachments: [{
516
- type: "share",
517
- ID: fetchData.extensible_attachment.legacy_attachment_id,
518
- url: fetchData.extensible_attachment.story_attachment.url,
519
-
520
- title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
521
- description: fetchData.extensible_attachment.story_attachment.description.text,
522
- source: fetchData.extensible_attachment.story_attachment.source,
523
-
524
- image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
525
- width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
526
- height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
527
- playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
528
- duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
529
-
530
- subattachments: fetchData.extensible_attachment.subattachments,
531
- properties: fetchData.extensible_attachment.story_attachment.properties,
532
- }],
533
- mentions: {},
534
- timestamp: parseInt(fetchData.timestamp_precise),
535
- isGroup: (fetchData.message_sender.id != tid.toString())
536
- });
537
- globalCallback(null, {
538
- type: "message",
539
- senderID: utils.formatID(fetchData.message_sender.id),
540
- body: fetchData.message.text || "",
541
- threadID: utils.formatID(tid.toString()),
542
- messageID: fetchData.message_id,
543
- attachments: [{
544
- type: "share",
545
- ID: fetchData.extensible_attachment.legacy_attachment_id,
546
- url: fetchData.extensible_attachment.story_attachment.url,
547
-
548
- title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
549
- description: fetchData.extensible_attachment.story_attachment.description.text,
550
- source: fetchData.extensible_attachment.story_attachment.source,
551
-
552
- image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
553
- width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
554
- height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
555
- playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
556
- duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
557
-
558
- subattachments: fetchData.extensible_attachment.subattachments,
559
- properties: fetchData.extensible_attachment.story_attachment.properties,
560
- }],
561
- mentions: {},
562
- timestamp: parseInt(fetchData.timestamp_precise),
563
- isGroup: (fetchData.message_sender.id != tid.toString())
564
- });
565
- }
566
- } else log.error("forcedFetch", fetchData);
567
- })
568
- .catch((err) => log.error("forcedFetch", err));
569
- }
570
- break;
571
- case "ThreadName":
572
- case "ParticipantsAddedToGroupThread":
573
- case "ParticipantLeftGroupThread":
574
- var formattedEvent;
575
- try {
576
- formattedEvent = utils.formatDeltaEvent(v.delta);
577
- } catch (err) {
578
- return log.error("Lỗi Nhẹ", err);
579
- }
580
- return (!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID) || !ctx.loggedIn ? undefined : (function () { globalCallback(null, formattedEvent); })();
581
- }
208
+ if (v.delta.class == "NewMessage") {
209
+ //Not tested for pages
210
+ if (ctx.globalOptions.pageID && ctx.globalOptions.pageID != v.queue) return;
211
+
212
+ (function resolveAttachmentUrl(i) {
213
+ if (v.delta.attachments && (i == v.delta.attachments.length)) {
214
+ var fmtMsg;
215
+ try {
216
+ fmtMsg = utils.formatDeltaMessage(v);
217
+ } catch (err) {
218
+ return globalCallback({
219
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
220
+ detail: err,
221
+ res: v,
222
+ type: "parse_error"
223
+ });
224
+ }
225
+ if (fmtMsg)
226
+ if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
227
+
228
+ return !ctx.globalOptions.selfListen && fmtMsg.senderID === ctx.userID ? undefined : (function() { globalCallback(null, fmtMsg); })();
229
+ } else {
230
+ if (v.delta.attachments && (v.delta.attachments[i].mercury.attach_type == "photo")) {
231
+ api.resolvePhotoUrl(v.delta.attachments[i].fbid, (err, url) => {
232
+ if (!err) v.delta.attachments[i].mercury.metadata.url = url;
233
+ return resolveAttachmentUrl(i + 1);
234
+ });
235
+ } else return resolveAttachmentUrl(i + 1);
236
+ }
237
+ })(0);
238
+ }
239
+
240
+ if (v.delta.class == "ClientPayload") {
241
+ var clientPayload = utils.decodeClientPayload(v.delta.payload);
242
+ if (clientPayload && clientPayload.deltas) {
243
+ for (var i in clientPayload.deltas) {
244
+ var delta = clientPayload.deltas[i];
245
+ if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
246
+ (function() {
247
+ globalCallback(null, {
248
+ type: "message_reaction",
249
+ threadID: (delta.deltaMessageReaction.threadKey.threadFbId ? delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey.otherUserFbId).toString(),
250
+ messageID: delta.deltaMessageReaction.messageId,
251
+ reaction: delta.deltaMessageReaction.reaction,
252
+ senderID: delta.deltaMessageReaction.senderId.toString(),
253
+ userID: delta.deltaMessageReaction.userId.toString()
254
+ });
255
+ })();
256
+ } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
257
+ (function() {
258
+ globalCallback(null, {
259
+ type: "message_unsend",
260
+ threadID: (delta.deltaRecallMessageData.threadKey.threadFbId ? delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey.otherUserFbId).toString(),
261
+ messageID: delta.deltaRecallMessageData.messageID,
262
+ senderID: delta.deltaRecallMessageData.senderID.toString(),
263
+ deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
264
+ timestamp: delta.deltaRecallMessageData.timestamp
265
+ });
266
+ })();
267
+ } else if (delta.deltaMessageReply) {
268
+ //Mention block - #1
269
+ var mdata = delta.deltaMessageReply.message === undefined ? [] :
270
+ delta.deltaMessageReply.message.data === undefined ? [] :
271
+ delta.deltaMessageReply.message.data.prng === undefined ? [] :
272
+ JSON.parse(delta.deltaMessageReply.message.data.prng);
273
+ var m_id = mdata.map(u => u.i);
274
+ var m_offset = mdata.map(u => u.o);
275
+ var m_length = mdata.map(u => u.l);
276
+
277
+ var mentions = {};
278
+
279
+ for (var i = 0; i < m_id.length; i++) mentions[m_id[i]] = (delta.deltaMessageReply.message.body || "").substring(m_offset[i], m_offset[i] + m_length[i]);
280
+ //Mention block - 1#
281
+ var callbackToReturn = {
282
+ type: "message_reply",
283
+ threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey.otherUserFbId).toString(),
284
+ messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
285
+ senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId.toString(),
286
+ attachments: delta.deltaMessageReply.message.attachments.map(function(att) {
287
+ var mercury = JSON.parse(att.mercuryJSON);
288
+ Object.assign(att, mercury);
289
+ return att;
290
+ }).map(att => {
291
+ var x;
292
+ try {
293
+ x = utils._formatAttachment(att);
294
+ } catch (ex) {
295
+ x = att;
296
+ x.error = ex;
297
+ x.type = "unknown";
298
+ }
299
+ return x;
300
+ }),
301
+ args: (delta.deltaMessageReply.message.body || "").trim().split(/\s+/),
302
+ body: (delta.deltaMessageReply.message.body || ""),
303
+ isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
304
+ mentions: mentions,
305
+ timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
306
+ participantIDs: (delta.deltaMessageReply.message.participants || []).map(e => e.toString())
307
+ };
308
+
309
+ if (delta.deltaMessageReply.repliedToMessage) {
310
+ //Mention block - #2
311
+ mdata = delta.deltaMessageReply.repliedToMessage === undefined ? [] :
312
+ delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
313
+ delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
314
+ JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
315
+ m_id = mdata.map(u => u.i);
316
+ m_offset = mdata.map(u => u.o);
317
+ m_length = mdata.map(u => u.l);
318
+
319
+ var rmentions = {};
320
+
321
+ for (var i = 0; i < m_id.length; i++) rmentions[m_id[i]] = (delta.deltaMessageReply.repliedToMessage.body || "").substring(m_offset[i], m_offset[i] + m_length[i]);
322
+ //Mention block - 2#
323
+ callbackToReturn.messageReply = {
324
+ threadID: (delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.otherUserFbId).toString(),
325
+ messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
326
+ senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
327
+ attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function(att) {
328
+ var mercury = JSON.parse(att.mercuryJSON);
329
+ Object.assign(att, mercury);
330
+ return att;
331
+ }).map(att => {
332
+ var x;
333
+ try {
334
+ x = utils._formatAttachment(att);
335
+ } catch (ex) {
336
+ x = att;
337
+ x.error = ex;
338
+ x.type = "unknown";
339
+ }
340
+ return x;
341
+ }),
342
+ args: (delta.deltaMessageReply.repliedToMessage.body || "").trim().split(/\s+/),
343
+ body: delta.deltaMessageReply.repliedToMessage.body || "",
344
+ isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
345
+ mentions: rmentions,
346
+ timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp,
347
+ participantIDs: (delta.deltaMessageReply.repliedToMessage.participants || []).map(e => e.toString())
348
+ };
349
+ } else if (delta.deltaMessageReply.replyToMessageId) {
350
+ return defaultFuncs
351
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
352
+ "av": ctx.globalOptions.pageID,
353
+ "queries": JSON.stringify({
354
+ "o0": {
355
+ //Using the same doc_id as forcedFetch
356
+ "doc_id": "2848441488556444",
357
+ "query_params": {
358
+ "thread_and_message_id": {
359
+ "thread_id": callbackToReturn.threadID,
360
+ "message_id": delta.deltaMessageReply.replyToMessageId.id,
361
+ }
362
+ }
363
+ }
364
+ })
365
+ })
366
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
367
+ .then((resData) => {
368
+ if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
369
+ if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
370
+ var fetchData = resData[0].o0.data.message;
371
+ var mobj = {};
372
+ for (var n in fetchData.message.ranges) mobj[fetchData.message.ranges[n].entity.id] = (fetchData.message.text || "").substr(fetchData.message.ranges[n].offset, fetchData.message.ranges[n].length);
373
+
374
+ callbackToReturn.messageReply = {
375
+ threadID: callbackToReturn.threadID,
376
+ messageID: fetchData.message_id,
377
+ senderID: fetchData.message_sender.id.toString(),
378
+ attachments: fetchData.message.blob_attachment.map(att => {
379
+ var x;
380
+ try {
381
+ x = utils._formatAttachment({ blob_attachment: att });
382
+ } catch (ex) {
383
+ x = att;
384
+ x.error = ex;
385
+ x.type = "unknown";
386
+ }
387
+ return x;
388
+ }),
389
+ args: (fetchData.message.text || "").trim().split(/\s+/) || [],
390
+ body: fetchData.message.text || "",
391
+ isGroup: callbackToReturn.isGroup,
392
+ mentions: mobj,
393
+ timestamp: parseInt(fetchData.timestamp_precise)
394
+ };
395
+ })
396
+ .catch(err => log.error("forcedFetch", err))
397
+ .finally(function() {
398
+ if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
399
+ !ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID ? undefined : (function() { globalCallback(null, callbackToReturn); })();
400
+ });
401
+ } else callbackToReturn.delta = delta;
402
+
403
+ if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
404
+
405
+ return !ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID ? undefined : (function() { globalCallback(null, callbackToReturn); })();
406
+ }
407
+ }
408
+ return;
409
+ }
410
+ }
411
+
412
+ if (v.delta.class !== "NewMessage" && !ctx.globalOptions.listenEvents) return;
413
+ switch (v.delta.class) {
414
+ case "ReadReceipt":
415
+ var fmtMsg;
416
+ try {
417
+ fmtMsg = utils.formatDeltaReadReceipt(v.delta);
418
+ } catch (err) {
419
+ return globalCallback({
420
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
421
+ detail: err,
422
+ res: v.delta,
423
+ type: "parse_error"
424
+ });
425
+ }
426
+ return (function() { globalCallback(null, fmtMsg); })();
427
+ case "AdminTextMessage":
428
+ switch (v.delta.type) {
429
+ case "change_thread_theme":
430
+ case "change_thread_icon":
431
+ case "change_thread_nickname":
432
+ case "change_thread_admins":
433
+ case "change_thread_approval_mode":
434
+ case "group_poll":
435
+ case "messenger_call_log":
436
+ case "participant_joined_group_call":
437
+ var fmtMsg;
438
+ try {
439
+ fmtMsg = utils.formatDeltaEvent(v.delta);
440
+ } catch (err) {
441
+ return globalCallback({
442
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
443
+ detail: err,
444
+ res: v.delta,
445
+ type: "parse_error"
446
+ });
447
+ }
448
+ return (function() { globalCallback(null, fmtMsg); })();
449
+ default:
450
+ return;
451
+ }
452
+ break;
453
+ //For group images
454
+ case "ForcedFetch":
455
+ if (!v.delta.threadKey) return;
456
+ var mid = v.delta.messageId;
457
+ var tid = v.delta.threadKey.threadFbId;
458
+ if (mid && tid) {
459
+ const form = {
460
+ "av": ctx.globalOptions.pageID,
461
+ "queries": JSON.stringify({
462
+ "o0": {
463
+ //This doc_id is valid as of March 25, 2020
464
+ "doc_id": "2848441488556444",
465
+ "query_params": {
466
+ "thread_and_message_id": {
467
+ "thread_id": tid.toString(),
468
+ "message_id": mid,
469
+ }
470
+ }
471
+ }
472
+ })
473
+ };
474
+
475
+ defaultFuncs
476
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
477
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
478
+ .then((resData) => {
479
+ if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
480
+
481
+ if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
482
+
483
+ var fetchData = resData[0].o0.data.message;
484
+
485
+ if (utils.getType(fetchData) == "Object") {
486
+ log.info("forcedFetch", fetchData);
487
+ switch (fetchData.__typename) {
488
+ case "ThreadImageMessage":
489
+ (!ctx.globalOptions.selfListen && fetchData.message_sender.id.toString() === ctx.userID) ||
490
+ !ctx.loggedIn ? undefined : (function() {
491
+ globalCallback(null, {
492
+ type: "change_thread_image",
493
+ threadID: utils.formatID(tid.toString()),
494
+ snippet: fetchData.snippet,
495
+ timestamp: fetchData.timestamp_precise,
496
+ author: fetchData.message_sender.id,
497
+ image: {
498
+ attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
499
+ width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
500
+ height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
501
+ url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
502
+ }
503
+ });
504
+ })();
505
+ break;
506
+ case "UserMessage":
507
+ log.info("ff-Return", {
508
+ type: "message",
509
+ senderID: utils.formatID(fetchData.message_sender.id),
510
+ body: fetchData.message.text || "",
511
+ threadID: utils.formatID(tid.toString()),
512
+ messageID: fetchData.message_id,
513
+ attachments: [{
514
+ type: "share",
515
+ ID: fetchData.extensible_attachment.legacy_attachment_id,
516
+ url: fetchData.extensible_attachment.story_attachment.url,
517
+
518
+ title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
519
+ description: fetchData.extensible_attachment.story_attachment.description.text,
520
+ source: fetchData.extensible_attachment.story_attachment.source,
521
+
522
+ image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
523
+ width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
524
+ height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
525
+ playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
526
+ duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
527
+
528
+ subattachments: fetchData.extensible_attachment.subattachments,
529
+ properties: fetchData.extensible_attachment.story_attachment.properties,
530
+ }],
531
+ mentions: {},
532
+ timestamp: parseInt(fetchData.timestamp_precise),
533
+ isGroup: (fetchData.message_sender.id != tid.toString())
534
+ });
535
+ globalCallback(null, {
536
+ type: "message",
537
+ senderID: utils.formatID(fetchData.message_sender.id),
538
+ body: fetchData.message.text || "",
539
+ threadID: utils.formatID(tid.toString()),
540
+ messageID: fetchData.message_id,
541
+ attachments: [{
542
+ type: "share",
543
+ ID: fetchData.extensible_attachment.legacy_attachment_id,
544
+ url: fetchData.extensible_attachment.story_attachment.url,
545
+
546
+ title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
547
+ description: fetchData.extensible_attachment.story_attachment.description.text,
548
+ source: fetchData.extensible_attachment.story_attachment.source,
549
+
550
+ image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
551
+ width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
552
+ height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
553
+ playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
554
+ duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
555
+
556
+ subattachments: fetchData.extensible_attachment.subattachments,
557
+ properties: fetchData.extensible_attachment.story_attachment.properties,
558
+ }],
559
+ mentions: {},
560
+ timestamp: parseInt(fetchData.timestamp_precise),
561
+ isGroup: (fetchData.message_sender.id != tid.toString())
562
+ });
563
+ }
564
+ } else log.error("forcedFetch", fetchData);
565
+ })
566
+ .catch((err) => log.error("forcedFetch", err));
567
+ }
568
+ break;
569
+ case "ThreadName":
570
+ case "ParticipantsAddedToGroupThread":
571
+ case "ParticipantLeftGroupThread":
572
+ var formattedEvent;
573
+ try {
574
+ formattedEvent = utils.formatDeltaEvent(v.delta);
575
+ } catch (err) {
576
+ return globalCallback({
577
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
578
+ detail: err,
579
+ res: v.delta,
580
+ type: "parse_error"
581
+ });
582
+ }
583
+ return (!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID) || !ctx.loggedIn ? undefined : (function() { globalCallback(null, formattedEvent); })();
584
+ }
582
585
  }
583
586
 
584
-
585
587
  function markDelivery(ctx, api, threadID, messageID) {
586
- if (threadID && messageID) {
587
- api.markAsDelivered(threadID, messageID, (err) => {
588
- if (err) log.error("markAsDelivered", err);
589
- else {
590
- if (ctx.globalOptions.autoMarkRead) {
591
- api.markAsRead(threadID, (err) => {
592
- if (err) log.error("markAsDelivered", err);
593
- });
594
- }
595
- }
596
- });
597
- }
588
+ if (threadID && messageID) {
589
+ api.markAsDelivered(threadID, messageID, (err) => {
590
+ if (err) {
591
+ log.error("markAsDelivered", err);
592
+ } else {
593
+ if (ctx.globalOptions.autoMarkRead) {
594
+ api.markAsRead(threadID, (err) => {
595
+ if (err) log.error("markAsDelivered", err);
596
+ });
597
+ }
598
+ }
599
+ });
600
+ }
598
601
  }
599
602
 
600
- module.exports = function (defaultFuncs, api, ctx) {
601
- var globalCallback = identity;
602
- getSeqID = function getSeqID() {
603
- ctx.t_mqttCalled = false;
604
- defaultFuncs
605
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
606
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
607
- .then((resData) => {
608
- if (utils.getType(resData) != "Array") {
609
- switch (global.Fca.Require.FastConfig.AutoLogin) {
610
- case true: {
611
- global.Fca.Require.logger.Warning(global.Fca.Require.Language.Index.AutoLogin, function() {
612
- return global.Fca.AutoLogin();
613
- });
614
- break;
615
- }
616
- case false: {
617
- throw { error: global.Fca.Require.Language.Index.ErrAppState };
618
-
619
- }
620
- }
621
- }
622
- if (resData && resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
623
- if (resData[resData.length - 1].successful_results === 0) throw { error: "getSeqId: there was no successful_results", res: resData };
624
- if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
625
- ctx.lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
626
- listenMqtt(defaultFuncs, api, ctx, globalCallback);
627
- } else throw { error: "getSeqId: no sync_sequence_id found.", res: resData };
628
- })
629
- .catch((err) => {
630
- log.error("getSeqId", err);
631
- if (utils.getType(err) == "Object" && err.error === global.Fca.Require.Language.Index.ErrAppState) ctx.loggedIn = false;
632
- return globalCallback(err);
633
- });
634
- };
635
-
636
- return function (callback) {
637
- class MessageEmitter extends EventEmitter {
638
- stopListening(callback) {
639
- callback = callback || (() => { });
640
- globalCallback = identity;
641
- if (ctx.mqttClient) {
642
- ctx.mqttClient.unsubscribe("/webrtc");
643
- ctx.mqttClient.unsubscribe("/rtc_multi");
644
- ctx.mqttClient.unsubscribe("/onevc");
645
- ctx.mqttClient.publish("/browser_close", "{}");
646
- ctx.mqttClient.end(false, function (...data) {
647
- callback(data);
648
- ctx.mqttClient = undefined;
649
- });
650
- }
651
- }
652
- }
653
-
654
- var msgEmitter = new MessageEmitter();
655
- globalCallback = (callback || function (error, message) {
656
- if (error) return msgEmitter.emit("error", error);
657
- msgEmitter.emit("message", message);
658
- });
659
-
660
- //Reset some stuff
661
- if (!ctx.firstListen) ctx.lastSeqId = null;
662
- ctx.syncToken = undefined;
663
- ctx.t_mqttCalled = false;
664
-
665
- //Same request as getThreadList
666
- form = {
667
- "av": ctx.globalOptions.pageID,
668
- "queries": JSON.stringify({
669
- "o0": {
670
- "doc_id": "3336396659757871",
671
- "query_params": {
672
- "limit": 1,
673
- "before": null,
674
- "tags": ["INBOX"],
675
- "includeDeliveryReceipts": false,
676
- "includeSeqID": true
677
- }
678
- }
679
- })
680
- };
681
-
682
- if (!ctx.firstListen || !ctx.lastSeqId) getSeqID();
683
- else listenMqtt(defaultFuncs, api, ctx, globalCallback);
684
- ctx.firstListen = false;
685
- return msgEmitter;
686
- };
603
+ module.exports = function(defaultFuncs, api, ctx) {
604
+ var globalCallback = identity;
605
+ getSeqID = function getSeqID() {
606
+ ctx.t_mqttCalled = false;
607
+ defaultFuncs
608
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
609
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
610
+ .then((resData) => {
611
+ if (utils.getType(resData) != "Array") throw { error: "Not logged in", res: resData };
612
+ if (resData && resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
613
+ if (resData[resData.length - 1].successful_results === 0) throw { error: "getSeqId: there was no successful_results", res: resData };
614
+ if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
615
+ ctx.lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
616
+ listenMqtt(defaultFuncs, api, ctx, globalCallback);
617
+ } else throw { error: "getSeqId: no sync_sequence_id found.", res: resData };
618
+ })
619
+ .catch((err) => {
620
+ log.error("getSeqId", err);
621
+ if (utils.getType(err) == "Object" && err.error === "Not logged in") ctx.loggedIn = false;
622
+ return globalCallback(err);
623
+ });
624
+ };
625
+
626
+ return function(callback) {
627
+ class MessageEmitter extends EventEmitter {
628
+ stopListening(callback) {
629
+ callback = callback || (() => {});
630
+ globalCallback = identity;
631
+ if (ctx.mqttClient) {
632
+ ctx.mqttClient.unsubscribe("/webrtc");
633
+ ctx.mqttClient.unsubscribe("/rtc_multi");
634
+ ctx.mqttClient.unsubscribe("/onevc");
635
+ ctx.mqttClient.publish("/browser_close", "{}");
636
+ ctx.mqttClient.end(false, function(...data) {
637
+ callback(data);
638
+ ctx.mqttClient = undefined;
639
+ });
640
+ }
641
+ }
642
+ }
643
+
644
+ var msgEmitter = new MessageEmitter();
645
+ globalCallback = (callback || function(error, message) {
646
+ if (error) return msgEmitter.emit("error", error);
647
+ msgEmitter.emit("message", message);
648
+ });
649
+
650
+ //Reset some stuff
651
+ if (!ctx.firstListen) ctx.lastSeqId = null;
652
+ ctx.syncToken = undefined;
653
+ ctx.t_mqttCalled = false;
654
+
655
+ //Same request as getThreadList
656
+ form = {
657
+ "av": ctx.globalOptions.pageID,
658
+ "queries": JSON.stringify({
659
+ "o0": {
660
+ "doc_id": "3336396659757871",
661
+ "query_params": {
662
+ "limit": 1,
663
+ "before": null,
664
+ "tags": ["INBOX"],
665
+ "includeDeliveryReceipts": false,
666
+ "includeSeqID": true
667
+ }
668
+ }
669
+ })
670
+ };
671
+
672
+ if (!ctx.firstListen || !ctx.lastSeqId) getSeqID();
673
+ else listenMqtt(defaultFuncs, api, ctx, globalCallback);
674
+ ctx.firstListen = false;
675
+ return msgEmitter;
676
+ };
687
677
  };