@cexy/hoonfca 1.0.0 → 1.0.2
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/.travis.yml +6 -0
- package/LICENSE-MIT +21 -0
- package/index.d.ts +620 -0
- package/index.js +745 -433
- package/package.json +45 -6
- package/src/addExternalModule.js +14 -16
- package/src/addUserToGroup.js +45 -30
- package/src/changeAdminStatus.js +39 -42
- package/src/changeApprovalMode.js +79 -0
- package/src/changeArchivedStatus.js +19 -15
- package/src/changeBio.js +18 -16
- package/src/changeBlockedStatus.js +14 -12
- package/src/changeBlockedStatusMqtt.js +38 -17
- package/src/changeGroupImage.js +100 -77
- package/src/changeNickname.js +12 -11
- package/src/changeThreadColor.js +25 -16
- package/src/changeThreadEmoji.js +11 -10
- package/src/createNewGroup.js +21 -14
- package/src/createPoll.js +87 -21
- package/src/deleteMessage.js +18 -17
- package/src/deleteThread.js +18 -17
- package/src/editMessage.js +28 -31
- package/src/forwardAttachment.js +22 -19
- package/src/forwardMessage.js +63 -0
- package/src/getCurrentUserID.js +4 -2
- package/src/getEmojiUrl.js +20 -9
- package/src/getFriendsList.js +21 -18
- package/src/getGroupsList.js +83 -0
- package/src/getMarketplace.js +84 -0
- package/src/getNotifications.js +86 -0
- package/src/getPagesList.js +83 -0
- package/src/getStories.js +88 -0
- package/src/getThreadHistory.js +277 -126
- package/src/getThreadInfo.js +143 -115
- package/src/getThreadList.js +216 -143
- package/src/getThreadPictures.js +26 -32
- package/src/getUserID.js +13 -14
- package/src/getUserInfo.js +107 -68
- package/src/handleFriendRequest.js +16 -15
- package/src/handleMessageRequest.js +15 -15
- package/src/httpGet.js +36 -31
- package/src/httpPost.js +36 -31
- package/src/listenMqtt.js +705 -370
- package/src/logout.js +26 -28
- package/src/markAsDelivered.js +22 -17
- package/src/markAsRead.js +63 -49
- package/src/markAsReadAll.js +17 -13
- package/src/markAsSeen.js +23 -19
- package/src/muteThread.js +17 -14
- package/src/pinMessage.js +23 -22
- package/src/removeUserFromGroup.js +42 -22
- package/src/resolvePhotoUrl.js +15 -17
- package/src/searchForThread.js +18 -20
- package/src/searchUsers.js +89 -0
- package/src/sendComment.js +161 -0
- package/src/sendMessage.js +65 -52
- package/src/sendTypingIndicator.js +173 -48
- package/src/setBio.js +86 -0
- package/src/setMessageReaction.js +76 -16
- package/src/setPostReaction.js +29 -61
- package/src/setTheme.js +313 -0
- package/src/setTitle.js +27 -37
- package/src/shareContact.js +34 -82
- package/src/shareLink.js +56 -99
- package/src/threadColors.js +35 -97
- package/src/unfriend.js +15 -20
- package/src/unsendMessage.js +71 -18
- package/utils.js +1000 -472
- package/README.md +0 -83
- package/replit.nix +0 -3
- package/src/changeAvatar.js +0 -89
- package/src/changeCover.js +0 -92
- package/src/changeName.js +0 -106
- package/src/changeUsername.js +0 -80
- package/src/createCommentPost.js +0 -196
- package/src/createPost.js +0 -285
- package/src/data/getThreadInfo.json +0 -1
- package/src/follow.js +0 -71
- package/src/getAccess.js +0 -130
- package/src/getAvatarUser.js +0 -88
- package/src/getBotInitialData.js +0 -59
- package/src/getCtx.js +0 -5
- package/src/getMessage.js +0 -827
- package/src/getOptions.js +0 -5
- package/src/getRegion.js +0 -7
- package/src/getThreadHistoryDeprecated.js +0 -95
- package/src/getThreadInfoDeprecated.js +0 -77
- package/src/getThreadListDeprecated.js +0 -86
- package/src/httpPostFormData.js +0 -58
- package/src/listenNotification.js +0 -96
- package/src/refreshFb_dtsg.js +0 -75
- package/src/searchStickers.js +0 -59
- package/src/sendMessageMqtt.js +0 -326
- package/src/setMessageReactionMqtt.js +0 -74
- package/src/setProfileGuard.js +0 -66
- package/src/setStoryReaction.js +0 -97
- package/src/stopListenMqtt.js +0 -47
- package/src/uploadAttachment.js +0 -98
package/src/listenMqtt.js
CHANGED
|
@@ -1,27 +1,35 @@
|
|
|
1
|
+
/* eslint-disable no-redeclare */
|
|
1
2
|
"use strict";
|
|
3
|
+
var utils = require("../utils");
|
|
4
|
+
var log = require("npmlog");
|
|
5
|
+
var mqtt = require("mqtt");
|
|
6
|
+
var websocket = require("websocket-stream");
|
|
7
|
+
var HttpsProxyAgent = require("https-proxy-agent");
|
|
8
|
+
const EventEmitter = require("events");
|
|
2
9
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const HttpsProxyAgent = require('https-proxy-agent');
|
|
7
|
-
const EventEmitter = require('events');
|
|
10
|
+
var identity = function () {};
|
|
11
|
+
var form = {};
|
|
12
|
+
var getSeqID = function () {};
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
let form = {};
|
|
11
|
-
let getSeqID = () => {};
|
|
12
|
-
|
|
13
|
-
const topics = [
|
|
14
|
+
var topics = [
|
|
14
15
|
"/legacy_web",
|
|
15
16
|
"/webrtc",
|
|
16
17
|
"/rtc_multi",
|
|
17
18
|
"/onevc",
|
|
18
|
-
"/br_sr",
|
|
19
|
+
"/br_sr", //Notification
|
|
20
|
+
//Need to publish /br_sr right after this
|
|
19
21
|
"/sr_res",
|
|
20
22
|
"/t_ms",
|
|
21
23
|
"/thread_typing",
|
|
22
24
|
"/orca_typing_notifications",
|
|
23
25
|
"/notify_disconnect",
|
|
26
|
+
//Need to publish /messenger_sync_create_queue right after this
|
|
24
27
|
"/orca_presence",
|
|
28
|
+
//Will receive /sr_res right here.
|
|
29
|
+
|
|
30
|
+
"/ls_resp",
|
|
31
|
+
// "/ls_req",
|
|
32
|
+
|
|
25
33
|
"/inbox",
|
|
26
34
|
"/mercury",
|
|
27
35
|
"/messaging_events",
|
|
@@ -31,104 +39,100 @@ const topics = [
|
|
|
31
39
|
];
|
|
32
40
|
|
|
33
41
|
function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
//Don't really know what this does but I think it's for the active state?
|
|
43
|
+
//TODO: Move to ctx when implemented
|
|
44
|
+
var chatOn = ctx.globalOptions.online;
|
|
45
|
+
var foreground = false;
|
|
46
|
+
|
|
47
|
+
ctx["tasks"].clear(); // Clear tasks
|
|
48
|
+
|
|
49
|
+
var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
|
|
50
|
+
var username = {
|
|
40
51
|
u: ctx.userID,
|
|
41
52
|
s: sessionID,
|
|
42
53
|
chat_on: chatOn,
|
|
43
54
|
fg: foreground,
|
|
44
|
-
d:
|
|
45
|
-
ct:
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
d: utils.getGUID(),
|
|
56
|
+
ct: "websocket",
|
|
57
|
+
//App id from facebook
|
|
58
|
+
aid: "219994525426954",
|
|
59
|
+
mqtt_sid: "",
|
|
48
60
|
cp: 3,
|
|
49
61
|
ecp: 10,
|
|
50
62
|
st: [],
|
|
51
63
|
pm: [],
|
|
52
|
-
dc:
|
|
64
|
+
dc: "",
|
|
53
65
|
no_auto_fg: true,
|
|
54
66
|
gas: null,
|
|
55
67
|
pack: [],
|
|
56
|
-
a: ctx.globalOptions.userAgent,
|
|
57
|
-
p: null,
|
|
58
|
-
aids: null, // ডুপ্লিকেট 'aids' কী-টি রিমুভ করা হয়েছে
|
|
59
|
-
php_override: ""
|
|
60
68
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
|
|
70
|
+
|
|
71
|
+
var host;
|
|
64
72
|
if (ctx.mqttEndpoint) {
|
|
65
73
|
host = `${ctx.mqttEndpoint}&sid=${sessionID}`;
|
|
66
74
|
} else if (ctx.region) {
|
|
67
|
-
host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.
|
|
75
|
+
host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}`;
|
|
68
76
|
} else {
|
|
69
77
|
host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}`;
|
|
70
78
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
clientId:
|
|
74
|
-
protocolId:
|
|
79
|
+
|
|
80
|
+
var options = {
|
|
81
|
+
clientId: "mqttwsclient",
|
|
82
|
+
protocolId: "MQIsdp",
|
|
75
83
|
protocolVersion: 3,
|
|
76
84
|
username: JSON.stringify(username),
|
|
77
85
|
clean: true,
|
|
78
86
|
wsOptions: {
|
|
79
87
|
headers: {
|
|
80
88
|
Cookie: cookies,
|
|
81
|
-
Origin:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Host: new URL(host).hostname,
|
|
89
|
+
Origin: "https://www.facebook.com",
|
|
90
|
+
"User-Agent": ctx.globalOptions.userAgent,
|
|
91
|
+
Referer: "https://www.facebook.com/",
|
|
92
|
+
Host: new URL(host).hostname, //'edge-chat.facebook.com'
|
|
85
93
|
},
|
|
86
|
-
origin:
|
|
94
|
+
origin: "https://www.facebook.com",
|
|
87
95
|
protocolVersion: 13,
|
|
88
|
-
binaryType: 'arraybuffer',
|
|
89
96
|
},
|
|
90
97
|
keepalive: 10,
|
|
91
|
-
reschedulePings:
|
|
92
|
-
connectTimeout: 10 * 1000,
|
|
93
|
-
reconnectPeriod: 1 * 1000,
|
|
98
|
+
reschedulePings: false,
|
|
94
99
|
};
|
|
95
|
-
|
|
96
|
-
if (typeof ctx.globalOptions.proxy
|
|
97
|
-
|
|
100
|
+
|
|
101
|
+
if (typeof ctx.globalOptions.proxy != "undefined") {
|
|
102
|
+
var agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
|
|
98
103
|
options.wsOptions.agent = agent;
|
|
99
104
|
}
|
|
100
|
-
|
|
101
|
-
ctx.mqttClient = new mqtt.Client(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
ctx.mqttClient = null;
|
|
112
|
-
mqttClient = null;
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
mqttClient.on('error', err => {
|
|
118
|
-
stopListening();
|
|
105
|
+
|
|
106
|
+
ctx.mqttClient = new mqtt.Client(
|
|
107
|
+
(_) => websocket(host, options.wsOptions),
|
|
108
|
+
options,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
var mqttClient = ctx.mqttClient;
|
|
112
|
+
|
|
113
|
+
mqttClient.on("error", function (err) {
|
|
114
|
+
log.error("listenMqtt", err);
|
|
115
|
+
mqttClient.end();
|
|
119
116
|
if (ctx.globalOptions.autoReconnect) {
|
|
120
117
|
getSeqID();
|
|
121
118
|
} else {
|
|
122
|
-
globalCallback(
|
|
119
|
+
globalCallback(
|
|
120
|
+
{
|
|
121
|
+
type: "stop_listen",
|
|
122
|
+
error: "Connection refused: Server unavailable",
|
|
123
|
+
},
|
|
124
|
+
null,
|
|
125
|
+
);
|
|
123
126
|
}
|
|
124
|
-
utils.warn("Error detected. Will relogin automatically...");
|
|
125
|
-
api.ws3?.relogin(); // অপশনাল চেইনিং
|
|
126
127
|
});
|
|
127
128
|
|
|
128
|
-
mqttClient.on(
|
|
129
|
-
topics.forEach(
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
mqttClient.on("connect", function () {
|
|
130
|
+
topics.forEach(function (topicsub) {
|
|
131
|
+
mqttClient.subscribe(topicsub);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
var topic;
|
|
135
|
+
var queue = {
|
|
132
136
|
sync_api_version: 10,
|
|
133
137
|
max_deltas_able_to_process: 1000,
|
|
134
138
|
delta_batch_size: 500,
|
|
@@ -145,102 +149,166 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
|
|
|
145
149
|
queue.initial_titan_sequence_id = ctx.lastSeqId;
|
|
146
150
|
queue.device_params = null;
|
|
147
151
|
}
|
|
148
|
-
|
|
149
|
-
mqttClient.publish(topic, JSON.stringify(queue), {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
|
|
153
|
+
mqttClient.publish(topic, JSON.stringify(queue), {
|
|
154
|
+
qos: 1,
|
|
155
|
+
retain: false,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
var rTimeout = setTimeout(function () {
|
|
154
159
|
mqttClient.end();
|
|
155
|
-
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
ctx.tmsWait = ()
|
|
160
|
+
getSeqID();
|
|
161
|
+
}, 5000);
|
|
162
|
+
|
|
163
|
+
ctx.tmsWait = function () {
|
|
159
164
|
clearTimeout(rTimeout);
|
|
160
|
-
|
|
161
|
-
globalCallback({
|
|
162
|
-
|
|
165
|
+
ctx.globalOptions.emitReady
|
|
166
|
+
? globalCallback({
|
|
167
|
+
type: "ready",
|
|
168
|
+
error: null,
|
|
169
|
+
})
|
|
170
|
+
: "";
|
|
163
171
|
delete ctx.tmsWait;
|
|
164
172
|
};
|
|
165
173
|
});
|
|
166
174
|
|
|
167
|
-
mqttClient.on(
|
|
168
|
-
let jsonMessage;
|
|
175
|
+
mqttClient.on("message", function (topic, message, _packet) {
|
|
169
176
|
try {
|
|
170
|
-
jsonMessage = JSON.parse(message);
|
|
177
|
+
var jsonMessage = JSON.parse(message);
|
|
171
178
|
} catch (ex) {
|
|
172
|
-
return
|
|
179
|
+
return log.error("listenMqtt", ex);
|
|
173
180
|
}
|
|
174
|
-
|
|
175
181
|
if (topic === "/t_ms") {
|
|
176
|
-
if (ctx.tmsWait && typeof ctx.tmsWait
|
|
182
|
+
if (ctx.tmsWait && typeof ctx.tmsWait == "function") {
|
|
183
|
+
ctx.tmsWait();
|
|
184
|
+
}
|
|
185
|
+
|
|
177
186
|
if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
|
|
178
187
|
ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
|
|
179
188
|
ctx.syncToken = jsonMessage.syncToken;
|
|
180
189
|
}
|
|
190
|
+
|
|
181
191
|
if (jsonMessage.lastIssuedSeqId) {
|
|
182
192
|
ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
|
|
183
193
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
194
|
+
|
|
195
|
+
//If it contains more than 1 delta
|
|
196
|
+
for (var i in jsonMessage.deltas) {
|
|
197
|
+
var delta = jsonMessage.deltas[i];
|
|
198
|
+
parseDelta(defaultFuncs, api, ctx, globalCallback, {
|
|
199
|
+
delta: delta,
|
|
200
|
+
});
|
|
188
201
|
}
|
|
189
|
-
} else if (
|
|
190
|
-
|
|
202
|
+
} else if (
|
|
203
|
+
topic === "/thread_typing" ||
|
|
204
|
+
topic === "/orca_typing_notifications"
|
|
205
|
+
) {
|
|
206
|
+
var typ = {
|
|
191
207
|
type: "typ",
|
|
192
208
|
isTyping: !!jsonMessage.state,
|
|
193
209
|
from: jsonMessage.sender_fbid.toString(),
|
|
194
|
-
threadID: utils.formatID(
|
|
210
|
+
threadID: utils.formatID(
|
|
211
|
+
(jsonMessage.thread || jsonMessage.sender_fbid).toString(),
|
|
212
|
+
),
|
|
195
213
|
};
|
|
196
|
-
|
|
214
|
+
(function () {
|
|
215
|
+
globalCallback(null, typ);
|
|
216
|
+
})();
|
|
197
217
|
} else if (topic === "/orca_presence") {
|
|
198
218
|
if (!ctx.globalOptions.updatePresence) {
|
|
199
|
-
for (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
219
|
+
for (var i in jsonMessage.list) {
|
|
220
|
+
var data = jsonMessage.list[i];
|
|
221
|
+
var userID = data["u"];
|
|
222
|
+
|
|
223
|
+
var presence = {
|
|
203
224
|
type: "presence",
|
|
204
225
|
userID: userID.toString(),
|
|
226
|
+
//Convert to ms
|
|
205
227
|
timestamp: data["l"] * 1000,
|
|
206
|
-
statuses: data["p"]
|
|
228
|
+
statuses: data["p"],
|
|
207
229
|
};
|
|
208
|
-
|
|
230
|
+
(function () {
|
|
231
|
+
globalCallback(null, presence);
|
|
232
|
+
})();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} else if (topic == "/ls_resp") {
|
|
236
|
+
const parsedPayload = JSON.parse(jsonMessage.payload);
|
|
237
|
+
const reqID = jsonMessage.request_id;
|
|
238
|
+
if (ctx["tasks"].has(reqID)) {
|
|
239
|
+
const taskData = ctx["tasks"].get(reqID);
|
|
240
|
+
const { type: taskType, callback: taskCallback } = taskData;
|
|
241
|
+
const taskRespData = getTaskResponseData(taskType, parsedPayload);
|
|
242
|
+
|
|
243
|
+
if (taskRespData == null) {
|
|
244
|
+
taskCallback("error", null);
|
|
245
|
+
} else {
|
|
246
|
+
taskCallback(null, {
|
|
247
|
+
type: taskType,
|
|
248
|
+
reqID: reqID,
|
|
249
|
+
...taskRespData,
|
|
250
|
+
});
|
|
209
251
|
}
|
|
210
252
|
}
|
|
211
253
|
}
|
|
212
254
|
});
|
|
213
|
-
|
|
214
|
-
mqttClient.on(
|
|
215
|
-
|
|
255
|
+
|
|
256
|
+
mqttClient.on("close", function () {
|
|
257
|
+
//(function () { globalCallback("Connection closed."); })();
|
|
258
|
+
// client.end();
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function getTaskResponseData(taskType, payload) {
|
|
263
|
+
try {
|
|
264
|
+
switch (taskType) {
|
|
265
|
+
case "set_message_reaction": {
|
|
266
|
+
return {
|
|
267
|
+
mid: payload.step[1][2][2][1][4],
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
case "edit_message": {
|
|
271
|
+
return {
|
|
272
|
+
mid: payload.step[1][2][2][1][2],
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} catch (error) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
216
279
|
}
|
|
217
280
|
|
|
218
281
|
function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
|
|
219
|
-
if (v.delta.class
|
|
282
|
+
if (v.delta.class == "NewMessage") {
|
|
283
|
+
//Not tested for pages
|
|
220
284
|
if (ctx.globalOptions.pageID && ctx.globalOptions.pageID != v.queue) return;
|
|
221
|
-
|
|
285
|
+
|
|
222
286
|
(function resolveAttachmentUrl(i) {
|
|
223
|
-
if (v.delta.attachments &&
|
|
224
|
-
|
|
287
|
+
if (v.delta.attachments && i == v.delta.attachments.length) {
|
|
288
|
+
var fmtMsg;
|
|
225
289
|
try {
|
|
226
290
|
fmtMsg = utils.formatDeltaMessage(v);
|
|
227
291
|
} catch (err) {
|
|
228
292
|
return globalCallback({
|
|
229
|
-
error:
|
|
293
|
+
error:
|
|
294
|
+
"Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
|
|
230
295
|
detail: err,
|
|
231
296
|
res: v,
|
|
232
|
-
type: "parse_error"
|
|
297
|
+
type: "parse_error",
|
|
233
298
|
});
|
|
234
299
|
}
|
|
235
|
-
if (fmtMsg
|
|
236
|
-
|
|
300
|
+
if (fmtMsg) {
|
|
301
|
+
if (ctx.globalOptions.autoMarkDelivery) {
|
|
302
|
+
markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
|
|
303
|
+
}
|
|
237
304
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
305
|
+
return !ctx.globalOptions.selfListen && fmtMsg.senderID === ctx.userID
|
|
306
|
+
? undefined
|
|
307
|
+
: (function () {
|
|
308
|
+
globalCallback(null, fmtMsg);
|
|
309
|
+
})();
|
|
242
310
|
} else {
|
|
243
|
-
if (v.delta.attachments
|
|
311
|
+
if (v.delta.attachments[i].mercury.attach_type == "photo") {
|
|
244
312
|
api.resolvePhotoUrl(v.delta.attachments[i].fbid, (err, url) => {
|
|
245
313
|
if (!err) v.delta.attachments[i].mercury.metadata.url = url;
|
|
246
314
|
return resolveAttachmentUrl(i + 1);
|
|
@@ -252,93 +320,86 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
|
|
|
252
320
|
})(0);
|
|
253
321
|
}
|
|
254
322
|
|
|
255
|
-
if (v.delta.class
|
|
256
|
-
|
|
323
|
+
if (v.delta.class == "ClientPayload") {
|
|
324
|
+
var clientPayload = utils.decodeClientPayload(v.delta.payload);
|
|
257
325
|
if (clientPayload && clientPayload.deltas) {
|
|
258
|
-
for (
|
|
259
|
-
|
|
326
|
+
for (var i in clientPayload.deltas) {
|
|
327
|
+
var delta = clientPayload.deltas[i];
|
|
260
328
|
if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
329
|
+
(function () {
|
|
330
|
+
globalCallback(null, {
|
|
331
|
+
type: "message_reaction",
|
|
332
|
+
threadID: (delta.deltaMessageReaction.threadKey.threadFbId
|
|
333
|
+
? delta.deltaMessageReaction.threadKey.threadFbId
|
|
334
|
+
: delta.deltaMessageReaction.threadKey.otherUserFbId
|
|
335
|
+
).toString(),
|
|
336
|
+
messageID: delta.deltaMessageReaction.messageId,
|
|
337
|
+
reaction: delta.deltaMessageReaction.reaction,
|
|
338
|
+
senderID: delta.deltaMessageReaction.senderId.toString(),
|
|
339
|
+
userID: delta.deltaMessageReaction.userId.toString(),
|
|
340
|
+
reactionTimestamp: delta.deltaMessageReaction.reactionTimestamp,
|
|
341
|
+
});
|
|
342
|
+
})();
|
|
343
|
+
} else if (
|
|
344
|
+
delta.deltaRecallMessageData &&
|
|
345
|
+
!!ctx.globalOptions.listenEvents
|
|
346
|
+
) {
|
|
347
|
+
(function () {
|
|
348
|
+
globalCallback(null, {
|
|
349
|
+
type: "message_unsend",
|
|
350
|
+
threadID: (delta.deltaRecallMessageData.threadKey.threadFbId
|
|
351
|
+
? delta.deltaRecallMessageData.threadKey.threadFbId
|
|
352
|
+
: delta.deltaRecallMessageData.threadKey.otherUserFbId
|
|
353
|
+
).toString(),
|
|
354
|
+
messageID: delta.deltaRecallMessageData.messageID,
|
|
355
|
+
senderID: delta.deltaRecallMessageData.senderID.toString(),
|
|
356
|
+
deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
|
|
357
|
+
timestamp: delta.deltaRecallMessageData.messageTimestamp,
|
|
358
|
+
});
|
|
359
|
+
})();
|
|
278
360
|
} else if (delta.deltaMessageReply) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
361
|
+
//Mention block - #1
|
|
362
|
+
var mdata =
|
|
363
|
+
delta.deltaMessageReply.message === undefined
|
|
364
|
+
? []
|
|
365
|
+
: delta.deltaMessageReply.message.data === undefined
|
|
366
|
+
? []
|
|
367
|
+
: delta.deltaMessageReply.message.data.prng === undefined
|
|
368
|
+
? []
|
|
369
|
+
: JSON.parse(delta.deltaMessageReply.message.data.prng);
|
|
370
|
+
var m_id = mdata.map((u) => u.i);
|
|
371
|
+
var m_offset = mdata.map((u) => u.o);
|
|
372
|
+
var m_length = mdata.map((u) => u.l);
|
|
373
|
+
|
|
374
|
+
var mentions = {};
|
|
375
|
+
|
|
376
|
+
for (var i = 0; i < m_id.length; i++) {
|
|
377
|
+
mentions[m_id[i]] = (
|
|
378
|
+
delta.deltaMessageReply.message.body || ""
|
|
379
|
+
).substring(m_offset[i], m_offset[i] + m_length[i]);
|
|
289
380
|
}
|
|
290
|
-
|
|
291
|
-
|
|
381
|
+
//Mention block - 1#
|
|
382
|
+
var callbackToReturn = {
|
|
292
383
|
type: "message_reply",
|
|
293
|
-
threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
x.type = "unknown";
|
|
308
|
-
}
|
|
309
|
-
return x;
|
|
310
|
-
}),
|
|
311
|
-
args: (delta.deltaMessageReply.message.body || "").trim().split(/\s+/),
|
|
312
|
-
body: (delta.deltaMessageReply.message.body || ""),
|
|
313
|
-
isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
|
|
314
|
-
mentions,
|
|
315
|
-
timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
|
|
316
|
-
participantIDs: (delta.deltaMessageReply.message.participants || []).map(e => e.toString())
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
if (delta.deltaMessageReply.repliedToMessage) {
|
|
320
|
-
const r_mdata = delta.deltaMessageReply.repliedToMessage?.data?.prng
|
|
321
|
-
? JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng)
|
|
322
|
-
: [];
|
|
323
|
-
const r_m_id = r_mdata.map(u => u.i);
|
|
324
|
-
const r_m_offset = r_mdata.map(u => u.o);
|
|
325
|
-
const r_m_length = r_mdata.map(u => u.l);
|
|
326
|
-
const rmentions = {};
|
|
327
|
-
|
|
328
|
-
for (let i = 0; i < r_m_id.length; i++) {
|
|
329
|
-
rmentions[r_m_id[i]] = (delta.deltaMessageReply.repliedToMessage.body || "").substring(r_m_offset[i], r_m_offset[i] + r_m_length[i]);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
callbackToReturn.messageReply = {
|
|
333
|
-
threadID: (delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.otherUserFbId).toString(),
|
|
334
|
-
messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
|
|
335
|
-
senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
|
|
336
|
-
attachments: (delta.deltaMessageReply.repliedToMessage.attachments || []).map(att => {
|
|
337
|
-
const mercury = JSON.parse(att.mercuryJSON);
|
|
384
|
+
threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey
|
|
385
|
+
.threadFbId
|
|
386
|
+
? delta.deltaMessageReply.message.messageMetadata.threadKey
|
|
387
|
+
.threadFbId
|
|
388
|
+
: delta.deltaMessageReply.message.messageMetadata.threadKey
|
|
389
|
+
.otherUserFbId
|
|
390
|
+
).toString(),
|
|
391
|
+
messageID:
|
|
392
|
+
delta.deltaMessageReply.message.messageMetadata.messageId,
|
|
393
|
+
senderID:
|
|
394
|
+
delta.deltaMessageReply.message.messageMetadata.actorFbId.toString(),
|
|
395
|
+
attachments: delta.deltaMessageReply.message.attachments
|
|
396
|
+
.map(function (att) {
|
|
397
|
+
var mercury = JSON.parse(att.mercuryJSON);
|
|
338
398
|
Object.assign(att, mercury);
|
|
339
399
|
return att;
|
|
340
|
-
})
|
|
341
|
-
|
|
400
|
+
})
|
|
401
|
+
.map((att) => {
|
|
402
|
+
var x;
|
|
342
403
|
try {
|
|
343
404
|
x = utils._formatAttachment(att);
|
|
344
405
|
} catch (ex) {
|
|
@@ -348,52 +409,140 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
|
|
|
348
409
|
}
|
|
349
410
|
return x;
|
|
350
411
|
}),
|
|
351
|
-
|
|
412
|
+
args: (delta.deltaMessageReply.message.body || "")
|
|
413
|
+
.trim()
|
|
414
|
+
.split(/\s+/),
|
|
415
|
+
body: delta.deltaMessageReply.message.body || "",
|
|
416
|
+
mentions: mentions,
|
|
417
|
+
timestamp:
|
|
418
|
+
delta.deltaMessageReply.message.messageMetadata.timestamp,
|
|
419
|
+
isGroup:
|
|
420
|
+
!!delta.deltaMessageReply.message.messageMetadata.threadKey
|
|
421
|
+
.threadFbId,
|
|
422
|
+
participantIDs: delta.deltaMessageReply.message.participants?.map(
|
|
423
|
+
(u) => u.toString(),
|
|
424
|
+
),
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
if (delta.deltaMessageReply.repliedToMessage) {
|
|
428
|
+
//Mention block - #2
|
|
429
|
+
mdata =
|
|
430
|
+
delta.deltaMessageReply.repliedToMessage === undefined
|
|
431
|
+
? []
|
|
432
|
+
: delta.deltaMessageReply.repliedToMessage.data === undefined
|
|
433
|
+
? []
|
|
434
|
+
: delta.deltaMessageReply.repliedToMessage.data.prng ===
|
|
435
|
+
undefined
|
|
436
|
+
? []
|
|
437
|
+
: JSON.parse(
|
|
438
|
+
delta.deltaMessageReply.repliedToMessage.data.prng,
|
|
439
|
+
);
|
|
440
|
+
m_id = mdata.map((u) => u.i);
|
|
441
|
+
m_offset = mdata.map((u) => u.o);
|
|
442
|
+
m_length = mdata.map((u) => u.l);
|
|
443
|
+
|
|
444
|
+
var rmentions = {};
|
|
445
|
+
|
|
446
|
+
for (var i = 0; i < m_id.length; i++) {
|
|
447
|
+
rmentions[m_id[i]] = (
|
|
448
|
+
delta.deltaMessageReply.repliedToMessage.body || ""
|
|
449
|
+
).substring(m_offset[i], m_offset[i] + m_length[i]);
|
|
450
|
+
}
|
|
451
|
+
//Mention block - 2#
|
|
452
|
+
callbackToReturn.messageReply = {
|
|
453
|
+
threadID: (delta.deltaMessageReply.repliedToMessage
|
|
454
|
+
.messageMetadata.threadKey.threadFbId
|
|
455
|
+
? delta.deltaMessageReply.repliedToMessage.messageMetadata
|
|
456
|
+
.threadKey.threadFbId
|
|
457
|
+
: delta.deltaMessageReply.repliedToMessage.messageMetadata
|
|
458
|
+
.threadKey.otherUserFbId
|
|
459
|
+
).toString(),
|
|
460
|
+
messageID:
|
|
461
|
+
delta.deltaMessageReply.repliedToMessage.messageMetadata
|
|
462
|
+
.messageId,
|
|
463
|
+
senderID:
|
|
464
|
+
delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
|
|
465
|
+
attachments: delta.deltaMessageReply.repliedToMessage.attachments
|
|
466
|
+
.map(function (att) {
|
|
467
|
+
var mercury = JSON.parse(att.mercuryJSON);
|
|
468
|
+
Object.assign(att, mercury);
|
|
469
|
+
return att;
|
|
470
|
+
})
|
|
471
|
+
.map((att) => {
|
|
472
|
+
var x;
|
|
473
|
+
try {
|
|
474
|
+
x = utils._formatAttachment(att);
|
|
475
|
+
} catch (ex) {
|
|
476
|
+
x = att;
|
|
477
|
+
x.error = ex;
|
|
478
|
+
x.type = "unknown";
|
|
479
|
+
}
|
|
480
|
+
return x;
|
|
481
|
+
}),
|
|
482
|
+
args: (delta.deltaMessageReply.repliedToMessage.body || "")
|
|
483
|
+
.trim()
|
|
484
|
+
.split(/\s+/),
|
|
352
485
|
body: delta.deltaMessageReply.repliedToMessage.body || "",
|
|
353
|
-
isGroup:
|
|
486
|
+
isGroup:
|
|
487
|
+
!!delta.deltaMessageReply.repliedToMessage.messageMetadata
|
|
488
|
+
.threadKey.threadFbId,
|
|
354
489
|
mentions: rmentions,
|
|
355
|
-
timestamp:
|
|
356
|
-
|
|
490
|
+
timestamp:
|
|
491
|
+
delta.deltaMessageReply.repliedToMessage.messageMetadata
|
|
492
|
+
.timestamp,
|
|
357
493
|
};
|
|
358
494
|
} else if (delta.deltaMessageReply.replyToMessageId) {
|
|
359
495
|
return defaultFuncs
|
|
360
496
|
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
"
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
497
|
+
av: ctx.globalOptions.pageID,
|
|
498
|
+
queries: JSON.stringify({
|
|
499
|
+
o0: {
|
|
500
|
+
//Using the same doc_id as forcedFetch
|
|
501
|
+
doc_id: "2848441488556444",
|
|
502
|
+
query_params: {
|
|
503
|
+
thread_and_message_id: {
|
|
504
|
+
thread_id: callbackToReturn.threadID,
|
|
505
|
+
message_id: delta.deltaMessageReply.replyToMessageId.id,
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
}),
|
|
373
510
|
})
|
|
374
511
|
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
375
|
-
.then(resData => {
|
|
512
|
+
.then((resData) => {
|
|
376
513
|
if (resData[resData.length - 1].error_results > 0) {
|
|
377
514
|
throw resData[0].o0.errors;
|
|
378
515
|
}
|
|
516
|
+
|
|
379
517
|
if (resData[resData.length - 1].successful_results === 0) {
|
|
380
|
-
throw {
|
|
518
|
+
throw {
|
|
519
|
+
error: "forcedFetch: there was no successful_results",
|
|
520
|
+
res: resData,
|
|
521
|
+
};
|
|
381
522
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
523
|
+
|
|
524
|
+
var fetchData = resData[0].o0.data.message;
|
|
525
|
+
|
|
526
|
+
var mobj = {};
|
|
527
|
+
for (var n in fetchData.message.ranges) {
|
|
528
|
+
mobj[fetchData.message.ranges[n].entity.id] = (
|
|
529
|
+
fetchData.message.text || ""
|
|
530
|
+
).substr(
|
|
531
|
+
fetchData.message.ranges[n].offset,
|
|
532
|
+
fetchData.message.ranges[n].length,
|
|
533
|
+
);
|
|
387
534
|
}
|
|
388
535
|
|
|
389
536
|
callbackToReturn.messageReply = {
|
|
390
537
|
threadID: callbackToReturn.threadID,
|
|
391
538
|
messageID: fetchData.message_id,
|
|
392
|
-
senderID: fetchData.message_sender
|
|
393
|
-
attachments:
|
|
394
|
-
|
|
539
|
+
senderID: fetchData.message_sender.id.toString(),
|
|
540
|
+
attachments: fetchData.message.blob_attachment.map((att) => {
|
|
541
|
+
var x;
|
|
395
542
|
try {
|
|
396
|
-
x = utils._formatAttachment({
|
|
543
|
+
x = utils._formatAttachment({
|
|
544
|
+
blob_attachment: att,
|
|
545
|
+
});
|
|
397
546
|
} catch (ex) {
|
|
398
547
|
x = att;
|
|
399
548
|
x.error = ex;
|
|
@@ -401,32 +550,53 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
|
|
|
401
550
|
}
|
|
402
551
|
return x;
|
|
403
552
|
}),
|
|
404
|
-
args: (
|
|
405
|
-
|
|
553
|
+
args: (delta.deltaMessageReply.repliedToMessage.body || "")
|
|
554
|
+
.trim()
|
|
555
|
+
.split(/\s+/),
|
|
556
|
+
body: fetchData.message.text || "",
|
|
406
557
|
isGroup: callbackToReturn.isGroup,
|
|
407
558
|
mentions: mobj,
|
|
408
559
|
timestamp: parseInt(fetchData.timestamp_precise),
|
|
409
560
|
};
|
|
410
561
|
})
|
|
411
|
-
.catch(err =>
|
|
412
|
-
|
|
562
|
+
.catch((err) => {
|
|
563
|
+
log.error("forcedFetch", err);
|
|
564
|
+
})
|
|
565
|
+
.finally(function () {
|
|
413
566
|
if (ctx.globalOptions.autoMarkDelivery) {
|
|
414
|
-
markDelivery(
|
|
567
|
+
markDelivery(
|
|
568
|
+
ctx,
|
|
569
|
+
api,
|
|
570
|
+
callbackToReturn.threadID,
|
|
571
|
+
callbackToReturn.messageID,
|
|
572
|
+
);
|
|
415
573
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
574
|
+
!ctx.globalOptions.selfListen &&
|
|
575
|
+
callbackToReturn.senderID === ctx.userID
|
|
576
|
+
? undefined
|
|
577
|
+
: (function () {
|
|
578
|
+
globalCallback(null, callbackToReturn);
|
|
579
|
+
})();
|
|
419
580
|
});
|
|
420
581
|
} else {
|
|
421
582
|
callbackToReturn.delta = delta;
|
|
422
583
|
}
|
|
423
|
-
|
|
584
|
+
|
|
424
585
|
if (ctx.globalOptions.autoMarkDelivery) {
|
|
425
|
-
markDelivery(
|
|
586
|
+
markDelivery(
|
|
587
|
+
ctx,
|
|
588
|
+
api,
|
|
589
|
+
callbackToReturn.threadID,
|
|
590
|
+
callbackToReturn.messageID,
|
|
591
|
+
);
|
|
426
592
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
593
|
+
|
|
594
|
+
return !ctx.globalOptions.selfListen &&
|
|
595
|
+
callbackToReturn.senderID === ctx.userID
|
|
596
|
+
? undefined
|
|
597
|
+
: (function () {
|
|
598
|
+
globalCallback(null, callbackToReturn);
|
|
599
|
+
})();
|
|
430
600
|
}
|
|
431
601
|
}
|
|
432
602
|
return;
|
|
@@ -434,174 +604,306 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
|
|
|
434
604
|
}
|
|
435
605
|
|
|
436
606
|
if (v.delta.class !== "NewMessage" && !ctx.globalOptions.listenEvents) return;
|
|
437
|
-
|
|
607
|
+
|
|
438
608
|
switch (v.delta.class) {
|
|
439
|
-
case "ReadReceipt":
|
|
440
|
-
|
|
609
|
+
case "ReadReceipt":
|
|
610
|
+
var fmtMsg;
|
|
441
611
|
try {
|
|
442
612
|
fmtMsg = utils.formatDeltaReadReceipt(v.delta);
|
|
443
613
|
} catch (err) {
|
|
444
614
|
return globalCallback({
|
|
445
|
-
error:
|
|
615
|
+
error:
|
|
616
|
+
"Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
|
|
446
617
|
detail: err,
|
|
447
618
|
res: v.delta,
|
|
448
|
-
type: "parse_error"
|
|
619
|
+
type: "parse_error",
|
|
449
620
|
});
|
|
450
621
|
}
|
|
451
|
-
return
|
|
452
|
-
|
|
453
|
-
|
|
622
|
+
return (function () {
|
|
623
|
+
globalCallback(null, fmtMsg);
|
|
624
|
+
})();
|
|
625
|
+
case "AdminTextMessage":
|
|
454
626
|
switch (v.delta.type) {
|
|
455
627
|
case "change_thread_theme":
|
|
628
|
+
// case "change_thread_icon": deprecated
|
|
629
|
+
case "change_thread_quick_reaction":
|
|
456
630
|
case "change_thread_nickname":
|
|
457
631
|
case "change_thread_admins":
|
|
458
632
|
case "change_thread_approval_mode":
|
|
459
|
-
case "joinable_group_link_mode_change":
|
|
460
|
-
case "rtc_call_log":
|
|
461
633
|
case "group_poll":
|
|
462
|
-
case "update_vote":
|
|
463
|
-
case "magic_words":
|
|
464
634
|
case "messenger_call_log":
|
|
465
|
-
case "participant_joined_group_call":
|
|
466
|
-
|
|
635
|
+
case "participant_joined_group_call":
|
|
636
|
+
var fmtMsg;
|
|
467
637
|
try {
|
|
468
638
|
fmtMsg = utils.formatDeltaEvent(v.delta);
|
|
469
639
|
} catch (err) {
|
|
470
640
|
return globalCallback({
|
|
471
|
-
error:
|
|
641
|
+
error:
|
|
642
|
+
"Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
|
|
472
643
|
detail: err,
|
|
473
644
|
res: v.delta,
|
|
474
|
-
type: "parse_error"
|
|
645
|
+
type: "parse_error",
|
|
475
646
|
});
|
|
476
647
|
}
|
|
477
|
-
return
|
|
478
|
-
|
|
648
|
+
return (function () {
|
|
649
|
+
globalCallback(null, fmtMsg);
|
|
650
|
+
})();
|
|
479
651
|
default:
|
|
480
652
|
return;
|
|
481
653
|
}
|
|
482
|
-
|
|
483
|
-
|
|
654
|
+
break;
|
|
655
|
+
//For group images
|
|
656
|
+
case "ForcedFetch":
|
|
484
657
|
if (!v.delta.threadKey) return;
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
658
|
+
var mid = v.delta.messageId;
|
|
659
|
+
var tid = v.delta.threadKey.threadFbId;
|
|
488
660
|
if (mid && tid) {
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
"
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
661
|
+
const form = {
|
|
662
|
+
av: ctx.globalOptions.pageID,
|
|
663
|
+
queries: JSON.stringify({
|
|
664
|
+
o0: {
|
|
665
|
+
//This doc_id is valid as of March 25, 2020
|
|
666
|
+
doc_id: "2848441488556444",
|
|
667
|
+
query_params: {
|
|
668
|
+
thread_and_message_id: {
|
|
669
|
+
thread_id: tid.toString(),
|
|
670
|
+
message_id: mid,
|
|
671
|
+
},
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
}),
|
|
502
675
|
};
|
|
503
676
|
|
|
504
677
|
defaultFuncs
|
|
505
|
-
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar,
|
|
678
|
+
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
|
|
506
679
|
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
507
|
-
.then(resData => {
|
|
680
|
+
.then((resData) => {
|
|
508
681
|
if (resData[resData.length - 1].error_results > 0) {
|
|
509
682
|
throw resData[0].o0.errors;
|
|
510
683
|
}
|
|
511
684
|
|
|
512
685
|
if (resData[resData.length - 1].successful_results === 0) {
|
|
513
|
-
throw {
|
|
686
|
+
throw {
|
|
687
|
+
error: "forcedFetch: there was no successful_results",
|
|
688
|
+
res: resData,
|
|
689
|
+
};
|
|
514
690
|
}
|
|
515
691
|
|
|
516
|
-
|
|
692
|
+
var fetchData = resData[0].o0.data.message;
|
|
517
693
|
|
|
518
|
-
if (utils.getType(fetchData)
|
|
519
|
-
|
|
694
|
+
if (utils.getType(fetchData) == "Object") {
|
|
695
|
+
log.info("forcedFetch", fetchData);
|
|
520
696
|
switch (fetchData.__typename) {
|
|
521
697
|
case "ThreadImageMessage":
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
698
|
+
(!ctx.globalOptions.selfListen &&
|
|
699
|
+
fetchData.message_sender.id.toString() === ctx.userID) ||
|
|
700
|
+
!ctx.loggedIn
|
|
701
|
+
? undefined
|
|
702
|
+
: (function () {
|
|
703
|
+
globalCallback(null, {
|
|
704
|
+
type: "event",
|
|
705
|
+
threadID: utils.formatID(tid.toString()),
|
|
706
|
+
logMessageType: "log:thread-image",
|
|
707
|
+
logMessageData: {
|
|
708
|
+
image: {
|
|
709
|
+
attachmentID:
|
|
710
|
+
fetchData.image_with_metadata &&
|
|
711
|
+
fetchData.image_with_metadata
|
|
712
|
+
.legacy_attachment_id,
|
|
713
|
+
width:
|
|
714
|
+
fetchData.image_with_metadata &&
|
|
715
|
+
fetchData.image_with_metadata
|
|
716
|
+
.original_dimensions.x,
|
|
717
|
+
height:
|
|
718
|
+
fetchData.image_with_metadata &&
|
|
719
|
+
fetchData.image_with_metadata
|
|
720
|
+
.original_dimensions.y,
|
|
721
|
+
url:
|
|
722
|
+
fetchData.image_with_metadata &&
|
|
723
|
+
fetchData.image_with_metadata.preview.uri,
|
|
724
|
+
},
|
|
725
|
+
},
|
|
726
|
+
logMessageBody: fetchData.snippet,
|
|
727
|
+
timestamp: fetchData.timestamp_precise,
|
|
728
|
+
author: fetchData.message_sender.id,
|
|
729
|
+
});
|
|
730
|
+
})();
|
|
538
731
|
break;
|
|
539
732
|
case "UserMessage":
|
|
733
|
+
log.info("ff-Return", {
|
|
734
|
+
type: "message",
|
|
735
|
+
senderID: utils.formatID(fetchData.message_sender.id),
|
|
736
|
+
body: fetchData.message.text || "",
|
|
737
|
+
threadID: utils.formatID(tid.toString()),
|
|
738
|
+
messageID: fetchData.message_id,
|
|
739
|
+
attachments: [
|
|
740
|
+
{
|
|
741
|
+
type: "share",
|
|
742
|
+
ID: fetchData.extensible_attachment
|
|
743
|
+
.legacy_attachment_id,
|
|
744
|
+
url: fetchData.extensible_attachment.story_attachment
|
|
745
|
+
.url,
|
|
746
|
+
|
|
747
|
+
title:
|
|
748
|
+
fetchData.extensible_attachment.story_attachment
|
|
749
|
+
.title_with_entities.text,
|
|
750
|
+
description:
|
|
751
|
+
fetchData.extensible_attachment.story_attachment
|
|
752
|
+
.description.text,
|
|
753
|
+
source:
|
|
754
|
+
fetchData.extensible_attachment.story_attachment
|
|
755
|
+
.source,
|
|
756
|
+
|
|
757
|
+
image: (
|
|
758
|
+
(
|
|
759
|
+
fetchData.extensible_attachment.story_attachment
|
|
760
|
+
.media || {}
|
|
761
|
+
).image || {}
|
|
762
|
+
).uri,
|
|
763
|
+
width: (
|
|
764
|
+
(
|
|
765
|
+
fetchData.extensible_attachment.story_attachment
|
|
766
|
+
.media || {}
|
|
767
|
+
).image || {}
|
|
768
|
+
).width,
|
|
769
|
+
height: (
|
|
770
|
+
(
|
|
771
|
+
fetchData.extensible_attachment.story_attachment
|
|
772
|
+
.media || {}
|
|
773
|
+
).image || {}
|
|
774
|
+
).height,
|
|
775
|
+
playable:
|
|
776
|
+
(
|
|
777
|
+
fetchData.extensible_attachment.story_attachment
|
|
778
|
+
.media || {}
|
|
779
|
+
).is_playable || false,
|
|
780
|
+
duration:
|
|
781
|
+
(
|
|
782
|
+
fetchData.extensible_attachment.story_attachment
|
|
783
|
+
.media || {}
|
|
784
|
+
).playable_duration_in_ms || 0,
|
|
785
|
+
|
|
786
|
+
subattachments:
|
|
787
|
+
fetchData.extensible_attachment.subattachments,
|
|
788
|
+
properties:
|
|
789
|
+
fetchData.extensible_attachment.story_attachment
|
|
790
|
+
.properties,
|
|
791
|
+
},
|
|
792
|
+
],
|
|
793
|
+
mentions: {},
|
|
794
|
+
timestamp: parseInt(fetchData.timestamp_precise),
|
|
795
|
+
isGroup: fetchData.message_sender.id != tid.toString(),
|
|
796
|
+
});
|
|
540
797
|
globalCallback(null, {
|
|
541
798
|
type: "message",
|
|
542
|
-
senderID: utils.formatID(fetchData.message_sender
|
|
543
|
-
body: fetchData.message
|
|
799
|
+
senderID: utils.formatID(fetchData.message_sender.id),
|
|
800
|
+
body: fetchData.message.text || "",
|
|
544
801
|
threadID: utils.formatID(tid.toString()),
|
|
545
802
|
messageID: fetchData.message_id,
|
|
546
|
-
attachments: [
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
803
|
+
attachments: [
|
|
804
|
+
{
|
|
805
|
+
type: "share",
|
|
806
|
+
ID: fetchData.extensible_attachment
|
|
807
|
+
.legacy_attachment_id,
|
|
808
|
+
url: fetchData.extensible_attachment.story_attachment
|
|
809
|
+
.url,
|
|
810
|
+
|
|
811
|
+
title:
|
|
812
|
+
fetchData.extensible_attachment.story_attachment
|
|
813
|
+
.title_with_entities.text,
|
|
814
|
+
description:
|
|
815
|
+
fetchData.extensible_attachment.story_attachment
|
|
816
|
+
.description.text,
|
|
817
|
+
source:
|
|
818
|
+
fetchData.extensible_attachment.story_attachment
|
|
819
|
+
.source,
|
|
820
|
+
|
|
821
|
+
image: (
|
|
822
|
+
(
|
|
823
|
+
fetchData.extensible_attachment.story_attachment
|
|
824
|
+
.media || {}
|
|
825
|
+
).image || {}
|
|
826
|
+
).uri,
|
|
827
|
+
width: (
|
|
828
|
+
(
|
|
829
|
+
fetchData.extensible_attachment.story_attachment
|
|
830
|
+
.media || {}
|
|
831
|
+
).image || {}
|
|
832
|
+
).width,
|
|
833
|
+
height: (
|
|
834
|
+
(
|
|
835
|
+
fetchData.extensible_attachment.story_attachment
|
|
836
|
+
.media || {}
|
|
837
|
+
).image || {}
|
|
838
|
+
).height,
|
|
839
|
+
playable:
|
|
840
|
+
(
|
|
841
|
+
fetchData.extensible_attachment.story_attachment
|
|
842
|
+
.media || {}
|
|
843
|
+
).is_playable || false,
|
|
844
|
+
duration:
|
|
845
|
+
(
|
|
846
|
+
fetchData.extensible_attachment.story_attachment
|
|
847
|
+
.media || {}
|
|
848
|
+
).playable_duration_in_ms || 0,
|
|
849
|
+
|
|
850
|
+
subattachments:
|
|
851
|
+
fetchData.extensible_attachment.subattachments,
|
|
852
|
+
properties:
|
|
853
|
+
fetchData.extensible_attachment.story_attachment
|
|
854
|
+
.properties,
|
|
855
|
+
},
|
|
856
|
+
],
|
|
561
857
|
mentions: {},
|
|
562
858
|
timestamp: parseInt(fetchData.timestamp_precise),
|
|
563
|
-
isGroup:
|
|
859
|
+
isGroup: fetchData.message_sender.id != tid.toString(),
|
|
564
860
|
});
|
|
565
|
-
break;
|
|
566
861
|
}
|
|
567
862
|
} else {
|
|
568
|
-
|
|
863
|
+
log.error("forcedFetch", fetchData);
|
|
569
864
|
}
|
|
570
865
|
})
|
|
571
|
-
.catch(err =>
|
|
866
|
+
.catch((err) => {
|
|
867
|
+
log.error("forcedFetch", err);
|
|
868
|
+
});
|
|
572
869
|
}
|
|
573
870
|
break;
|
|
574
|
-
}
|
|
575
871
|
case "ThreadName":
|
|
576
872
|
case "ParticipantsAddedToGroupThread":
|
|
577
|
-
case "ParticipantLeftGroupThread":
|
|
578
|
-
|
|
873
|
+
case "ParticipantLeftGroupThread":
|
|
874
|
+
var formattedEvent;
|
|
579
875
|
try {
|
|
580
876
|
formattedEvent = utils.formatDeltaEvent(v.delta);
|
|
581
877
|
} catch (err) {
|
|
582
878
|
return globalCallback({
|
|
583
|
-
error:
|
|
879
|
+
error:
|
|
880
|
+
"Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
|
|
584
881
|
detail: err,
|
|
585
882
|
res: v.delta,
|
|
586
|
-
type: "parse_error"
|
|
883
|
+
type: "parse_error",
|
|
587
884
|
});
|
|
588
885
|
}
|
|
589
|
-
return (!ctx.globalOptions.selfListen &&
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
886
|
+
return (!ctx.globalOptions.selfListen &&
|
|
887
|
+
formattedEvent.author.toString() === ctx.userID) ||
|
|
888
|
+
!ctx.loggedIn
|
|
889
|
+
? undefined
|
|
890
|
+
: (function () {
|
|
891
|
+
globalCallback(null, formattedEvent);
|
|
892
|
+
})();
|
|
593
893
|
}
|
|
594
894
|
}
|
|
595
895
|
|
|
596
896
|
function markDelivery(ctx, api, threadID, messageID) {
|
|
597
897
|
if (threadID && messageID) {
|
|
598
|
-
api.markAsDelivered(threadID, messageID, err => {
|
|
898
|
+
api.markAsDelivered(threadID, messageID, (err) => {
|
|
599
899
|
if (err) {
|
|
600
|
-
|
|
900
|
+
log.error("markAsDelivered", err);
|
|
601
901
|
} else {
|
|
602
902
|
if (ctx.globalOptions.autoMarkRead) {
|
|
603
|
-
api.markAsRead(threadID,
|
|
604
|
-
if (
|
|
903
|
+
api.markAsRead(threadID, (err) => {
|
|
904
|
+
if (err) {
|
|
905
|
+
log.error("markAsDelivered", err);
|
|
906
|
+
}
|
|
605
907
|
});
|
|
606
908
|
}
|
|
607
909
|
}
|
|
@@ -609,74 +911,107 @@ function markDelivery(ctx, api, threadID, messageID) {
|
|
|
609
911
|
}
|
|
610
912
|
}
|
|
611
913
|
|
|
612
|
-
module.exports = function(defaultFuncs, api, ctx) {
|
|
613
|
-
|
|
614
|
-
|
|
914
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
915
|
+
var globalCallback = identity;
|
|
615
916
|
getSeqID = function getSeqID() {
|
|
616
917
|
ctx.t_mqttCalled = false;
|
|
617
918
|
defaultFuncs
|
|
618
919
|
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
|
|
619
920
|
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
620
|
-
.then(resData => {
|
|
621
|
-
if (utils.getType(resData)
|
|
622
|
-
throw {
|
|
921
|
+
.then((resData) => {
|
|
922
|
+
if (utils.getType(resData) != "Array") {
|
|
923
|
+
throw {
|
|
924
|
+
error: "Not logged in",
|
|
925
|
+
res: resData,
|
|
926
|
+
};
|
|
623
927
|
}
|
|
624
|
-
|
|
928
|
+
|
|
929
|
+
if (resData && resData[resData.length - 1].error_results > 0) {
|
|
625
930
|
throw resData[0].o0.errors;
|
|
626
931
|
}
|
|
932
|
+
|
|
627
933
|
if (resData[resData.length - 1].successful_results === 0) {
|
|
628
|
-
throw {
|
|
934
|
+
throw {
|
|
935
|
+
error: "getSeqId: there was no successful_results",
|
|
936
|
+
res: resData,
|
|
937
|
+
};
|
|
629
938
|
}
|
|
939
|
+
|
|
630
940
|
if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
|
|
631
|
-
ctx.lastSeqId =
|
|
941
|
+
ctx.lastSeqId =
|
|
942
|
+
resData[0].o0.data.viewer.message_threads.sync_sequence_id;
|
|
632
943
|
listenMqtt(defaultFuncs, api, ctx, globalCallback);
|
|
633
944
|
} else {
|
|
634
|
-
throw {
|
|
945
|
+
throw {
|
|
946
|
+
error: "getSeqId: no sync_sequence_id found.",
|
|
947
|
+
res: resData,
|
|
948
|
+
};
|
|
635
949
|
}
|
|
636
950
|
})
|
|
637
|
-
.catch(err => {
|
|
638
|
-
|
|
951
|
+
.catch((err) => {
|
|
952
|
+
log.error("getSeqId", err);
|
|
953
|
+
if (utils.getType(err) == "Object" && err.error === "Not logged in") {
|
|
639
954
|
ctx.loggedIn = false;
|
|
640
955
|
}
|
|
641
956
|
return globalCallback(err);
|
|
642
957
|
});
|
|
643
958
|
};
|
|
644
959
|
|
|
645
|
-
return
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
960
|
+
return function (callback) {
|
|
961
|
+
class MessageEmitter extends EventEmitter {
|
|
962
|
+
stopListening(callback) {
|
|
963
|
+
callback = callback || (() => {});
|
|
964
|
+
globalCallback = identity;
|
|
965
|
+
if (ctx.mqttClient) {
|
|
966
|
+
ctx.mqttClient.unsubscribe("/webrtc");
|
|
967
|
+
ctx.mqttClient.unsubscribe("/rtc_multi");
|
|
968
|
+
ctx.mqttClient.unsubscribe("/onevc");
|
|
969
|
+
ctx.mqttClient.publish("/browser_close", "{}");
|
|
970
|
+
ctx.mqttClient.end(false, function (...data) {
|
|
971
|
+
callback(data);
|
|
972
|
+
ctx.mqttClient = undefined;
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
}
|
|
654
976
|
}
|
|
977
|
+
|
|
978
|
+
var msgEmitter = new MessageEmitter();
|
|
979
|
+
globalCallback =
|
|
980
|
+
callback ||
|
|
981
|
+
function (error, message) {
|
|
982
|
+
if (error) {
|
|
983
|
+
return msgEmitter.emit("error", error);
|
|
984
|
+
}
|
|
985
|
+
msgEmitter.emit("message", message);
|
|
986
|
+
};
|
|
987
|
+
|
|
988
|
+
//Reset some stuff
|
|
989
|
+
if (!ctx.firstListen) ctx.lastSeqId = null;
|
|
655
990
|
ctx.syncToken = undefined;
|
|
656
991
|
ctx.t_mqttCalled = false;
|
|
657
|
-
|
|
992
|
+
|
|
993
|
+
//Same request as getThreadList
|
|
658
994
|
form = {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
})
|
|
995
|
+
av: ctx.globalOptions.pageID,
|
|
996
|
+
queries: JSON.stringify({
|
|
997
|
+
o0: {
|
|
998
|
+
doc_id: "3336396659757871",
|
|
999
|
+
query_params: {
|
|
1000
|
+
limit: 1,
|
|
1001
|
+
before: null,
|
|
1002
|
+
tags: ["INBOX"],
|
|
1003
|
+
includeDeliveryReceipts: false,
|
|
1004
|
+
includeSeqID: true,
|
|
1005
|
+
},
|
|
1006
|
+
},
|
|
1007
|
+
}),
|
|
672
1008
|
};
|
|
673
|
-
|
|
1009
|
+
|
|
674
1010
|
if (!ctx.firstListen || !ctx.lastSeqId) {
|
|
675
1011
|
getSeqID();
|
|
676
1012
|
} else {
|
|
677
1013
|
listenMqtt(defaultFuncs, api, ctx, globalCallback);
|
|
678
1014
|
}
|
|
679
|
-
|
|
680
1015
|
ctx.firstListen = false;
|
|
681
1016
|
return msgEmitter;
|
|
682
1017
|
};
|