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