node-ainzfb-new 1.7.10-11 → 1.7.10-14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/utils.js +1146 -1449
package/utils.js
CHANGED
@@ -10,61 +10,55 @@ var querystring = require("querystring");
|
|
10
10
|
var url = require("url");
|
11
11
|
|
12
12
|
function setProxy(url) {
|
13
|
-
|
14
|
-
return
|
15
|
-
require("request").defaults({ jar: true })
|
16
|
-
));
|
17
|
-
return (request = bluebird.promisify(
|
18
|
-
require("request").defaults({ jar: true, proxy: url })
|
19
|
-
));
|
13
|
+
if (typeof url == undefined) return request = bluebird.promisify(require("request").defaults({ jar: true }));
|
14
|
+
return request = bluebird.promisify(require("request").defaults({ jar: true, proxy: url }));
|
20
15
|
}
|
21
16
|
|
22
17
|
function getHeaders(url, options, ctx, customHeader) {
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
18
|
+
var headers = {
|
19
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
20
|
+
Referer: "https://www.facebook.com/",
|
21
|
+
Host: url.replace("https://", "").split("/")[0],
|
22
|
+
Origin: "https://www.facebook.com",
|
23
|
+
"User-Agent": options.userAgent,
|
24
|
+
Connection: "keep-alive",
|
25
|
+
"sec-fetch-site": 'same-origin',
|
26
|
+
"sec-fetch-mode": 'cors'
|
27
|
+
};
|
28
|
+
if (customHeader) Object.assign(headers, customHeader);
|
29
|
+
|
30
|
+
if (ctx && ctx.region) headers["X-MSGR-Region"] = ctx.region;
|
31
|
+
|
32
|
+
return headers;
|
38
33
|
}
|
39
34
|
|
40
35
|
function isReadableStream(obj) {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
36
|
+
return (
|
37
|
+
obj instanceof stream.Stream &&
|
38
|
+
(getType(obj._read) === "Function" ||
|
39
|
+
getType(obj._read) === "AsyncFunction") &&
|
40
|
+
getType(obj._readableState) === "Object"
|
41
|
+
);
|
47
42
|
}
|
48
43
|
|
49
44
|
function get(url, jar, qs, options, ctx) {
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
});
|
45
|
+
// I'm still confused about this
|
46
|
+
if (getType(qs) === "Object")
|
47
|
+
for (var prop in qs)
|
48
|
+
if (qs.hasOwnProperty(prop) && getType(qs[prop]) === "Object") qs[prop] = JSON.stringify(qs[prop]);
|
49
|
+
var op = {
|
50
|
+
headers: getHeaders(url, options, ctx),
|
51
|
+
timeout: 60000,
|
52
|
+
qs: qs,
|
53
|
+
url: url,
|
54
|
+
method: "GET",
|
55
|
+
jar: jar,
|
56
|
+
gzip: true
|
57
|
+
};
|
58
|
+
|
59
|
+
return request(op).then(function(res) {
|
60
|
+
return res[0];
|
61
|
+
});
|
68
62
|
}
|
69
63
|
|
70
64
|
/*function getv2(url, jar, qs, options, ctx) {
|
@@ -88,21 +82,21 @@ function get(url, jar, qs, options, ctx) {
|
|
88
82
|
}*/
|
89
83
|
|
90
84
|
function post(url, jar, form, options, ctx, customHeader) {
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
85
|
+
let headers = getHeaders(url, options);
|
86
|
+
headers['sec-fetch-site'] = 'same-origin';
|
87
|
+
var op = {
|
88
|
+
headers: headers,
|
89
|
+
timeout: 60000,
|
90
|
+
url: url,
|
91
|
+
method: "POST",
|
92
|
+
form: form,
|
93
|
+
jar: jar,
|
94
|
+
gzip: true
|
95
|
+
};
|
96
|
+
|
97
|
+
return request(op).then(function(res) {
|
98
|
+
return res[0];
|
99
|
+
});
|
106
100
|
}
|
107
101
|
|
108
102
|
/*function postv2(url, jar, form, options, ctx, customHeader) {
|
@@ -124,1021 +118,815 @@ function post(url, jar, form, options, ctx, customHeader) {
|
|
124
118
|
}*/
|
125
119
|
|
126
120
|
function postFormData(url, jar, form, qs, options, ctx) {
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
121
|
+
var headers = getHeaders(url, options, ctx);
|
122
|
+
headers["Content-Type"] = "multipart/form-data";
|
123
|
+
var op = {
|
124
|
+
headers: headers,
|
125
|
+
timeout: 60000,
|
126
|
+
url: url,
|
127
|
+
method: "POST",
|
128
|
+
formData: form,
|
129
|
+
qs: qs,
|
130
|
+
jar: jar,
|
131
|
+
gzip: true
|
132
|
+
};
|
133
|
+
|
134
|
+
return request(op).then(function(res) {
|
135
|
+
return res[0];
|
136
|
+
});
|
143
137
|
}
|
144
138
|
|
145
139
|
function padZeros(val, len) {
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
140
|
+
val = String(val);
|
141
|
+
len = len || 2;
|
142
|
+
while (val.length < len) val = "0" + val;
|
143
|
+
return val;
|
150
144
|
}
|
151
145
|
|
152
146
|
function generateThreadingID(clientID) {
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
147
|
+
var k = Date.now();
|
148
|
+
var l = Math.floor(Math.random() * 4294967295);
|
149
|
+
var m = clientID;
|
150
|
+
return "<" + k + ":" + l + "-" + m + "@mail.projektitan.com>";
|
157
151
|
}
|
158
152
|
|
159
153
|
function getCurrentTimestamp() {
|
160
|
-
|
161
|
-
|
162
|
-
|
154
|
+
const date = new Date();
|
155
|
+
const unixTime = date.getTime();
|
156
|
+
return unixTime;
|
163
157
|
}
|
164
158
|
|
165
159
|
function binaryToDecimal(data) {
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
160
|
+
var ret = "";
|
161
|
+
while (data !== "0") {
|
162
|
+
var end = 0;
|
163
|
+
var fullName = "";
|
164
|
+
var i = 0;
|
165
|
+
for (; i < data.length; i++) {
|
166
|
+
end = 2 * end + parseInt(data[i], 10);
|
167
|
+
if (end >= 10) {
|
168
|
+
fullName += "1";
|
169
|
+
end -= 10;
|
170
|
+
} else fullName += "0";
|
171
|
+
}
|
172
|
+
ret = end.toString() + ret;
|
173
|
+
data = fullName.slice(fullName.indexOf("1"));
|
177
174
|
}
|
178
|
-
|
179
|
-
data = fullName.slice(fullName.indexOf("1"));
|
180
|
-
}
|
181
|
-
return ret;
|
175
|
+
return ret;
|
182
176
|
}
|
183
177
|
|
184
178
|
function generateOfflineThreadingID() {
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
179
|
+
var ret = Date.now();
|
180
|
+
var value = Math.floor(Math.random() * 4294967295);
|
181
|
+
var str = ("0000000000000000000000" + value.toString(2)).slice(-22);
|
182
|
+
var msgs = ret.toString(2) + str;
|
183
|
+
return binaryToDecimal(msgs);
|
190
184
|
}
|
191
185
|
|
192
186
|
var h;
|
193
187
|
var i = {};
|
194
188
|
var j = {
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
"%2c%
|
222
|
-
Z:
|
223
|
-
"%2c%22sb%22%3a1%2c%22t%22%3a%5b%5d%2c%22f%22%3anull%2c%22uct%22%3a0%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a"
|
189
|
+
_: "%",
|
190
|
+
A: "%2",
|
191
|
+
B: "000",
|
192
|
+
C: "%7d",
|
193
|
+
D: "%7b%22",
|
194
|
+
E: "%2c%22",
|
195
|
+
F: "%22%3a",
|
196
|
+
G: "%2c%22ut%22%3a1",
|
197
|
+
H: "%2c%22bls%22%3a",
|
198
|
+
I: "%2c%22n%22%3a%22%",
|
199
|
+
J: "%22%3a%7b%22i%22%3a0%7d",
|
200
|
+
K: "%2c%22pt%22%3a0%2c%22vis%22%3a",
|
201
|
+
L: "%2c%22ch%22%3a%7b%22h%22%3a%22",
|
202
|
+
M: "%7b%22v%22%3a2%2c%22time%22%3a1",
|
203
|
+
N: ".channel%22%2c%22sub%22%3a%5b",
|
204
|
+
O: "%2c%22sb%22%3a1%2c%22t%22%3a%5b",
|
205
|
+
P: "%2c%22ud%22%3a100%2c%22lc%22%3a0",
|
206
|
+
Q: "%5d%2c%22f%22%3anull%2c%22uct%22%3a",
|
207
|
+
R: ".channel%22%2c%22sub%22%3a%5b1%5d",
|
208
|
+
S: "%22%2c%22m%22%3a0%7d%2c%7b%22i%22%3a",
|
209
|
+
T: "%2c%22blc%22%3a1%2c%22snd%22%3a1%2c%22ct%22%3a",
|
210
|
+
U: "%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a",
|
211
|
+
V: "%2c%22blc%22%3a0%2c%22snd%22%3a0%2c%22ct%22%3a",
|
212
|
+
W: "%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a",
|
213
|
+
X: "%2c%22ri%22%3a0%7d%2c%22state%22%3a%7b%22p%22%3a0%2c%22ut%22%3a1",
|
214
|
+
Y: "%2c%22pt%22%3a0%2c%22vis%22%3a1%2c%22bls%22%3a0%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a",
|
215
|
+
Z: "%2c%22sb%22%3a1%2c%22t%22%3a%5b%5d%2c%22f%22%3anull%2c%22uct%22%3a0%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a"
|
224
216
|
};
|
225
217
|
(function() {
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
218
|
+
var l = [];
|
219
|
+
for (var m in j) {
|
220
|
+
i[j[m]] = m;
|
221
|
+
l.push(j[m]);
|
222
|
+
}
|
223
|
+
l.reverse();
|
224
|
+
h = new RegExp(l.join("|"), "g");
|
233
225
|
})();
|
234
226
|
|
235
227
|
function presenceEncode(str) {
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
228
|
+
return encodeURIComponent(str)
|
229
|
+
.replace(/([_A-Z])|%../g, function(m, n) {
|
230
|
+
return n ? "%" + n.charCodeAt(0).toString(16) : m;
|
231
|
+
})
|
232
|
+
.toLowerCase()
|
233
|
+
.replace(h, function(m) {
|
234
|
+
return i[m];
|
235
|
+
});
|
244
236
|
}
|
245
237
|
|
246
238
|
// eslint-disable-next-line no-unused-vars
|
247
239
|
function presenceDecode(str) {
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
240
|
+
return decodeURIComponent(
|
241
|
+
str.replace(/[_A-Z]/g, function(m) {
|
242
|
+
return j[m];
|
243
|
+
})
|
244
|
+
);
|
253
245
|
}
|
254
246
|
|
255
247
|
function generatePresence(userID) {
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
248
|
+
var time = Date.now();
|
249
|
+
return (
|
250
|
+
"E" +
|
251
|
+
presenceEncode(
|
252
|
+
JSON.stringify({
|
253
|
+
v: 3,
|
254
|
+
time: parseInt(time / 1000, 10),
|
255
|
+
user: userID,
|
256
|
+
state: {
|
257
|
+
ut: 0,
|
258
|
+
t2: [],
|
259
|
+
lm2: null,
|
260
|
+
uct2: time,
|
261
|
+
tr: null,
|
262
|
+
tw: Math.floor(Math.random() * 4294967295) + 1,
|
263
|
+
at: time
|
264
|
+
},
|
265
|
+
ch: {
|
266
|
+
["p_" + userID]: 0
|
267
|
+
}
|
268
|
+
})
|
269
|
+
)
|
270
|
+
);
|
279
271
|
}
|
280
272
|
|
281
273
|
function generateAccessiblityCookie() {
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
274
|
+
var time = Date.now();
|
275
|
+
return encodeURIComponent(
|
276
|
+
JSON.stringify({
|
277
|
+
sr: 0,
|
278
|
+
"sr-ts": time,
|
279
|
+
jk: 0,
|
280
|
+
"jk-ts": time,
|
281
|
+
kb: 0,
|
282
|
+
"kb-ts": time,
|
283
|
+
hcm: 0,
|
284
|
+
"hcm-ts": time
|
285
|
+
})
|
286
|
+
);
|
295
287
|
}
|
296
288
|
|
297
289
|
function getGUID() {
|
298
|
-
/** @type {number} */
|
299
|
-
var sectionLength = Date.now();
|
300
|
-
/** @type {string} */
|
301
|
-
var id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
302
290
|
/** @type {number} */
|
303
|
-
var
|
304
|
-
/** @type {number} */
|
305
|
-
sectionLength = Math.floor(sectionLength / 16);
|
291
|
+
var sectionLength = Date.now();
|
306
292
|
/** @type {string} */
|
307
|
-
var
|
308
|
-
|
309
|
-
|
310
|
-
|
293
|
+
var id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
294
|
+
/** @type {number} */
|
295
|
+
var r = Math.floor((sectionLength + Math.random() * 16) % 16);
|
296
|
+
/** @type {number} */
|
297
|
+
sectionLength = Math.floor(sectionLength / 16);
|
298
|
+
/** @type {string} */
|
299
|
+
var _guid = (c == "x" ? r : (r & 7) | 8).toString(16);
|
300
|
+
return _guid;
|
301
|
+
});
|
302
|
+
return id;
|
311
303
|
}
|
312
304
|
|
313
305
|
function _formatAttachment(attachment1, attachment2) {
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
"MessageLocation"
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
/* empty */
|
593
|
-
}
|
306
|
+
// TODO: THIS IS REALLY BAD
|
307
|
+
// This is an attempt at fixing Facebook's inconsistencies. Sometimes they give us
|
308
|
+
// two attachment objects, but sometimes only one. They each contain part of the
|
309
|
+
// data that you'd want so we merge them for convenience.
|
310
|
+
// Instead of having a bunch of if statements guarding every access to image_data,
|
311
|
+
// we set it to empty object and use the fact that it'll return undefined.
|
312
|
+
attachment2 = attachment2 || { id: "", image_data: {} };
|
313
|
+
attachment1 = attachment1.mercury ? attachment1.mercury : attachment1;
|
314
|
+
var blob = attachment1.blob_attachment;
|
315
|
+
var type =
|
316
|
+
blob && blob.__typename ? blob.__typename : attachment1.attach_type;
|
317
|
+
if (!type && attachment1.sticker_attachment) {
|
318
|
+
type = "StickerAttachment";
|
319
|
+
blob = attachment1.sticker_attachment;
|
320
|
+
} else if (!type && attachment1.extensible_attachment) {
|
321
|
+
if (
|
322
|
+
attachment1.extensible_attachment.story_attachment &&
|
323
|
+
attachment1.extensible_attachment.story_attachment.target &&
|
324
|
+
attachment1.extensible_attachment.story_attachment.target.__typename &&
|
325
|
+
attachment1.extensible_attachment.story_attachment.target.__typename === "MessageLocation"
|
326
|
+
) type = "MessageLocation";
|
327
|
+
else type = "ExtensibleAttachment";
|
328
|
+
|
329
|
+
blob = attachment1.extensible_attachment;
|
330
|
+
}
|
331
|
+
// TODO: Determine whether "sticker", "photo", "file" etc are still used
|
332
|
+
// KEEP IN SYNC WITH getThreadHistory
|
333
|
+
switch (type) {
|
334
|
+
case "sticker":
|
335
|
+
return {
|
336
|
+
type: "sticker",
|
337
|
+
ID: attachment1.metadata.stickerID.toString(),
|
338
|
+
url: attachment1.url,
|
339
|
+
|
340
|
+
packID: attachment1.metadata.packID.toString(),
|
341
|
+
spriteUrl: attachment1.metadata.spriteURI,
|
342
|
+
spriteUrl2x: attachment1.metadata.spriteURI2x,
|
343
|
+
width: attachment1.metadata.width,
|
344
|
+
height: attachment1.metadata.height,
|
345
|
+
|
346
|
+
caption: attachment2.caption,
|
347
|
+
description: attachment2.description,
|
348
|
+
|
349
|
+
frameCount: attachment1.metadata.frameCount,
|
350
|
+
frameRate: attachment1.metadata.frameRate,
|
351
|
+
framesPerRow: attachment1.metadata.framesPerRow,
|
352
|
+
framesPerCol: attachment1.metadata.framesPerCol,
|
353
|
+
|
354
|
+
stickerID: attachment1.metadata.stickerID.toString(), // @Legacy
|
355
|
+
spriteURI: attachment1.metadata.spriteURI, // @Legacy
|
356
|
+
spriteURI2x: attachment1.metadata.spriteURI2x // @Legacy
|
357
|
+
};
|
358
|
+
case "file":
|
359
|
+
return {
|
360
|
+
type: "file",
|
361
|
+
filename: attachment1.name,
|
362
|
+
ID: attachment2.id.toString(),
|
363
|
+
url: attachment1.url,
|
364
|
+
|
365
|
+
isMalicious: attachment2.is_malicious,
|
366
|
+
contentType: attachment2.mime_type,
|
367
|
+
|
368
|
+
name: attachment1.name, // @Legacy
|
369
|
+
mimeType: attachment2.mime_type, // @Legacy
|
370
|
+
fileSize: attachment2.file_size // @Legacy
|
371
|
+
};
|
372
|
+
case "photo":
|
373
|
+
return {
|
374
|
+
type: "photo",
|
375
|
+
ID: attachment1.metadata.fbid.toString(),
|
376
|
+
filename: attachment1.fileName,
|
377
|
+
thumbnailUrl: attachment1.thumbnail_url,
|
378
|
+
|
379
|
+
previewUrl: attachment1.preview_url,
|
380
|
+
previewWidth: attachment1.preview_width,
|
381
|
+
previewHeight: attachment1.preview_height,
|
382
|
+
|
383
|
+
largePreviewUrl: attachment1.large_preview_url,
|
384
|
+
largePreviewWidth: attachment1.large_preview_width,
|
385
|
+
largePreviewHeight: attachment1.large_preview_height,
|
386
|
+
|
387
|
+
url: attachment1.metadata.url, // @Legacy
|
388
|
+
width: attachment1.metadata.dimensions.split(",")[0], // @Legacy
|
389
|
+
height: attachment1.metadata.dimensions.split(",")[1], // @Legacy
|
390
|
+
name: attachment1.fileName // @Legacy
|
391
|
+
};
|
392
|
+
case "animated_image":
|
393
|
+
return {
|
394
|
+
type: "animated_image",
|
395
|
+
ID: attachment2.id.toString(),
|
396
|
+
filename: attachment2.filename,
|
397
|
+
|
398
|
+
previewUrl: attachment1.preview_url,
|
399
|
+
previewWidth: attachment1.preview_width,
|
400
|
+
previewHeight: attachment1.preview_height,
|
401
|
+
|
402
|
+
url: attachment2.image_data.url,
|
403
|
+
width: attachment2.image_data.width,
|
404
|
+
height: attachment2.image_data.height,
|
405
|
+
|
406
|
+
name: attachment1.name, // @Legacy
|
407
|
+
facebookUrl: attachment1.url, // @Legacy
|
408
|
+
thumbnailUrl: attachment1.thumbnail_url, // @Legacy
|
409
|
+
mimeType: attachment2.mime_type, // @Legacy
|
410
|
+
rawGifImage: attachment2.image_data.raw_gif_image, // @Legacy
|
411
|
+
rawWebpImage: attachment2.image_data.raw_webp_image, // @Legacy
|
412
|
+
animatedGifUrl: attachment2.image_data.animated_gif_url, // @Legacy
|
413
|
+
animatedGifPreviewUrl: attachment2.image_data.animated_gif_preview_url, // @Legacy
|
414
|
+
animatedWebpUrl: attachment2.image_data.animated_webp_url, // @Legacy
|
415
|
+
animatedWebpPreviewUrl: attachment2.image_data.animated_webp_preview_url // @Legacy
|
416
|
+
};
|
417
|
+
case "share":
|
418
|
+
return {
|
419
|
+
type: "share",
|
420
|
+
ID: attachment1.share.share_id.toString(),
|
421
|
+
url: attachment2.href,
|
422
|
+
|
423
|
+
title: attachment1.share.title,
|
424
|
+
description: attachment1.share.description,
|
425
|
+
source: attachment1.share.source,
|
426
|
+
|
427
|
+
image: attachment1.share.media.image,
|
428
|
+
width: attachment1.share.media.image_size.width,
|
429
|
+
height: attachment1.share.media.image_size.height,
|
430
|
+
playable: attachment1.share.media.playable,
|
431
|
+
duration: attachment1.share.media.duration,
|
432
|
+
|
433
|
+
subattachments: attachment1.share.subattachments,
|
434
|
+
properties: {},
|
435
|
+
|
436
|
+
animatedImageSize: attachment1.share.media.animated_image_size, // @Legacy
|
437
|
+
facebookUrl: attachment1.share.uri, // @Legacy
|
438
|
+
target: attachment1.share.target, // @Legacy
|
439
|
+
styleList: attachment1.share.style_list // @Legacy
|
440
|
+
};
|
441
|
+
case "video":
|
442
|
+
return {
|
443
|
+
type: "video",
|
444
|
+
ID: attachment1.metadata.fbid.toString(),
|
445
|
+
filename: attachment1.name,
|
446
|
+
|
447
|
+
previewUrl: attachment1.preview_url,
|
448
|
+
previewWidth: attachment1.preview_width,
|
449
|
+
previewHeight: attachment1.preview_height,
|
450
|
+
|
451
|
+
url: attachment1.url,
|
452
|
+
width: attachment1.metadata.dimensions.width,
|
453
|
+
height: attachment1.metadata.dimensions.height,
|
454
|
+
|
455
|
+
duration: attachment1.metadata.duration,
|
456
|
+
videoType: "unknown",
|
457
|
+
|
458
|
+
thumbnailUrl: attachment1.thumbnail_url // @Legacy
|
459
|
+
};
|
460
|
+
case "error":
|
461
|
+
return {
|
462
|
+
type: "error",
|
463
|
+
|
464
|
+
// Save error attachments because we're unsure of their format,
|
465
|
+
// and whether there are cases they contain something useful for debugging.
|
466
|
+
attachment1: attachment1,
|
467
|
+
attachment2: attachment2
|
468
|
+
};
|
469
|
+
case "MessageImage":
|
470
|
+
return {
|
471
|
+
type: "photo",
|
472
|
+
ID: blob.legacy_attachment_id,
|
473
|
+
filename: blob.filename,
|
474
|
+
thumbnailUrl: blob.thumbnail.uri,
|
475
|
+
|
476
|
+
previewUrl: blob.preview.uri,
|
477
|
+
previewWidth: blob.preview.width,
|
478
|
+
previewHeight: blob.preview.height,
|
479
|
+
|
480
|
+
largePreviewUrl: blob.large_preview.uri,
|
481
|
+
largePreviewWidth: blob.large_preview.width,
|
482
|
+
largePreviewHeight: blob.large_preview.height,
|
483
|
+
|
484
|
+
url: blob.large_preview.uri, // @Legacy
|
485
|
+
width: blob.original_dimensions.x, // @Legacy
|
486
|
+
height: blob.original_dimensions.y, // @Legacy
|
487
|
+
name: blob.filename // @Legacy
|
488
|
+
};
|
489
|
+
case "MessageAnimatedImage":
|
490
|
+
return {
|
491
|
+
type: "animated_image",
|
492
|
+
ID: blob.legacy_attachment_id,
|
493
|
+
filename: blob.filename,
|
494
|
+
|
495
|
+
previewUrl: blob.preview_image.uri,
|
496
|
+
previewWidth: blob.preview_image.width,
|
497
|
+
previewHeight: blob.preview_image.height,
|
498
|
+
|
499
|
+
url: blob.animated_image.uri,
|
500
|
+
width: blob.animated_image.width,
|
501
|
+
height: blob.animated_image.height,
|
502
|
+
|
503
|
+
thumbnailUrl: blob.preview_image.uri, // @Legacy
|
504
|
+
name: blob.filename, // @Legacy
|
505
|
+
facebookUrl: blob.animated_image.uri, // @Legacy
|
506
|
+
rawGifImage: blob.animated_image.uri, // @Legacy
|
507
|
+
animatedGifUrl: blob.animated_image.uri, // @Legacy
|
508
|
+
animatedGifPreviewUrl: blob.preview_image.uri, // @Legacy
|
509
|
+
animatedWebpUrl: blob.animated_image.uri, // @Legacy
|
510
|
+
animatedWebpPreviewUrl: blob.preview_image.uri // @Legacy
|
511
|
+
};
|
512
|
+
case "MessageVideo":
|
513
|
+
return {
|
514
|
+
type: "video",
|
515
|
+
filename: blob.filename,
|
516
|
+
ID: blob.legacy_attachment_id,
|
517
|
+
|
518
|
+
previewUrl: blob.large_image.uri,
|
519
|
+
previewWidth: blob.large_image.width,
|
520
|
+
previewHeight: blob.large_image.height,
|
521
|
+
|
522
|
+
url: blob.playable_url,
|
523
|
+
width: blob.original_dimensions.x,
|
524
|
+
height: blob.original_dimensions.y,
|
525
|
+
|
526
|
+
duration: blob.playable_duration_in_ms,
|
527
|
+
videoType: blob.video_type.toLowerCase(),
|
528
|
+
|
529
|
+
thumbnailUrl: blob.large_image.uri // @Legacy
|
530
|
+
};
|
531
|
+
case "MessageAudio":
|
532
|
+
return {
|
533
|
+
type: "audio",
|
534
|
+
filename: blob.filename,
|
535
|
+
ID: blob.url_shimhash,
|
536
|
+
|
537
|
+
audioType: blob.audio_type,
|
538
|
+
duration: blob.playable_duration_in_ms,
|
539
|
+
url: blob.playable_url,
|
540
|
+
|
541
|
+
isVoiceMail: blob.is_voicemail
|
542
|
+
};
|
543
|
+
case "StickerAttachment":
|
544
|
+
return {
|
545
|
+
type: "sticker",
|
546
|
+
ID: blob.id,
|
547
|
+
url: blob.url,
|
548
|
+
|
549
|
+
packID: blob.pack ? blob.pack.id : null,
|
550
|
+
spriteUrl: blob.sprite_image,
|
551
|
+
spriteUrl2x: blob.sprite_image_2x,
|
552
|
+
width: blob.width,
|
553
|
+
height: blob.height,
|
554
|
+
|
555
|
+
caption: blob.label,
|
556
|
+
description: blob.label,
|
557
|
+
|
558
|
+
frameCount: blob.frame_count,
|
559
|
+
frameRate: blob.frame_rate,
|
560
|
+
framesPerRow: blob.frames_per_row,
|
561
|
+
framesPerCol: blob.frames_per_column,
|
562
|
+
|
563
|
+
stickerID: blob.id, // @Legacy
|
564
|
+
spriteURI: blob.sprite_image, // @Legacy
|
565
|
+
spriteURI2x: blob.sprite_image_2x // @Legacy
|
566
|
+
};
|
567
|
+
case "MessageLocation":
|
568
|
+
var urlAttach = blob.story_attachment.url;
|
569
|
+
var mediaAttach = blob.story_attachment.media;
|
570
|
+
|
571
|
+
var u = querystring.parse(url.parse(urlAttach).query).u;
|
572
|
+
var where1 = querystring.parse(url.parse(u).query).where1;
|
573
|
+
var address = where1.split(", ");
|
574
|
+
|
575
|
+
var latitude;
|
576
|
+
var longitude;
|
577
|
+
|
578
|
+
try {
|
579
|
+
latitude = Number.parseFloat(address[0]);
|
580
|
+
longitude = Number.parseFloat(address[1]);
|
581
|
+
} catch (err) {
|
582
|
+
/* empty */
|
583
|
+
}
|
594
584
|
|
595
|
-
|
596
|
-
|
597
|
-
|
585
|
+
var imageUrl;
|
586
|
+
var width;
|
587
|
+
var height;
|
598
588
|
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
589
|
+
if (mediaAttach && mediaAttach.image) {
|
590
|
+
imageUrl = mediaAttach.image.uri;
|
591
|
+
width = mediaAttach.image.width;
|
592
|
+
height = mediaAttach.image.height;
|
593
|
+
}
|
604
594
|
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
default:
|
682
|
-
throw new Error(
|
683
|
-
"unrecognized attach_file of type " +
|
684
|
-
type +
|
685
|
-
"`" +
|
686
|
-
JSON.stringify(attachment1, null, 4) +
|
687
|
-
" attachment2: " +
|
688
|
-
JSON.stringify(attachment2, null, 4) +
|
689
|
-
"`"
|
690
|
-
);
|
691
|
-
}
|
595
|
+
return {
|
596
|
+
type: "location",
|
597
|
+
ID: blob.legacy_attachment_id,
|
598
|
+
latitude: latitude,
|
599
|
+
longitude: longitude,
|
600
|
+
image: imageUrl,
|
601
|
+
width: width,
|
602
|
+
height: height,
|
603
|
+
url: u || urlAttach,
|
604
|
+
address: where1,
|
605
|
+
|
606
|
+
facebookUrl: blob.story_attachment.url, // @Legacy
|
607
|
+
target: blob.story_attachment.target, // @Legacy
|
608
|
+
styleList: blob.story_attachment.style_list // @Legacy
|
609
|
+
};
|
610
|
+
case "ExtensibleAttachment":
|
611
|
+
return {
|
612
|
+
type: "share",
|
613
|
+
ID: blob.legacy_attachment_id,
|
614
|
+
url: blob.story_attachment.url,
|
615
|
+
|
616
|
+
title: blob.story_attachment.title_with_entities.text,
|
617
|
+
description: blob.story_attachment.description &&
|
618
|
+
blob.story_attachment.description.text,
|
619
|
+
source: blob.story_attachment.source ? blob.story_attachment.source.text : null,
|
620
|
+
|
621
|
+
image: blob.story_attachment.media &&
|
622
|
+
blob.story_attachment.media.image &&
|
623
|
+
blob.story_attachment.media.image.uri,
|
624
|
+
width: blob.story_attachment.media &&
|
625
|
+
blob.story_attachment.media.image &&
|
626
|
+
blob.story_attachment.media.image.width,
|
627
|
+
height: blob.story_attachment.media &&
|
628
|
+
blob.story_attachment.media.image &&
|
629
|
+
blob.story_attachment.media.image.height,
|
630
|
+
playable: blob.story_attachment.media &&
|
631
|
+
blob.story_attachment.media.is_playable,
|
632
|
+
duration: blob.story_attachment.media &&
|
633
|
+
blob.story_attachment.media.playable_duration_in_ms,
|
634
|
+
playableUrl: blob.story_attachment.media == null ? null : blob.story_attachment.media.playable_url,
|
635
|
+
|
636
|
+
subattachments: blob.story_attachment.subattachments,
|
637
|
+
properties: blob.story_attachment.properties.reduce(function(obj, cur) {
|
638
|
+
obj[cur.key] = cur.value.text;
|
639
|
+
return obj;
|
640
|
+
}, {}),
|
641
|
+
|
642
|
+
facebookUrl: blob.story_attachment.url, // @Legacy
|
643
|
+
target: blob.story_attachment.target, // @Legacy
|
644
|
+
styleList: blob.story_attachment.style_list // @Legacy
|
645
|
+
};
|
646
|
+
case "MessageFile":
|
647
|
+
return {
|
648
|
+
type: "file",
|
649
|
+
filename: blob.filename,
|
650
|
+
ID: blob.message_file_fbid,
|
651
|
+
|
652
|
+
url: blob.url,
|
653
|
+
isMalicious: blob.is_malicious,
|
654
|
+
contentType: blob.content_type,
|
655
|
+
|
656
|
+
name: blob.filename,
|
657
|
+
mimeType: "",
|
658
|
+
fileSize: -1
|
659
|
+
};
|
660
|
+
default:
|
661
|
+
throw new Error(
|
662
|
+
"unrecognized attach_file of type " +
|
663
|
+
type +
|
664
|
+
"`" +
|
665
|
+
JSON.stringify(attachment1, null, 4) +
|
666
|
+
" attachment2: " +
|
667
|
+
JSON.stringify(attachment2, null, 4) +
|
668
|
+
"`"
|
669
|
+
);
|
670
|
+
}
|
692
671
|
}
|
693
672
|
|
694
673
|
function formatAttachment(attachments, attachmentIds, attachmentMap, shareMap) {
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
})
|
707
|
-
: [];
|
674
|
+
attachmentMap = shareMap || attachmentMap;
|
675
|
+
return attachments ?
|
676
|
+
attachments.map(function(val, i) {
|
677
|
+
if (!attachmentMap ||
|
678
|
+
!attachmentIds ||
|
679
|
+
!attachmentMap[attachmentIds[i]]
|
680
|
+
) {
|
681
|
+
return _formatAttachment(val);
|
682
|
+
}
|
683
|
+
return _formatAttachment(val, attachmentMap[attachmentIds[i]]);
|
684
|
+
}) : [];
|
708
685
|
}
|
709
686
|
|
710
687
|
function formatDeltaMessage(m) {
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
attachments: (m.delta.attachments || []).map(v => _formatAttachment(v)),
|
738
|
-
mentions: mentions,
|
739
|
-
timestamp: md.timestamp,
|
740
|
-
isGroup: !!md.threadKey.threadFbId,
|
741
|
-
participantIDs: m.delta.participants || []
|
742
|
-
};
|
688
|
+
var md = m.delta.messageMetadata;
|
689
|
+
var mdata =
|
690
|
+
m.delta.data === undefined ? [] :
|
691
|
+
m.delta.data.prng === undefined ? [] :
|
692
|
+
JSON.parse(m.delta.data.prng);
|
693
|
+
var m_id = mdata.map(u => u.i);
|
694
|
+
var m_offset = mdata.map(u => u.o);
|
695
|
+
var m_length = mdata.map(u => u.l);
|
696
|
+
var mentions = {};
|
697
|
+
var body = m.delta.body || "";
|
698
|
+
var args = body == "" ? [] : body.trim().split(/\s+/);
|
699
|
+
for (var i = 0; i < m_id.length; i++) mentions[m_id[i]] = m.delta.body.substring(m_offset[i], m_offset[i] + m_length[i]);
|
700
|
+
|
701
|
+
return {
|
702
|
+
type: "message",
|
703
|
+
senderID: formatID(md.actorFbId.toString()),
|
704
|
+
threadID: formatID((md.threadKey.threadFbId || md.threadKey.otherUserFbId).toString()),
|
705
|
+
messageID: md.messageId,
|
706
|
+
args: args,
|
707
|
+
body: body,
|
708
|
+
attachments: (m.delta.attachments || []).map(v => _formatAttachment(v)),
|
709
|
+
mentions: mentions,
|
710
|
+
timestamp: md.timestamp,
|
711
|
+
isGroup: !!md.threadKey.threadFbId,
|
712
|
+
participantIDs: m.delta.participants || []
|
713
|
+
};
|
743
714
|
}
|
744
715
|
|
745
716
|
function formatID(id) {
|
746
|
-
|
747
|
-
|
717
|
+
if (id != undefined && id != null) return id.replace(/(fb)?id[:.]/, "");
|
718
|
+
else return id;
|
748
719
|
}
|
749
720
|
|
750
721
|
function formatMessage(m) {
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
timestampRelative: originalMessage.timestamp_relative,
|
786
|
-
timestampDatetime: originalMessage.timestamp_datetime,
|
787
|
-
tags: originalMessage.tags,
|
788
|
-
reactions: originalMessage.reactions ? originalMessage.reactions : [],
|
789
|
-
isUnread: originalMessage.is_unread
|
790
|
-
};
|
791
|
-
|
792
|
-
if (m.type === "pages_messaging")
|
793
|
-
obj.pageID = m.realtime_viewer_fbid.toString();
|
794
|
-
obj.isGroup = obj.participantIDs.length > 2;
|
795
|
-
|
796
|
-
return obj;
|
722
|
+
var originalMessage = m.message ? m.message : m;
|
723
|
+
var obj = {
|
724
|
+
type: "message",
|
725
|
+
senderName: originalMessage.sender_name,
|
726
|
+
senderID: formatID(originalMessage.sender_fbid.toString()),
|
727
|
+
participantNames: originalMessage.group_thread_info ? originalMessage.group_thread_info.participant_names : [originalMessage.sender_name.split(" ")[0]],
|
728
|
+
participantIDs: originalMessage.group_thread_info ?
|
729
|
+
originalMessage.group_thread_info.participant_ids.map(function(v) {
|
730
|
+
return formatID(v.toString());
|
731
|
+
}) : [formatID(originalMessage.sender_fbid)],
|
732
|
+
body: originalMessage.body || "",
|
733
|
+
threadID: formatID((originalMessage.thread_fbid || originalMessage.other_user_fbid).toString()),
|
734
|
+
threadName: originalMessage.group_thread_info ? originalMessage.group_thread_info.name : originalMessage.sender_name,
|
735
|
+
location: originalMessage.coordinates ? originalMessage.coordinates : null,
|
736
|
+
messageID: originalMessage.mid ? originalMessage.mid.toString() : originalMessage.message_id,
|
737
|
+
attachments: formatAttachment(
|
738
|
+
originalMessage.attachments,
|
739
|
+
originalMessage.attachmentIds,
|
740
|
+
originalMessage.attachment_map,
|
741
|
+
originalMessage.share_map
|
742
|
+
),
|
743
|
+
timestamp: originalMessage.timestamp,
|
744
|
+
timestampAbsolute: originalMessage.timestamp_absolute,
|
745
|
+
timestampRelative: originalMessage.timestamp_relative,
|
746
|
+
timestampDatetime: originalMessage.timestamp_datetime,
|
747
|
+
tags: originalMessage.tags,
|
748
|
+
reactions: originalMessage.reactions ? originalMessage.reactions : [],
|
749
|
+
isUnread: originalMessage.is_unread
|
750
|
+
};
|
751
|
+
|
752
|
+
if (m.type === "pages_messaging") obj.pageID = m.realtime_viewer_fbid.toString();
|
753
|
+
obj.isGroup = obj.participantIDs.length > 2;
|
754
|
+
|
755
|
+
return obj;
|
797
756
|
}
|
798
757
|
|
799
758
|
function formatEvent(m) {
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
logMessageBody: originalMessage.log_message_body
|
815
|
-
});
|
759
|
+
var originalMessage = m.message ? m.message : m;
|
760
|
+
var logMessageType = originalMessage.log_message_type;
|
761
|
+
var logMessageData;
|
762
|
+
if (logMessageType === "log:generic-admin-text") {
|
763
|
+
logMessageData = originalMessage.log_message_data.untypedData;
|
764
|
+
logMessageType = getAdminTextMessageType(originalMessage.log_message_data.message_type);
|
765
|
+
} else logMessageData = originalMessage.log_message_data;
|
766
|
+
|
767
|
+
return Object.assign(formatMessage(originalMessage), {
|
768
|
+
type: "event",
|
769
|
+
logMessageType: logMessageType,
|
770
|
+
logMessageData: logMessageData,
|
771
|
+
logMessageBody: originalMessage.log_message_body
|
772
|
+
});
|
816
773
|
}
|
817
774
|
|
818
775
|
function formatHistoryMessage(m) {
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
776
|
+
switch (m.action_type) {
|
777
|
+
case "ma-type:log-message":
|
778
|
+
return formatEvent(m);
|
779
|
+
default:
|
780
|
+
return formatMessage(m);
|
781
|
+
}
|
825
782
|
}
|
826
783
|
|
827
784
|
// Get a more readable message type for AdminTextMessages
|
828
785
|
function getAdminTextMessageType(m) {
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
786
|
+
switch (m.type) {
|
787
|
+
case "change_thread_theme":
|
788
|
+
return "log:thread-color";
|
789
|
+
case "change_thread_icon":
|
790
|
+
return "log:thread-icon";
|
791
|
+
case "change_thread_nickname":
|
792
|
+
return "log:user-nickname";
|
793
|
+
case "change_thread_admins":
|
794
|
+
return "log:thread-admins";
|
795
|
+
case "group_poll":
|
796
|
+
return "log:thread-poll";
|
797
|
+
case "change_thread_approval_mode":
|
798
|
+
return "log:thread-approval-mode";
|
799
|
+
case "messenger_call_log":
|
800
|
+
case "participant_joined_group_call":
|
801
|
+
return "log:thread-call";
|
802
|
+
}
|
846
803
|
}
|
847
804
|
|
848
805
|
function formatDeltaEvent(m) {
|
849
|
-
|
850
|
-
|
851
|
-
|
806
|
+
var { updateData,getData,hasData } = require('./Extra/ExtraGetThread');
|
807
|
+
var logMessageType;
|
808
|
+
var logMessageData;
|
852
809
|
|
853
|
-
|
810
|
+
switch (m.class) {
|
854
811
|
case "AdminTextMessage":
|
855
|
-
|
856
|
-
|
857
|
-
|
812
|
+
logMessageType = getAdminTextMessageType(m);
|
813
|
+
logMessageData = m.untypedData;
|
814
|
+
break;
|
858
815
|
case "ThreadName":
|
859
|
-
|
860
|
-
|
861
|
-
|
816
|
+
logMessageType = "log:thread-name";
|
817
|
+
logMessageData = { name: m.name };
|
818
|
+
break;
|
862
819
|
case "ParticipantsAddedToGroupThread":
|
863
|
-
|
864
|
-
|
865
|
-
|
820
|
+
logMessageType = "log:subscribe";
|
821
|
+
logMessageData = { addedParticipants: m.addedParticipants };
|
822
|
+
break;
|
866
823
|
case "ParticipantLeftGroupThread":
|
867
|
-
|
868
|
-
|
869
|
-
|
824
|
+
logMessageType = "log:unsubscribe";
|
825
|
+
logMessageData = { leftParticipantFbId: m.leftParticipantFbId };
|
826
|
+
break;
|
870
827
|
case "UserLocation": {
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
.
|
876
|
-
|
877
|
-
|
878
|
-
.location_title,
|
879
|
-
coordinates:
|
880
|
-
m.attachments[0].mercury.extensible_attachment.story_attachment.target
|
881
|
-
.coordinate,
|
882
|
-
url: m.attachments[0].mercury.extensible_attachment.story_attachment.url
|
883
|
-
};
|
828
|
+
logMessageType = "log:user-location";
|
829
|
+
logMessageData = {
|
830
|
+
Image: m.attachments[0].mercury.extensible_attachment.story_attachment.media.image,
|
831
|
+
Location: m.attachments[0].mercury.extensible_attachment.story_attachment.target.location_title,
|
832
|
+
coordinates: m.attachments[0].mercury.extensible_attachment.story_attachment.target.coordinate,
|
833
|
+
url: m.attachments[0].mercury.extensible_attachment.story_attachment.url
|
834
|
+
};
|
884
835
|
}
|
885
|
-
|
886
|
-
|
887
|
-
formatID(
|
888
|
-
(
|
889
|
-
m.messageMetadata.threadKey.threadFbId ||
|
890
|
-
m.messageMetadata.threadKey.otherUserFbId
|
891
|
-
).toString()
|
892
|
-
)
|
893
|
-
)) {
|
836
|
+
}
|
837
|
+
switch (hasData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()))) {
|
894
838
|
case true: {
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
(
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
updateData(
|
909
|
-
formatID(
|
910
|
-
(
|
911
|
-
m.messageMetadata.threadKey.threadFbId ||
|
912
|
-
m.messageMetadata.threadKey.otherUserFbId
|
913
|
-
).toString()
|
914
|
-
),
|
915
|
-
x
|
916
|
-
);
|
917
|
-
}
|
918
|
-
break;
|
919
|
-
case "log:thread-icon":
|
920
|
-
{
|
921
|
-
let x = getData(
|
922
|
-
formatID(
|
923
|
-
(
|
924
|
-
m.messageMetadata.threadKey.threadFbId ||
|
925
|
-
m.messageMetadata.threadKey.otherUserFbId
|
926
|
-
).toString()
|
927
|
-
)
|
928
|
-
);
|
929
|
-
x.emoji = logMessageData["thread_icon"] || x.emoji;
|
930
|
-
updateData(
|
931
|
-
formatID(
|
932
|
-
(
|
933
|
-
m.messageMetadata.threadKey.threadFbId ||
|
934
|
-
m.messageMetadata.threadKey.otherUserFbId
|
935
|
-
).toString()
|
936
|
-
),
|
937
|
-
x
|
938
|
-
);
|
939
|
-
}
|
940
|
-
break;
|
941
|
-
case "log:user-nickname":
|
942
|
-
{
|
943
|
-
let x = getData(
|
944
|
-
formatID(
|
945
|
-
(
|
946
|
-
m.messageMetadata.threadKey.threadFbId ||
|
947
|
-
m.messageMetadata.threadKey.otherUserFbId
|
948
|
-
).toString()
|
949
|
-
)
|
950
|
-
);
|
951
|
-
x.nicknames[logMessageData.participant_id] =
|
952
|
-
logMessageData.nickname.length == 0
|
953
|
-
? x.userInfo.find(
|
954
|
-
i => i.id == String(logMessageData.participant_id)
|
955
|
-
).name
|
956
|
-
: logMessageData.nickname;
|
957
|
-
updateData(
|
958
|
-
formatID(
|
959
|
-
(
|
960
|
-
m.messageMetadata.threadKey.threadFbId ||
|
961
|
-
m.messageMetadata.threadKey.otherUserFbId
|
962
|
-
).toString()
|
963
|
-
),
|
964
|
-
x
|
965
|
-
);
|
966
|
-
}
|
967
|
-
break;
|
968
|
-
case "log:thread-admins":
|
969
|
-
{
|
970
|
-
let x = getData(
|
971
|
-
formatID(
|
972
|
-
(
|
973
|
-
m.messageMetadata.threadKey.threadFbId ||
|
974
|
-
m.messageMetadata.threadKey.otherUserFbId
|
975
|
-
).toString()
|
976
|
-
)
|
977
|
-
);
|
978
|
-
switch (logMessageData.ADMIN_EVENT) {
|
979
|
-
case "add_admin":
|
980
|
-
{
|
981
|
-
x.adminIDs.push({ id: logMessageData.TARGET_ID });
|
982
|
-
}
|
839
|
+
switch (logMessageType) {
|
840
|
+
case "log:thread-color": {
|
841
|
+
let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
842
|
+
x.emoji = (logMessageData.theme_emoji || x.emoji);
|
843
|
+
x.color = (logMessageData['theme_color'] || x.color);
|
844
|
+
updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
|
845
|
+
}
|
846
|
+
break;
|
847
|
+
case "log:thread-icon": {
|
848
|
+
let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
849
|
+
x.emoji = (logMessageData['thread_icon'] || x.emoji);
|
850
|
+
updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
|
851
|
+
}
|
983
852
|
break;
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
853
|
+
case "log:user-nickname": {
|
854
|
+
let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
855
|
+
x.nicknames[logMessageData.participant_id] = (logMessageData.nickname.length == 0 ? x.userInfo.find(i => i.id == String(logMessageData.participant_id)).name : logMessageData.nickname);
|
856
|
+
updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
|
857
|
+
}
|
858
|
+
break;
|
859
|
+
case "log:thread-admins": {
|
860
|
+
let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
861
|
+
switch (logMessageData.ADMIN_EVENT) {
|
862
|
+
case "add_admin": {
|
863
|
+
x.adminIDs.push({ id: logMessageData.TARGET_ID });
|
864
|
+
}
|
865
|
+
break;
|
866
|
+
case "remove_admin": {
|
867
|
+
x.adminIDs = x.adminIDs.filter(item => item.id != logMessageData.TARGET_ID);
|
868
|
+
}
|
869
|
+
break;
|
989
870
|
}
|
871
|
+
updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
|
872
|
+
}
|
990
873
|
break;
|
874
|
+
case "log:thread-approval-mode": {
|
875
|
+
let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
876
|
+
if (x.approvalMode == true) {
|
877
|
+
x.approvalMode = false;
|
878
|
+
}
|
879
|
+
else {
|
880
|
+
x.approvalMode = true;
|
881
|
+
}
|
882
|
+
updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
|
991
883
|
}
|
992
|
-
|
993
|
-
|
994
|
-
(
|
995
|
-
|
996
|
-
|
997
|
-
).toString()
|
998
|
-
),
|
999
|
-
x
|
1000
|
-
);
|
1001
|
-
}
|
1002
|
-
break;
|
1003
|
-
case "log:thread-approval-mode":
|
1004
|
-
{
|
1005
|
-
let x = getData(
|
1006
|
-
formatID(
|
1007
|
-
(
|
1008
|
-
m.messageMetadata.threadKey.threadFbId ||
|
1009
|
-
m.messageMetadata.threadKey.otherUserFbId
|
1010
|
-
).toString()
|
1011
|
-
)
|
1012
|
-
);
|
1013
|
-
if (x.approvalMode == true) {
|
1014
|
-
x.approvalMode = false;
|
1015
|
-
} else {
|
1016
|
-
x.approvalMode = true;
|
884
|
+
break;
|
885
|
+
case "log:thread-name": {
|
886
|
+
let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
887
|
+
x.threadName = (logMessageData.name || formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
888
|
+
updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
|
1017
889
|
}
|
1018
|
-
|
1019
|
-
|
1020
|
-
(
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
(
|
1034
|
-
m.messageMetadata.threadKey.threadFbId ||
|
1035
|
-
m.messageMetadata.threadKey.otherUserFbId
|
1036
|
-
).toString()
|
1037
|
-
)
|
1038
|
-
);
|
1039
|
-
x.threadName =
|
1040
|
-
logMessageData.name ||
|
1041
|
-
formatID(
|
1042
|
-
(
|
1043
|
-
m.messageMetadata.threadKey.threadFbId ||
|
1044
|
-
m.messageMetadata.threadKey.otherUserFbId
|
1045
|
-
).toString()
|
1046
|
-
);
|
1047
|
-
updateData(
|
1048
|
-
formatID(
|
1049
|
-
(
|
1050
|
-
m.messageMetadata.threadKey.threadFbId ||
|
1051
|
-
m.messageMetadata.threadKey.otherUserFbId
|
1052
|
-
).toString()
|
1053
|
-
),
|
1054
|
-
x
|
1055
|
-
);
|
1056
|
-
}
|
1057
|
-
break;
|
1058
|
-
case "log:subscribe":
|
1059
|
-
{
|
1060
|
-
let x = getData(
|
1061
|
-
formatID(
|
1062
|
-
(
|
1063
|
-
m.messageMetadata.threadKey.threadFbId ||
|
1064
|
-
m.messageMetadata.threadKey.otherUserFbId
|
1065
|
-
).toString()
|
1066
|
-
)
|
1067
|
-
);
|
1068
|
-
for (let o of logMessageData.addedParticipants) {
|
1069
|
-
if (x.userInfo.some(i => i.id == o.userFbId)) continue;
|
1070
|
-
else {
|
1071
|
-
x.userInfo.push({
|
1072
|
-
id: o.userFbId,
|
1073
|
-
name: o.fullName,
|
1074
|
-
gender: getGenderByPhysicalMethod(o.fullName)
|
1075
|
-
});
|
1076
|
-
x.participantIDs.push(o.userFbId);
|
1077
|
-
}
|
890
|
+
break;
|
891
|
+
case "log:subscribe": {
|
892
|
+
let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
893
|
+
for (let o of logMessageData.addedParticipants) {
|
894
|
+
if (x.userInfo.some(i => i.id == o.userFbId)) continue;
|
895
|
+
else {
|
896
|
+
x.userInfo.push({
|
897
|
+
id: o.userFbId,
|
898
|
+
name: o.fullName,
|
899
|
+
gender: getGenderByPhysicalMethod(o.fullName)
|
900
|
+
});
|
901
|
+
x.participantIDs.push(o.userFbId);
|
902
|
+
}
|
903
|
+
}
|
904
|
+
updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
|
1078
905
|
}
|
1079
|
-
|
1080
|
-
|
1081
|
-
(
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
}
|
1089
|
-
break;
|
1090
|
-
case "log:unsubscribe":
|
1091
|
-
{
|
1092
|
-
let x = getData(
|
1093
|
-
formatID(
|
1094
|
-
(
|
1095
|
-
m.messageMetadata.threadKey.threadFbId ||
|
1096
|
-
m.messageMetadata.threadKey.otherUserFbId
|
1097
|
-
).toString()
|
1098
|
-
)
|
1099
|
-
);
|
1100
|
-
x.participantIDs = x.participantIDs.filter(
|
1101
|
-
item => item != logMessageData.leftParticipantFbId
|
1102
|
-
);
|
1103
|
-
x.userInfo = x.userInfo.filter(
|
1104
|
-
item => item.id != logMessageData.leftParticipantFbId
|
1105
|
-
);
|
1106
|
-
if (
|
1107
|
-
x.adminIDs.some(i => i.id == logMessageData.leftParticipantFbId)
|
1108
|
-
) {
|
1109
|
-
x.adminIDs = x.adminIDs.filter(
|
1110
|
-
item => item.id != logMessageData.leftParticipantFbId
|
1111
|
-
);
|
906
|
+
break;
|
907
|
+
case "log:unsubscribe": {
|
908
|
+
let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
|
909
|
+
x.participantIDs = x.participantIDs.filter(item => item != logMessageData.leftParticipantFbId);
|
910
|
+
x.userInfo = x.userInfo.filter(item => item.id != logMessageData.leftParticipantFbId);
|
911
|
+
if (x.adminIDs.some(i => i.id == logMessageData.leftParticipantFbId)) {
|
912
|
+
x.adminIDs = x.adminIDs.filter(item => item.id != logMessageData.leftParticipantFbId);
|
913
|
+
}
|
914
|
+
updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
|
1112
915
|
}
|
1113
|
-
|
1114
|
-
|
1115
|
-
(
|
1116
|
-
m.messageMetadata.threadKey.threadFbId ||
|
1117
|
-
m.messageMetadata.threadKey.otherUserFbId
|
1118
|
-
).toString()
|
1119
|
-
),
|
1120
|
-
x
|
1121
|
-
);
|
1122
|
-
}
|
1123
|
-
break;
|
1124
|
-
}
|
916
|
+
break;
|
917
|
+
}
|
1125
918
|
}
|
1126
|
-
|
919
|
+
}
|
1127
920
|
|
1128
|
-
|
921
|
+
return {
|
1129
922
|
type: "event",
|
1130
|
-
threadID: formatID(
|
1131
|
-
(
|
1132
|
-
m.messageMetadata.threadKey.threadFbId ||
|
1133
|
-
m.messageMetadata.threadKey.otherUserFbId
|
1134
|
-
).toString()
|
1135
|
-
),
|
923
|
+
threadID: formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),
|
1136
924
|
logMessageType: logMessageType,
|
1137
925
|
logMessageData: logMessageData,
|
1138
926
|
logMessageBody: m.messageMetadata.adminText,
|
1139
927
|
author: m.messageMetadata.actorFbId,
|
1140
928
|
participantIDs: m.participants || []
|
1141
|
-
|
929
|
+
};
|
1142
930
|
}
|
1143
931
|
|
1144
932
|
/**
|
@@ -1146,482 +934,399 @@ function formatDeltaEvent(m) {
|
|
1146
934
|
*/
|
1147
935
|
|
1148
936
|
function formatTyp(event) {
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
type: "typ"
|
1160
|
-
};
|
937
|
+
return {
|
938
|
+
isTyping: !!event.st,
|
939
|
+
from: event.from.toString(),
|
940
|
+
threadID: formatID((event.to || event.thread_fbid || event.from).toString()),
|
941
|
+
// When receiving typ indication from mobile, `from_mobile` isn't set.
|
942
|
+
// If it is, we just use that value.
|
943
|
+
fromMobile: event.hasOwnProperty("from_mobile") ? event.from_mobile : true,
|
944
|
+
userID: (event.realtime_viewer_fbid || event.from).toString(),
|
945
|
+
type: "typ"
|
946
|
+
};
|
1161
947
|
}
|
1162
948
|
|
1163
949
|
function formatDeltaReadReceipt(delta) {
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
type: "read_receipt"
|
1173
|
-
};
|
950
|
+
// otherUserFbId seems to be used as both the readerID and the threadID in a 1-1 chat.
|
951
|
+
// In a group chat actorFbId is used for the reader and threadFbId for the thread.
|
952
|
+
return {
|
953
|
+
reader: (delta.threadKey.otherUserFbId || delta.actorFbId).toString(),
|
954
|
+
time: delta.actionTimestampMs,
|
955
|
+
threadID: formatID((delta.threadKey.otherUserFbId || delta.threadKey.threadFbId).toString()),
|
956
|
+
type: "read_receipt"
|
957
|
+
};
|
1174
958
|
}
|
1175
959
|
|
1176
960
|
function formatReadReceipt(event) {
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
961
|
+
return {
|
962
|
+
reader: event.reader.toString(),
|
963
|
+
time: event.time,
|
964
|
+
threadID: formatID((event.thread_fbid || event.reader).toString()),
|
965
|
+
type: "read_receipt"
|
966
|
+
};
|
1183
967
|
}
|
1184
968
|
|
1185
969
|
function formatRead(event) {
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
).toString()
|
1192
|
-
),
|
1193
|
-
time: event.timestamp,
|
1194
|
-
type: "read"
|
1195
|
-
};
|
970
|
+
return {
|
971
|
+
threadID: formatID(((event.chat_ids && event.chat_ids[0]) || (event.thread_fbids && event.thread_fbids[0])).toString()),
|
972
|
+
time: event.timestamp,
|
973
|
+
type: "read"
|
974
|
+
};
|
1196
975
|
}
|
1197
976
|
|
1198
977
|
function getFrom(str, startToken, endToken) {
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
"Could not find endTime `" + endToken + "` in the given string."
|
1207
|
-
);
|
1208
|
-
return lastHalf.substring(0, end);
|
978
|
+
var start = str.indexOf(startToken) + startToken.length;
|
979
|
+
if (start < startToken.length) return "";
|
980
|
+
|
981
|
+
var lastHalf = str.substring(start);
|
982
|
+
var end = lastHalf.indexOf(endToken);
|
983
|
+
if (end === -1) throw Error("Could not find endTime `" + endToken + "` in the given string.");
|
984
|
+
return lastHalf.substring(0, end);
|
1209
985
|
}
|
1210
986
|
|
1211
987
|
function makeParsable(html) {
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
988
|
+
let withoutForLoop = html.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, "");
|
989
|
+
|
990
|
+
// (What the fuck FB, why windows style newlines?)
|
991
|
+
// So sometimes FB will send us base multiple objects in the same response.
|
992
|
+
// They're all valid JSON, one after the other, at the top level. We detect
|
993
|
+
// that and make it parse-able by JSON.parse.
|
994
|
+
// Ben - July 15th 2017
|
995
|
+
//
|
996
|
+
// It turns out that Facebook may insert random number of spaces before
|
997
|
+
// next object begins (issue #616)
|
998
|
+
// rav_kr - 2018-03-19
|
999
|
+
let maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
|
1000
|
+
if (maybeMultipleObjects.length === 1) return maybeMultipleObjects;
|
1001
|
+
|
1002
|
+
return "[" + maybeMultipleObjects.join("},{") + "]";
|
1227
1003
|
}
|
1228
1004
|
|
1229
1005
|
function arrToForm(form) {
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
);
|
1006
|
+
return arrayToObject(form,
|
1007
|
+
function(v) {
|
1008
|
+
return v.name;
|
1009
|
+
},
|
1010
|
+
function(v) {
|
1011
|
+
return v.val;
|
1012
|
+
}
|
1013
|
+
);
|
1239
1014
|
}
|
1240
1015
|
|
1241
1016
|
function arrayToObject(arr, getKey, getValue) {
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1017
|
+
return arr.reduce(function(acc, val) {
|
1018
|
+
acc[getKey(val)] = getValue(val);
|
1019
|
+
return acc;
|
1020
|
+
}, {});
|
1246
1021
|
}
|
1247
1022
|
|
1248
1023
|
function getSignatureID() {
|
1249
|
-
|
1024
|
+
return Math.floor(Math.random() * 2147483648).toString(16);
|
1250
1025
|
}
|
1251
1026
|
|
1252
1027
|
function generateTimestampRelative() {
|
1253
|
-
|
1254
|
-
|
1028
|
+
var d = new Date();
|
1029
|
+
return d.getHours() + ":" + padZeros(d.getMinutes());
|
1255
1030
|
}
|
1256
1031
|
|
1257
1032
|
function makeDefaults(html, userID, ctx) {
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
// @Hack Ok we've done hacky things, this is definitely on top 5.
|
1262
|
-
// We totally assume the object is flat and try parsing until a }.
|
1263
|
-
// If it works though it's cool because we get a bunch of extra data things.
|
1264
|
-
//
|
1265
|
-
// Update: we don't need this. Leaving it in in case we ever do.
|
1266
|
-
// Ben - July 15th 2017
|
1267
|
-
|
1268
|
-
// var siteData = getFrom(html, "[\"SiteData\",[],", "},");
|
1269
|
-
// try {
|
1270
|
-
// siteData = JSON.parse(siteData + "}");
|
1271
|
-
// } catch(e) {
|
1272
|
-
// log.warn("makeDefaults", "Couldn't parse SiteData. Won't have access to some variables.");
|
1273
|
-
// siteData = {};
|
1274
|
-
// }
|
1275
|
-
|
1276
|
-
var ttstamp = "2";
|
1277
|
-
for (var i = 0; i < fb_dtsg.length; i++) ttstamp += fb_dtsg.charCodeAt(i);
|
1278
|
-
var revision = getFrom(html, 'revision":', ",");
|
1279
|
-
|
1280
|
-
function mergeWithDefaults(obj) {
|
1281
|
-
// @TODO This is missing a key called __dyn.
|
1282
|
-
// After some investigation it seems like __dyn is some sort of set that FB
|
1283
|
-
// calls BitMap. It seems like certain responses have a "define" key in the
|
1284
|
-
// res.jsmods arrays. I think the code iterates over those and calls `set`
|
1285
|
-
// on the bitmap for each of those keys. Then it calls
|
1286
|
-
// bitmap.toCompressedString() which returns what __dyn is.
|
1287
|
-
//
|
1288
|
-
// So far the API has been working without this.
|
1289
|
-
//
|
1290
|
-
// Ben - July 15th 2017
|
1291
|
-
var newObj = {
|
1292
|
-
__user: userID,
|
1293
|
-
__req: (reqCounter++).toString(36),
|
1294
|
-
__rev: revision,
|
1295
|
-
__a: 1,
|
1296
|
-
// __af: siteData.features,
|
1297
|
-
fb_dtsg: ctx.fb_dtsg ? ctx.fb_dtsg : fb_dtsg,
|
1298
|
-
jazoest: ctx.ttstamp ? ctx.ttstamp : ttstamp
|
1299
|
-
// __spin_r: siteData.__spin_r,
|
1300
|
-
// __spin_b: siteData.__spin_b,
|
1301
|
-
// __spin_t: siteData.__spin_t,
|
1302
|
-
};
|
1033
|
+
var reqCounter = 1;
|
1034
|
+
var fb_dtsg = getFrom(html, 'name="fb_dtsg" value="', '"');
|
1303
1035
|
|
1304
|
-
// @
|
1305
|
-
//
|
1306
|
-
//
|
1307
|
-
//
|
1308
|
-
//
|
1309
|
-
//
|
1310
|
-
|
1036
|
+
// @Hack Ok we've done hacky things, this is definitely on top 5.
|
1037
|
+
// We totally assume the object is flat and try parsing until a }.
|
1038
|
+
// If it works though it's cool because we get a bunch of extra data things.
|
1039
|
+
//
|
1040
|
+
// Update: we don't need this. Leaving it in in case we ever do.
|
1041
|
+
// Ben - July 15th 2017
|
1042
|
+
|
1043
|
+
// var siteData = getFrom(html, "[\"SiteData\",[],", "},");
|
1044
|
+
// try {
|
1045
|
+
// siteData = JSON.parse(siteData + "}");
|
1046
|
+
// } catch(e) {
|
1047
|
+
// log.warn("makeDefaults", "Couldn't parse SiteData. Won't have access to some variables.");
|
1048
|
+
// siteData = {};
|
1311
1049
|
// }
|
1312
1050
|
|
1313
|
-
|
1314
|
-
for (var
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1051
|
+
var ttstamp = "2";
|
1052
|
+
for (var i = 0; i < fb_dtsg.length; i++) ttstamp += fb_dtsg.charCodeAt(i);
|
1053
|
+
var revision = getFrom(html, 'revision":', ",");
|
1054
|
+
|
1055
|
+
function mergeWithDefaults(obj) {
|
1056
|
+
// @TODO This is missing a key called __dyn.
|
1057
|
+
// After some investigation it seems like __dyn is some sort of set that FB
|
1058
|
+
// calls BitMap. It seems like certain responses have a "define" key in the
|
1059
|
+
// res.jsmods arrays. I think the code iterates over those and calls `set`
|
1060
|
+
// on the bitmap for each of those keys. Then it calls
|
1061
|
+
// bitmap.toCompressedString() which returns what __dyn is.
|
1062
|
+
//
|
1063
|
+
// So far the API has been working without this.
|
1064
|
+
//
|
1065
|
+
// Ben - July 15th 2017
|
1066
|
+
var newObj = {
|
1067
|
+
__user: userID,
|
1068
|
+
__req: (reqCounter++).toString(36),
|
1069
|
+
__rev: revision,
|
1070
|
+
__a: 1,
|
1071
|
+
// __af: siteData.features,
|
1072
|
+
fb_dtsg: ctx.fb_dtsg ? ctx.fb_dtsg : fb_dtsg,
|
1073
|
+
jazoest: ctx.ttstamp ? ctx.ttstamp : ttstamp
|
1074
|
+
// __spin_r: siteData.__spin_r,
|
1075
|
+
// __spin_b: siteData.__spin_b,
|
1076
|
+
// __spin_t: siteData.__spin_t,
|
1077
|
+
};
|
1318
1078
|
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1079
|
+
// @TODO this is probably not needed.
|
1080
|
+
// Ben - July 15th 2017
|
1081
|
+
// if (siteData.be_key) {
|
1082
|
+
// newObj[siteData.be_key] = siteData.be_mode;
|
1083
|
+
// }
|
1084
|
+
// if (siteData.pkg_cohort_key) {
|
1085
|
+
// newObj[siteData.pkg_cohort_key] = siteData.pkg_cohort;
|
1086
|
+
// }
|
1087
|
+
|
1088
|
+
if (!obj) return newObj;
|
1089
|
+
for (var prop in obj)
|
1090
|
+
if (obj.hasOwnProperty(prop))
|
1091
|
+
if (!newObj[prop]) newObj[prop] = obj[prop];
|
1092
|
+
return newObj;
|
1093
|
+
}
|
1328
1094
|
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1095
|
+
function postWithDefaults(url, jar, form, ctxx) {
|
1096
|
+
return post(url, jar, mergeWithDefaults(form), ctx.globalOptions, ctxx || ctx);
|
1097
|
+
}
|
1332
1098
|
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
ctxx || ctx
|
1341
|
-
);
|
1342
|
-
}
|
1099
|
+
function getWithDefaults(url, jar, qs, ctxx) {
|
1100
|
+
return get(url, jar, mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
|
1101
|
+
}
|
1102
|
+
|
1103
|
+
function postFormDataWithDefault(url, jar, form, qs, ctxx) {
|
1104
|
+
return postFormData(url, jar, mergeWithDefaults(form), mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
|
1105
|
+
}
|
1343
1106
|
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1107
|
+
return {
|
1108
|
+
get: getWithDefaults,
|
1109
|
+
post: postWithDefaults,
|
1110
|
+
postFormData: postFormDataWithDefault
|
1111
|
+
};
|
1349
1112
|
}
|
1350
1113
|
|
1351
1114
|
function parseAndCheckLogin(ctx, defaultFuncs, retryCount) {
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
.then(() =>
|
1389
|
-
defaultFuncs.postFormData(url, ctx.jar, data.request.formData, {})
|
1390
|
-
)
|
1391
|
-
.then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
|
1392
|
-
} else {
|
1393
|
-
return bluebird
|
1394
|
-
.delay(retryTime)
|
1395
|
-
.then(() => defaultFuncs.post(url, ctx.jar, data.request.formData))
|
1396
|
-
.then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
|
1397
|
-
}
|
1398
|
-
}
|
1399
|
-
if (data.statusCode !== 200)
|
1400
|
-
throw new Error(
|
1401
|
-
"parseAndCheckLogin got status code: " +
|
1402
|
-
data.statusCode +
|
1403
|
-
". Bailing out of trying to parse response."
|
1404
|
-
);
|
1115
|
+
if (retryCount == undefined) retryCount = 0;
|
1116
|
+
return function(data) {
|
1117
|
+
return bluebird.try(function() {
|
1118
|
+
log.verbose("parseAndCheckLogin", data.body);
|
1119
|
+
if (data.statusCode >= 500 && data.statusCode < 600) {
|
1120
|
+
if (retryCount >= 5) {
|
1121
|
+
throw {
|
1122
|
+
error: "Request retry failed. Check the `res` and `statusCode` property on this error.",
|
1123
|
+
statusCode: data.statusCode,
|
1124
|
+
res: data.body
|
1125
|
+
};
|
1126
|
+
}
|
1127
|
+
retryCount++;
|
1128
|
+
var retryTime = Math.floor(Math.random() * 5000);
|
1129
|
+
log.warn("parseAndCheckLogin", "Got status code " + data.statusCode + " - " + retryCount + ". attempt to retry in " + retryTime + " milliseconds...");
|
1130
|
+
var url = data.request.uri.protocol + "//" + data.request.uri.hostname + data.request.uri.pathname;
|
1131
|
+
if (data.request.headers["Content-Type"].split(";")[0] === "multipart/form-data") {
|
1132
|
+
return bluebird.delay(retryTime).then(() => defaultFuncs.postFormData(url, ctx.jar, data.request.formData, {}))
|
1133
|
+
.then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
|
1134
|
+
} else {
|
1135
|
+
return bluebird.delay(retryTime).then(() => defaultFuncs.post(url, ctx.jar, data.request.formData))
|
1136
|
+
.then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
|
1137
|
+
}
|
1138
|
+
}
|
1139
|
+
if (data.statusCode !== 200) throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
|
1140
|
+
|
1141
|
+
var res = null;
|
1142
|
+
try {
|
1143
|
+
res = JSON.parse(makeParsable(data.body));
|
1144
|
+
} catch (e) {
|
1145
|
+
throw {
|
1146
|
+
error: "JSON.parse error. Check the `detail` property on this error.",
|
1147
|
+
detail: e,
|
1148
|
+
res: data.body
|
1149
|
+
};
|
1150
|
+
}
|
1405
1151
|
|
1406
|
-
|
1407
|
-
|
1408
|
-
res = JSON.parse(makeParsable(data.body));
|
1409
|
-
} catch (e) {
|
1410
|
-
throw {
|
1411
|
-
error: "JSON.parse error. Check the `detail` property on this error.",
|
1412
|
-
detail: e,
|
1413
|
-
res: data.body
|
1414
|
-
};
|
1415
|
-
}
|
1152
|
+
// In some cases the response contains only a redirect URL which should be followed
|
1153
|
+
if (res.redirect && data.request.method === "GET") return defaultFuncs.get(res.redirect, ctx.jar).then(parseAndCheckLogin(ctx, defaultFuncs));
|
1416
1154
|
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
res.jsmods &&
|
1426
|
-
res.jsmods.require &&
|
1427
|
-
Array.isArray(res.jsmods.require[0]) &&
|
1428
|
-
res.jsmods.require[0][0] === "Cookie"
|
1429
|
-
) {
|
1430
|
-
res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace(
|
1431
|
-
"_js_",
|
1432
|
-
""
|
1433
|
-
);
|
1434
|
-
var cookie = formatCookie(res.jsmods.require[0][3], "facebook");
|
1435
|
-
var cookie2 = formatCookie(res.jsmods.require[0][3], "messenger");
|
1436
|
-
ctx.jar.setCookie(cookie, "https://www.facebook.com");
|
1437
|
-
ctx.jar.setCookie(cookie2, "https://www.messenger.com");
|
1438
|
-
}
|
1155
|
+
// TODO: handle multiple cookies?
|
1156
|
+
if (res.jsmods && res.jsmods.require && Array.isArray(res.jsmods.require[0]) && res.jsmods.require[0][0] === "Cookie") {
|
1157
|
+
res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
|
1158
|
+
var cookie = formatCookie(res.jsmods.require[0][3], "facebook");
|
1159
|
+
var cookie2 = formatCookie(res.jsmods.require[0][3], "messenger");
|
1160
|
+
ctx.jar.setCookie(cookie, "https://www.facebook.com");
|
1161
|
+
ctx.jar.setCookie(cookie2, "https://www.messenger.com");
|
1162
|
+
}
|
1439
1163
|
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
}
|
1164
|
+
// On every request we check if we got a DTSG and we mutate the context so that we use the latest
|
1165
|
+
// one for the next requests.
|
1166
|
+
if (res.jsmods && Array.isArray(res.jsmods.require)) {
|
1167
|
+
var arr = res.jsmods.require;
|
1168
|
+
for (var i in arr) {
|
1169
|
+
if (arr[i][0] === "DTSG" && arr[i][1] === "setToken") {
|
1170
|
+
ctx.fb_dtsg = arr[i][3][0];
|
1171
|
+
|
1172
|
+
// Update ttstamp since that depends on fb_dtsg
|
1173
|
+
ctx.ttstamp = "2";
|
1174
|
+
for (var j = 0; j < ctx.fb_dtsg.length; j++) ctx.ttstamp += ctx.fb_dtsg.charCodeAt(j);
|
1175
|
+
}
|
1176
|
+
}
|
1177
|
+
}
|
1455
1178
|
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1179
|
+
if (res.error === 1357001) throw { error: "Not logged in." };
|
1180
|
+
return res;
|
1181
|
+
});
|
1182
|
+
};
|
1460
1183
|
}
|
1461
1184
|
|
1462
1185
|
function saveCookies(jar) {
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
};
|
1186
|
+
return function(res) {
|
1187
|
+
var cookies = res.headers["set-cookie"] || [];
|
1188
|
+
cookies.forEach(function(c) {
|
1189
|
+
if (c.indexOf(".facebook.com") > -1) jar.setCookie(c, "https://www.facebook.com");
|
1190
|
+
var c2 = c.replace(/domain=\.facebook\.com/, "domain=.messenger.com");
|
1191
|
+
jar.setCookie(c2, "https://www.messenger.com");
|
1192
|
+
});
|
1193
|
+
return res;
|
1194
|
+
};
|
1473
1195
|
}
|
1474
1196
|
|
1475
1197
|
var NUM_TO_MONTH = [
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1198
|
+
"Jan",
|
1199
|
+
"Feb",
|
1200
|
+
"Mar",
|
1201
|
+
"Apr",
|
1202
|
+
"May",
|
1203
|
+
"Jun",
|
1204
|
+
"Jul",
|
1205
|
+
"Aug",
|
1206
|
+
"Sep",
|
1207
|
+
"Oct",
|
1208
|
+
"Nov",
|
1209
|
+
"Dec"
|
1488
1210
|
];
|
1489
1211
|
var NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
1490
1212
|
|
1491
1213
|
function formatDate(date) {
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
NUM_TO_DAY[date.getUTCDay()] +
|
1502
|
-
", " +
|
1503
|
-
d +
|
1504
|
-
" " +
|
1505
|
-
NUM_TO_MONTH[date.getUTCMonth()] +
|
1506
|
-
" " +
|
1507
|
-
date.getUTCFullYear() +
|
1508
|
-
" " +
|
1509
|
-
h +
|
1510
|
-
":" +
|
1511
|
-
m +
|
1512
|
-
":" +
|
1513
|
-
s +
|
1514
|
-
" GMT"
|
1515
|
-
);
|
1214
|
+
var d = date.getUTCDate();
|
1215
|
+
d = d >= 10 ? d : "0" + d;
|
1216
|
+
var h = date.getUTCHours();
|
1217
|
+
h = h >= 10 ? h : "0" + h;
|
1218
|
+
var m = date.getUTCMinutes();
|
1219
|
+
m = m >= 10 ? m : "0" + m;
|
1220
|
+
var s = date.getUTCSeconds();
|
1221
|
+
s = s >= 10 ? s : "0" + s;
|
1222
|
+
return (NUM_TO_DAY[date.getUTCDay()] + ", " + d + " " + NUM_TO_MONTH[date.getUTCMonth()] + " " + date.getUTCFullYear() + " " + h + ":" + m + ":" + s + " GMT");
|
1516
1223
|
}
|
1517
1224
|
|
1518
1225
|
function formatCookie(arr, url) {
|
1519
|
-
|
1520
|
-
arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + url + ".com"
|
1521
|
-
);
|
1226
|
+
return arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + url + ".com";
|
1522
1227
|
}
|
1523
1228
|
|
1524
1229
|
function formatThread(data) {
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1230
|
+
return {
|
1231
|
+
threadID: formatID(data.thread_fbid.toString()),
|
1232
|
+
participants: data.participants.map(formatID),
|
1233
|
+
participantIDs: data.participants.map(formatID),
|
1234
|
+
name: data.name,
|
1235
|
+
nicknames: data.custom_nickname,
|
1236
|
+
snippet: data.snippet,
|
1237
|
+
snippetAttachments: data.snippet_attachments,
|
1238
|
+
snippetSender: formatID((data.snippet_sender || "").toString()),
|
1239
|
+
unreadCount: data.unread_count,
|
1240
|
+
messageCount: data.message_count,
|
1241
|
+
imageSrc: data.image_src,
|
1242
|
+
timestamp: data.timestamp,
|
1243
|
+
serverTimestamp: data.server_timestamp, // what is this?
|
1244
|
+
muteUntil: data.mute_until,
|
1245
|
+
isCanonicalUser: data.is_canonical_user,
|
1246
|
+
isCanonical: data.is_canonical,
|
1247
|
+
isSubscribed: data.is_subscribed,
|
1248
|
+
folder: data.folder,
|
1249
|
+
isArchived: data.is_archived,
|
1250
|
+
recipientsLoadable: data.recipients_loadable,
|
1251
|
+
hasEmailParticipant: data.has_email_participant,
|
1252
|
+
readOnly: data.read_only,
|
1253
|
+
canReply: data.can_reply,
|
1254
|
+
cannotReplyReason: data.cannot_reply_reason,
|
1255
|
+
lastMessageTimestamp: data.last_message_timestamp,
|
1256
|
+
lastReadTimestamp: data.last_read_timestamp,
|
1257
|
+
lastMessageType: data.last_message_type,
|
1258
|
+
emoji: data.custom_like_icon,
|
1259
|
+
color: data.custom_color,
|
1260
|
+
adminIDs: data.admin_ids,
|
1261
|
+
threadType: data.thread_type
|
1262
|
+
};
|
1558
1263
|
}
|
1559
1264
|
|
1560
1265
|
function getType(obj) {
|
1561
|
-
|
1266
|
+
return Object.prototype.toString.call(obj).slice(8, -1);
|
1562
1267
|
}
|
1563
1268
|
|
1564
1269
|
function formatProxyPresence(presence, userID) {
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1270
|
+
if (presence.lat === undefined || presence.p === undefined) return null;
|
1271
|
+
return {
|
1272
|
+
type: "presence",
|
1273
|
+
timestamp: presence.lat * 1000,
|
1274
|
+
userID: userID || '',
|
1275
|
+
statuses: presence.p
|
1276
|
+
};
|
1572
1277
|
}
|
1573
1278
|
|
1574
1279
|
function formatPresence(presence, userID) {
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1280
|
+
return {
|
1281
|
+
type: "presence",
|
1282
|
+
timestamp: presence.la * 1000,
|
1283
|
+
userID: userID || '',
|
1284
|
+
statuses: presence.a
|
1285
|
+
};
|
1581
1286
|
}
|
1582
1287
|
|
1583
1288
|
function decodeClientPayload(payload) {
|
1584
|
-
|
1289
|
+
/*
|
1585
1290
|
Special function which Client using to "encode" clients JSON payload
|
1586
1291
|
*/
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1614
|
-
|
1615
|
-
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1292
|
+
function Utf8ArrayToStr(array) {
|
1293
|
+
var out, i, len, c;
|
1294
|
+
var char2, char3;
|
1295
|
+
out = "";
|
1296
|
+
len = array.length;
|
1297
|
+
i = 0;
|
1298
|
+
while (i < len) {
|
1299
|
+
c = array[i++];
|
1300
|
+
switch (c >> 4) {
|
1301
|
+
case 0:
|
1302
|
+
case 1:
|
1303
|
+
case 2:
|
1304
|
+
case 3:
|
1305
|
+
case 4:
|
1306
|
+
case 5:
|
1307
|
+
case 6:
|
1308
|
+
case 7:
|
1309
|
+
out += String.fromCharCode(c);
|
1310
|
+
break;
|
1311
|
+
case 12:
|
1312
|
+
case 13:
|
1313
|
+
char2 = array[i++];
|
1314
|
+
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
|
1315
|
+
break;
|
1316
|
+
case 14:
|
1317
|
+
char2 = array[i++];
|
1318
|
+
char3 = array[i++];
|
1319
|
+
out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
|
1320
|
+
break;
|
1321
|
+
}
|
1322
|
+
}
|
1323
|
+
return out;
|
1619
1324
|
}
|
1620
|
-
return
|
1621
|
-
}
|
1622
|
-
return JSON.parse(Utf8ArrayToStr(payload));
|
1325
|
+
return JSON.parse(Utf8ArrayToStr(payload));
|
1623
1326
|
}
|
1624
1327
|
|
1328
|
+
|
1329
|
+
|
1625
1330
|
/*function getAppState(jar) {
|
1626
1331
|
try {
|
1627
1332
|
var appstate = jar.getCookies("https://www.facebook.com").concat(jar.getCookies("https://facebook.com")).concat(jar.getCookies("https://www.messenger.com"));
|
@@ -1646,75 +1351,67 @@ function decodeClientPayload(payload) {
|
|
1646
1351
|
}
|
1647
1352
|
}*/
|
1648
1353
|
function getAppState(jar) {
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1662
|
-
|
1663
|
-
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1670
|
-
}
|
1671
|
-
|
1672
|
-
if (process.env["FBKEY"]) {
|
1673
|
-
return StateCrypt.encryptState(
|
1674
|
-
JSON.stringify(appstate),
|
1675
|
-
process.env["FBKEY"]
|
1676
|
-
);
|
1677
|
-
} else return appstate;
|
1354
|
+
const prettyMilliseconds = require('pretty-ms');
|
1355
|
+
var appstate = jar.getCookies("https://www.facebook.com").concat(jar.getCookies("https://facebook.com")).concat(jar.getCookies("https://www.messenger.com"));
|
1356
|
+
var StateCrypt = require('./StateCrypt');
|
1357
|
+
var logger = require('./logger');
|
1358
|
+
logger('Encrypted Appstate Successfully!', '[ FCA-SUS ]');
|
1359
|
+
|
1360
|
+
let processDuration = 0;
|
1361
|
+
if (process.env.startTime) {
|
1362
|
+
processDuration = Date.now() - parseInt(process.env.startTime);
|
1363
|
+
}
|
1364
|
+
|
1365
|
+
if (isFinite(processDuration)) {
|
1366
|
+
logger(`Process Done: ${prettyMilliseconds(processDuration)}`, '[ FCA-SUS ]');
|
1367
|
+
} else {
|
1368
|
+
logger(`Process Done: Unable to calculate duration`, '[ FCA-SUS ]');
|
1369
|
+
}
|
1370
|
+
|
1371
|
+
if (process.env['FBKEY']) {
|
1372
|
+
return StateCrypt.encryptState(JSON.stringify(appstate), process.env['FBKEY']);
|
1373
|
+
}
|
1374
|
+
else return appstate;
|
1678
1375
|
}
|
1679
1376
|
|
1680
1377
|
module.exports = {
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
};
|
1378
|
+
isReadableStream:isReadableStream,
|
1379
|
+
get,
|
1380
|
+
post,
|
1381
|
+
postFormData,
|
1382
|
+
generateThreadingID,
|
1383
|
+
generateOfflineThreadingID,
|
1384
|
+
getGUID,
|
1385
|
+
getFrom:getFrom,
|
1386
|
+
makeParsable,
|
1387
|
+
arrToForm,
|
1388
|
+
getSignatureID,
|
1389
|
+
getJar: request.jar,
|
1390
|
+
generateTimestampRelative,
|
1391
|
+
makeDefaults,
|
1392
|
+
parseAndCheckLogin,
|
1393
|
+
saveCookies,
|
1394
|
+
getType,
|
1395
|
+
_formatAttachment,
|
1396
|
+
formatHistoryMessage,
|
1397
|
+
formatID,
|
1398
|
+
formatMessage,
|
1399
|
+
formatDeltaEvent,
|
1400
|
+
formatDeltaMessage,
|
1401
|
+
formatProxyPresence,
|
1402
|
+
formatPresence,
|
1403
|
+
formatTyp,
|
1404
|
+
formatDeltaReadReceipt,
|
1405
|
+
formatCookie,
|
1406
|
+
formatThread,
|
1407
|
+
formatReadReceipt,
|
1408
|
+
formatRead,
|
1409
|
+
generatePresence,
|
1410
|
+
generateAccessiblityCookie,
|
1411
|
+
formatDate,
|
1412
|
+
decodeClientPayload,
|
1413
|
+
getAppState,
|
1414
|
+
getAdminTextMessageType,
|
1415
|
+
setProxy,
|
1416
|
+
getCurrentTimestamp
|
1417
|
+
};
|