@dongdev/fca-unofficial 2.0.13 → 2.0.15
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/CHANGELOG.md
CHANGED
package/module/loginHelper.js
CHANGED
@@ -543,7 +543,8 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
|
|
543
543
|
clientID: ((Math.random() * 2147483648) | 0).toString(16),
|
544
544
|
clientId: getFrom(html, '["MqttWebDeviceID",[],{"clientID":"', '"}') || "",
|
545
545
|
wsReqNumber: 0,
|
546
|
-
wsTaskNumber: 0
|
546
|
+
wsTaskNumber: 0,
|
547
|
+
tasks: new Map()
|
547
548
|
};
|
548
549
|
ctx.performAutoLogin = async () => {
|
549
550
|
try {
|
package/package.json
CHANGED
@@ -1,110 +1,67 @@
|
|
1
1
|
"use strict";
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
// Check if thread is a single person chat or a group chat
|
16
|
-
// More info on this is in api.sendMessage
|
17
|
-
if (getType(isGroup) == "Boolean") {
|
18
|
-
if (!isGroup) {
|
19
|
-
form.to = threadID;
|
20
|
-
}
|
21
|
-
defaultFuncs
|
22
|
-
.post("https://www.facebook.com/ajax/messaging/typ.php", ctx.jar, form)
|
23
|
-
.then(parseAndCheckLogin(ctx, defaultFuncs))
|
24
|
-
.then(function(resData) {
|
25
|
-
if (resData.error) {
|
26
|
-
throw resData;
|
27
|
-
}
|
28
|
-
|
29
|
-
return callback();
|
30
|
-
})
|
31
|
-
.catch(function(err) {
|
32
|
-
log.error("sendTypingIndicator", err);
|
33
|
-
if (getType(err) == "Object" && err.error === "Not logged in") {
|
34
|
-
ctx.loggedIn = false;
|
35
|
-
}
|
36
|
-
return callback(err);
|
37
|
-
});
|
38
|
-
} else {
|
39
|
-
api.getUserInfo(threadID, function(err, res) {
|
40
|
-
if (err) {
|
41
|
-
return callback(err);
|
42
|
-
}
|
43
|
-
|
44
|
-
// If id is single person chat
|
45
|
-
if (Object.keys(res).length > 0) {
|
46
|
-
form.to = threadID;
|
47
|
-
}
|
48
|
-
|
49
|
-
defaultFuncs
|
50
|
-
.post(
|
51
|
-
"https://www.facebook.com/ajax/messaging/typ.php",
|
52
|
-
ctx.jar,
|
53
|
-
form
|
54
|
-
)
|
55
|
-
.then(parseAndCheckLogin(ctx, defaultFuncs))
|
56
|
-
.then(function(resData) {
|
57
|
-
if (resData.error) {
|
58
|
-
throw resData;
|
59
|
-
}
|
60
|
-
|
61
|
-
return callback();
|
62
|
-
})
|
63
|
-
.catch(function(err) {
|
64
|
-
log.error("sendTypingIndicator", err);
|
65
|
-
if (
|
66
|
-
getType(err) == "Object" &&
|
67
|
-
err.error === "Not logged in."
|
68
|
-
) {
|
69
|
-
ctx.loggedIn = false;
|
70
|
-
}
|
71
|
-
return callback(err);
|
72
|
-
});
|
73
|
-
});
|
2
|
+
const { getType } = require("../../utils/format.js");
|
3
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
4
|
+
return function sendTyping(threadID, isTyping, options, callback) {
|
5
|
+
var resolveFunc = function () { };
|
6
|
+
var rejectFunc = function () { };
|
7
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
8
|
+
resolveFunc = resolve;
|
9
|
+
rejectFunc = reject;
|
10
|
+
});
|
11
|
+
if (getType(options) == "Function" || getType(options) == "AsyncFunction") {
|
12
|
+
callback = options;
|
13
|
+
options = {};
|
74
14
|
}
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
"sendTypingIndicator",
|
85
|
-
"callback is not a function - ignoring."
|
86
|
-
);
|
87
|
-
}
|
88
|
-
callback = () => {};
|
15
|
+
options = options || {};
|
16
|
+
if (!callback || getType(callback) != "Function" && getType(callback) != "AsyncFunction") {
|
17
|
+
callback = function (err, data) {
|
18
|
+
if (err) return rejectFunc(err);
|
19
|
+
resolveFunc(data);
|
20
|
+
};
|
21
|
+
}
|
22
|
+
if (!threadID) {
|
23
|
+
return callback(new Error("threadID is required"));
|
89
24
|
}
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
) {
|
98
|
-
|
99
|
-
|
100
|
-
"
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
25
|
+
const threadIDs = Array.isArray(threadID) ? threadID : [threadID];
|
26
|
+
threadIDs.forEach(tid => {
|
27
|
+
var isGroupThread = getType(tid) === "Array" ? 0 : 1;
|
28
|
+
var threadType = isGroupThread ? 2 : 1;
|
29
|
+
var duration = options.duration || 10000;
|
30
|
+
var autoStop = options.autoStop !== false;
|
31
|
+
var attribution = options.type || 0;
|
32
|
+
const publishTypingStatus = (isTypingStatus) => {
|
33
|
+
ctx.mqttClient.publish('/ls_req',
|
34
|
+
JSON.stringify({
|
35
|
+
app_id: "772021112871879",
|
36
|
+
payload: JSON.stringify({
|
37
|
+
label: "3",
|
38
|
+
payload: JSON.stringify({
|
39
|
+
"thread_key": parseInt(tid),
|
40
|
+
"is_group_thread": isGroupThread,
|
41
|
+
"is_typing": isTypingStatus ? 1 : 0,
|
42
|
+
"attribution": attribution,
|
43
|
+
"sync_group": 1,
|
44
|
+
"thread_type": threadType
|
45
|
+
}),
|
46
|
+
version: "8965252033599983"
|
47
|
+
}),
|
48
|
+
request_id: ++ctx.req_ID,
|
49
|
+
type: 4
|
50
|
+
}),
|
51
|
+
{
|
52
|
+
qos: 1,
|
53
|
+
retain: false,
|
54
|
+
}
|
55
|
+
);
|
56
|
+
};
|
57
|
+
publishTypingStatus(isTyping);
|
58
|
+
if (isTyping && autoStop) {
|
59
|
+
setTimeout(() => {
|
60
|
+
publishTypingStatus(false);
|
61
|
+
}, duration);
|
105
62
|
}
|
106
|
-
|
107
|
-
|
108
|
-
|
63
|
+
});
|
64
|
+
callback(null, true);
|
65
|
+
return returnPromise;
|
109
66
|
};
|
110
67
|
};
|
@@ -1,105 +1,76 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
|
-
const
|
3
|
+
const logger = require("../../../func/logger");
|
4
4
|
const { generateOfflineThreadingID, getCurrentTimestamp } = require("../../utils/format");
|
5
|
-
const { parseAndCheckLogin } = require("../../utils/client");
|
6
5
|
|
7
6
|
module.exports = function (defaultFuncs, api, ctx) {
|
8
|
-
function
|
9
|
-
let resolveFunc = function () { };
|
10
|
-
let rejectFunc = function () { };
|
11
|
-
const returnPromise = new Promise(function (resolve, reject) {
|
12
|
-
resolveFunc = resolve;
|
13
|
-
rejectFunc = reject;
|
14
|
-
});
|
15
|
-
if (!callback) {
|
16
|
-
callback = function (err) {
|
17
|
-
if (err) return rejectFunc(err);
|
18
|
-
resolveFunc();
|
19
|
-
};
|
20
|
-
}
|
21
|
-
const variables = {
|
22
|
-
data: {
|
23
|
-
client_mutation_id: ctx.clientMutationId++,
|
24
|
-
actor_id: ctx.userID,
|
25
|
-
action: reaction === "" ? "REMOVE_REACTION" : "ADD_REACTION",
|
26
|
-
message_id: messageID,
|
27
|
-
reaction: reaction
|
28
|
-
}
|
29
|
-
};
|
30
|
-
const qs = {
|
31
|
-
doc_id: "1491398900900362",
|
32
|
-
variables: JSON.stringify(variables),
|
33
|
-
dpr: 1
|
34
|
-
};
|
35
|
-
defaultFuncs
|
36
|
-
.postFormData("https://www.facebook.com/webgraphql/mutation/", ctx.jar, {}, qs)
|
37
|
-
.then(parseAndCheckLogin(ctx.jar, defaultFuncs))
|
38
|
-
.then(function (resData) {
|
39
|
-
if (!resData) throw { error: "setReaction returned empty object." };
|
40
|
-
if (resData.error) throw resData;
|
41
|
-
callback(null);
|
42
|
-
})
|
43
|
-
.catch(function (err) {
|
44
|
-
log.error("setReaction", err);
|
45
|
-
return callback(err);
|
46
|
-
});
|
47
|
-
return returnPromise;
|
48
|
-
}
|
49
|
-
|
50
|
-
function setMessageReactionMqtt(reaction, messageID, threadID, callback) {
|
51
|
-
if (!ctx.mqttClient) return setMessageReactionNoMqtt(reaction, messageID, callback);
|
7
|
+
return function setMessageReaction(reaction, messageID, threadID, callback) {
|
52
8
|
return new Promise((resolve, reject) => {
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
reaction_style: null,
|
63
|
-
sync_group: 1,
|
64
|
-
send_attribution: Math.random() < 0.5 ? 65537 : 524289
|
65
|
-
};
|
66
|
-
const task = {
|
67
|
-
failure_count: null,
|
68
|
-
label: "29",
|
69
|
-
payload: JSON.stringify(taskPayload),
|
70
|
-
queue_name: JSON.stringify(["reaction", messageID]),
|
71
|
-
task_id: taskNumber
|
72
|
-
};
|
73
|
-
const content = {
|
74
|
-
app_id: "2220391788200892",
|
75
|
-
payload: JSON.stringify({
|
76
|
-
data_trace_id: null,
|
77
|
-
epoch_id: parseInt(generateOfflineThreadingID()),
|
78
|
-
tasks: [task],
|
79
|
-
version_id: "7158486590867448"
|
80
|
-
}),
|
81
|
-
request_id: ctx.wsReqNumber,
|
82
|
-
type: 3
|
83
|
-
};
|
84
|
-
const internalCb = (err) => {
|
85
|
-
if (typeof callback === "function") callback(err);
|
86
|
-
if (err) return reject(err);
|
87
|
-
return resolve();
|
88
|
-
};
|
89
|
-
ctx.tasks.set(taskNumber, { type: "set_message_reaction", callback: internalCb });
|
90
|
-
ctx.mqttClient.publish("/ls_req", JSON.stringify(content), { qos: 1, retain: false });
|
91
|
-
if (typeof callback !== "function") resolve();
|
92
|
-
} catch (e) {
|
93
|
-
if (typeof callback === "function") callback(e);
|
94
|
-
reject(e);
|
9
|
+
if (!ctx.mqttClient) {
|
10
|
+
const err = new Error("MQTT client not connected");
|
11
|
+
if (typeof callback === 'function') callback(err);
|
12
|
+
return reject(err);
|
13
|
+
}
|
14
|
+
if (!reaction || !messageID || !threadID) {
|
15
|
+
const err = new Error("Missing required parameters");
|
16
|
+
if (typeof callback === 'function') callback(err);
|
17
|
+
return reject(err);
|
95
18
|
}
|
19
|
+
const reqID = ++ctx.wsReqNumber;
|
20
|
+
const taskID = ++ctx.wsTaskNumber;
|
21
|
+
const taskPayload = {
|
22
|
+
thread_key: threadID,
|
23
|
+
timestamp_ms: getCurrentTimestamp(),
|
24
|
+
message_id: messageID,
|
25
|
+
reaction: reaction,
|
26
|
+
actor_id: ctx.userID,
|
27
|
+
reaction_style: null,
|
28
|
+
sync_group: 1,
|
29
|
+
send_attribution: 65537,
|
30
|
+
dataclass_params: null,
|
31
|
+
attachment_fbid: null
|
32
|
+
};
|
33
|
+
const task = {
|
34
|
+
failure_count: null,
|
35
|
+
label: "29",
|
36
|
+
payload: JSON.stringify(taskPayload),
|
37
|
+
queue_name: JSON.stringify(["reaction", messageID]),
|
38
|
+
task_id: taskID,
|
39
|
+
};
|
40
|
+
const mqttForm = {
|
41
|
+
app_id: "772021112871879",
|
42
|
+
payload: JSON.stringify({
|
43
|
+
data_trace_id: null,
|
44
|
+
epoch_id: parseInt(generateOfflineThreadingID()),
|
45
|
+
tasks: [task],
|
46
|
+
version_id: "25376272951962053"
|
47
|
+
}),
|
48
|
+
request_id: reqID,
|
49
|
+
type: 3
|
50
|
+
};
|
51
|
+
const handleResponse = (topic, message) => {
|
52
|
+
if (topic !== "/ls_resp") return;
|
53
|
+
let json;
|
54
|
+
try {
|
55
|
+
json = JSON.parse(message.toString());
|
56
|
+
json.payload = JSON.parse(json.payload);
|
57
|
+
} catch {
|
58
|
+
return;
|
59
|
+
}
|
60
|
+
if (json.request_id !== reqID) return;
|
61
|
+
ctx.mqttClient.removeListener("message", handleResponse);
|
62
|
+
if (typeof callback === 'function') callback(null, { success: true });
|
63
|
+
return resolve({ success: true });
|
64
|
+
};
|
65
|
+
ctx.mqttClient.on("message", handleResponse);
|
66
|
+
ctx.mqttClient.publish("/ls_req", JSON.stringify(mqttForm), { qos: 1, retain: false }, (err) => {
|
67
|
+
if (err) {
|
68
|
+
ctx.mqttClient.removeListener("message", handleResponse);
|
69
|
+
logger("setMessageReaction" + err, "error");
|
70
|
+
if (typeof callback === 'function') callback(err);
|
71
|
+
return reject(err);
|
72
|
+
}
|
73
|
+
});
|
96
74
|
});
|
97
|
-
}
|
98
|
-
|
99
|
-
return function setMessageReaction(reaction, messageID, threadID, callback) {
|
100
|
-
if (ctx.mqttClient) {
|
101
|
-
return setMessageReactionMqtt(reaction, messageID, threadID, callback);
|
102
|
-
}
|
103
|
-
return setMessageReactionNoMqtt(reaction, messageID, threadID, callback);
|
104
75
|
};
|
105
76
|
};
|
@@ -81,9 +81,10 @@ module.exports = function createListenMqtt(deps) {
|
|
81
81
|
return;
|
82
82
|
}
|
83
83
|
logger(`MQTT error: ${msg}`, "error");
|
84
|
-
mqttClient.end();
|
85
|
-
logger("MQTT autoReconnect listenMqtt() in 2000ms", "warn");
|
86
|
-
setTimeout(() => listenMqtt(defaultFuncs, api, ctx, globalCallback), 2000);
|
84
|
+
// mqttClient.end();
|
85
|
+
// logger("MQTT autoReconnect listenMqtt() in 2000ms", "warn");
|
86
|
+
// setTimeout(() => listenMqtt(defaultFuncs, api, ctx, globalCallback), 2000);
|
87
|
+
process.exit(1);
|
87
88
|
});
|
88
89
|
mqttClient.on("connect", function () {
|
89
90
|
if (process.env.OnStatus === undefined) {
|