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