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