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