@lazyneoaz/nkxchat 1.0.0
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/LICENSE +3 -0
- package/README.md +199 -0
- package/examples/login-with-cookies.js +102 -0
- package/examples/verify.js +70 -0
- package/index.js +2 -0
- package/package.json +84 -0
- package/src/apis/addExternalModule.js +24 -0
- package/src/apis/addUserToGroup.js +108 -0
- package/src/apis/changeAdminStatus.js +148 -0
- package/src/apis/changeArchivedStatus.js +61 -0
- package/src/apis/changeAvatar.js +103 -0
- package/src/apis/changeBio.js +69 -0
- package/src/apis/changeBlockedStatus.js +54 -0
- package/src/apis/changeGroupImage.js +136 -0
- package/src/apis/changeThreadColor.js +116 -0
- package/src/apis/changeThreadEmoji.js +53 -0
- package/src/apis/comment.js +207 -0
- package/src/apis/createAITheme.js +129 -0
- package/src/apis/createNewGroup.js +79 -0
- package/src/apis/createPoll.js +73 -0
- package/src/apis/deleteMessage.js +44 -0
- package/src/apis/deleteThread.js +52 -0
- package/src/apis/editMessage.js +70 -0
- package/src/apis/emoji.js +124 -0
- package/src/apis/enableAutoSaveAppState.js +69 -0
- package/src/apis/fetchThemeData.js +113 -0
- package/src/apis/follow.js +81 -0
- package/src/apis/forwardAttachment.js +178 -0
- package/src/apis/forwardMessage.js +52 -0
- package/src/apis/friend.js +243 -0
- package/src/apis/gcmember.js +122 -0
- package/src/apis/gcname.js +123 -0
- package/src/apis/gcrule.js +119 -0
- package/src/apis/getAccess.js +111 -0
- package/src/apis/getBotInfo.js +88 -0
- package/src/apis/getBotInitialData.js +43 -0
- package/src/apis/getEmojiUrl.js +40 -0
- package/src/apis/getFriendsList.js +79 -0
- package/src/apis/getMessage.js +423 -0
- package/src/apis/getTheme.js +123 -0
- package/src/apis/getThemeInfo.js +116 -0
- package/src/apis/getThemePictures.js +87 -0
- package/src/apis/getThreadColors.js +119 -0
- package/src/apis/getThreadHistory.js +239 -0
- package/src/apis/getThreadInfo.js +267 -0
- package/src/apis/getThreadList.js +232 -0
- package/src/apis/getThreadPictures.js +58 -0
- package/src/apis/getUserID.js +117 -0
- package/src/apis/getUserInfo.js +513 -0
- package/src/apis/getUserInfoV2.js +146 -0
- package/src/apis/handleFriendRequest.js +66 -0
- package/src/apis/handleMessageRequest.js +50 -0
- package/src/apis/httpGet.js +63 -0
- package/src/apis/httpPost.js +89 -0
- package/src/apis/httpPostFormData.js +69 -0
- package/src/apis/listenMqtt.js +924 -0
- package/src/apis/listenSpeed.js +178 -0
- package/src/apis/logout.js +63 -0
- package/src/apis/markAsDelivered.js +47 -0
- package/src/apis/markAsRead.js +95 -0
- package/src/apis/markAsReadAll.js +40 -0
- package/src/apis/markAsSeen.js +70 -0
- package/src/apis/mqttDeltaValue.js +252 -0
- package/src/apis/muteThread.js +45 -0
- package/src/apis/nickname.js +132 -0
- package/src/apis/notes.js +163 -0
- package/src/apis/pinMessage.js +150 -0
- package/src/apis/produceMetaTheme.js +160 -0
- package/src/apis/realtime.js +182 -0
- package/src/apis/refreshFb_dtsg.js +94 -0
- package/src/apis/removeUserFromGroup.js +117 -0
- package/src/apis/resolvePhotoUrl.js +58 -0
- package/src/apis/searchForThread.js +154 -0
- package/src/apis/sendEffect.js +306 -0
- package/src/apis/sendMessage.js +353 -0
- package/src/apis/sendMessageMqtt.js +255 -0
- package/src/apis/sendTypingIndicator.js +40 -0
- package/src/apis/setMessageReaction.js +27 -0
- package/src/apis/setMessageReactionMqtt.js +61 -0
- package/src/apis/setPostReaction.js +118 -0
- package/src/apis/setThreadTheme.js +210 -0
- package/src/apis/setThreadThemeMqtt.js +94 -0
- package/src/apis/setTitle.js +26 -0
- package/src/apis/share.js +106 -0
- package/src/apis/shareContact.js +66 -0
- package/src/apis/stickers.js +257 -0
- package/src/apis/story.js +181 -0
- package/src/apis/theme.js +233 -0
- package/src/apis/unfriend.js +47 -0
- package/src/apis/unsendMessage.js +17 -0
- package/src/apis/uploadAttachment.js +87 -0
- package/src/database/appStateBackup.js +189 -0
- package/src/database/models/index.js +56 -0
- package/src/database/models/thread.js +31 -0
- package/src/database/models/user.js +32 -0
- package/src/database/threadData.js +101 -0
- package/src/database/userData.js +90 -0
- package/src/engine/client.js +92 -0
- package/src/engine/models/buildAPI.js +118 -0
- package/src/engine/models/loginHelper.js +492 -0
- package/src/engine/models/setOptions.js +88 -0
- package/src/types/index.d.ts +498 -0
- package/src/utils/antiSuspension.js +516 -0
- package/src/utils/auth-helpers.js +149 -0
- package/src/utils/autoReLogin.js +237 -0
- package/src/utils/axios.js +368 -0
- package/src/utils/cache.js +54 -0
- package/src/utils/clients.js +279 -0
- package/src/utils/constants.js +525 -0
- package/src/utils/formatters/data/formatAttachment.js +370 -0
- package/src/utils/formatters/data/formatDelta.js +109 -0
- package/src/utils/formatters/index.js +159 -0
- package/src/utils/formatters/value/formatCookie.js +91 -0
- package/src/utils/formatters/value/formatDate.js +36 -0
- package/src/utils/formatters/value/formatID.js +16 -0
- package/src/utils/formatters.js +1369 -0
- package/src/utils/headers.js +235 -0
- package/src/utils/index.js +152 -0
- package/src/utils/monitoring.js +333 -0
- package/src/utils/rateLimiter.js +251 -0
- package/src/utils/tokenRefresh.js +285 -0
- package/src/utils/user-agents.js +238 -0
- package/src/utils/validation.js +157 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
function generateOfflineThreadingID() {
|
|
6
|
+
return Date.now().toString() + Math.floor(Math.random() * 1000000).toString();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function getType(obj) {
|
|
10
|
+
return Object.prototype.toString.call(obj).slice(8, -1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
14
|
+
return function changeAdminStatus(threadID, adminID, adminStatus, callback) {
|
|
15
|
+
let resolveFunc = function() {};
|
|
16
|
+
let rejectFunc = function() {};
|
|
17
|
+
const returnPromise = new Promise(function(resolve, reject) {
|
|
18
|
+
resolveFunc = resolve;
|
|
19
|
+
rejectFunc = reject;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (!callback) {
|
|
23
|
+
callback = function(err, data) {
|
|
24
|
+
if (err) return rejectFunc(err);
|
|
25
|
+
resolveFunc(data);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (getType(threadID) !== "String") {
|
|
30
|
+
return callback({ error: "changeAdminStatus: threadID must be a string" });
|
|
31
|
+
}
|
|
32
|
+
if (getType(adminID) !== "String" && getType(adminID) !== "Array") {
|
|
33
|
+
return callback({ error: "changeAdminStatus: adminID must be a string or an array" });
|
|
34
|
+
}
|
|
35
|
+
if (getType(adminStatus) !== "Boolean") {
|
|
36
|
+
return callback({ error: "changeAdminStatus: adminStatus must be true or false" });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (ctx.mqttClient) {
|
|
40
|
+
const tasks = [];
|
|
41
|
+
const isAdmin = adminStatus ? 1 : 0;
|
|
42
|
+
const epochID = generateOfflineThreadingID();
|
|
43
|
+
|
|
44
|
+
if (getType(adminID) === "Array") {
|
|
45
|
+
adminID.forEach((id, index) => {
|
|
46
|
+
tasks.push({
|
|
47
|
+
failure_count: null,
|
|
48
|
+
label: "25",
|
|
49
|
+
payload: JSON.stringify({
|
|
50
|
+
thread_key: threadID,
|
|
51
|
+
contact_id: id,
|
|
52
|
+
is_admin: isAdmin
|
|
53
|
+
}),
|
|
54
|
+
queue_name: "admin_status",
|
|
55
|
+
task_id: index + 1
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
tasks.push({
|
|
60
|
+
failure_count: null,
|
|
61
|
+
label: "25",
|
|
62
|
+
payload: JSON.stringify({
|
|
63
|
+
thread_key: threadID,
|
|
64
|
+
contact_id: adminID,
|
|
65
|
+
is_admin: isAdmin
|
|
66
|
+
}),
|
|
67
|
+
queue_name: "admin_status",
|
|
68
|
+
task_id: 1
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let count_req = 0;
|
|
73
|
+
const form = JSON.stringify({
|
|
74
|
+
app_id: "2220391788200892",
|
|
75
|
+
payload: JSON.stringify({
|
|
76
|
+
epoch_id: epochID,
|
|
77
|
+
tasks: tasks,
|
|
78
|
+
version_id: "8798795233522156"
|
|
79
|
+
}),
|
|
80
|
+
request_id: ++count_req,
|
|
81
|
+
type: 3
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
ctx.mqttClient.publish("/ls_req", form, {}, (err, _packet) => {
|
|
85
|
+
if (err) {
|
|
86
|
+
utils.error("changeAdminStatus (MQTT)", err);
|
|
87
|
+
return callback(err);
|
|
88
|
+
} else {
|
|
89
|
+
utils.log("Admin status changed successfully via MQTT");
|
|
90
|
+
return callback(null, { success: true });
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
} else {
|
|
94
|
+
utils.warn("MQTT client not available, using HTTP fallback for changeAdminStatus");
|
|
95
|
+
const tasks = [];
|
|
96
|
+
const epochID = generateOfflineThreadingID();
|
|
97
|
+
|
|
98
|
+
if (getType(adminID) === "Array") {
|
|
99
|
+
adminID.forEach((id, index) => {
|
|
100
|
+
tasks.push({
|
|
101
|
+
label: '25',
|
|
102
|
+
payload: JSON.stringify({ thread_key: threadID, contact_id: id, is_admin: adminStatus }),
|
|
103
|
+
queue_name: 'admin_status',
|
|
104
|
+
task_id: index + 1,
|
|
105
|
+
failure_count: null
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
} else {
|
|
109
|
+
tasks.push({
|
|
110
|
+
label: '25',
|
|
111
|
+
payload: JSON.stringify({ thread_key: threadID, contact_id: adminID, is_admin: adminStatus }),
|
|
112
|
+
queue_name: 'admin_status',
|
|
113
|
+
task_id: 1,
|
|
114
|
+
failure_count: null
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const form = {
|
|
119
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
120
|
+
request_id: 1,
|
|
121
|
+
type: 3,
|
|
122
|
+
payload: {
|
|
123
|
+
version_id: '3816854585040595',
|
|
124
|
+
tasks: tasks,
|
|
125
|
+
epoch_id: epochID,
|
|
126
|
+
data_trace_id: null
|
|
127
|
+
},
|
|
128
|
+
app_id: '772021112871879'
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
form.payload = JSON.stringify(form.payload);
|
|
132
|
+
|
|
133
|
+
defaultFuncs
|
|
134
|
+
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
|
|
135
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
136
|
+
.then(() => {
|
|
137
|
+
utils.log("Admin status changed successfully via HTTP");
|
|
138
|
+
callback(null, { success: true });
|
|
139
|
+
})
|
|
140
|
+
.catch(err => {
|
|
141
|
+
utils.error("changeAdminStatus (HTTP)", err);
|
|
142
|
+
callback(err);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return returnPromise;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (defaultFuncs, api, ctx) => {
|
|
6
|
+
return async function changeArchivedStatus(threadIDs, archive, callback) {
|
|
7
|
+
let resolveFunc = () => {};
|
|
8
|
+
let rejectFunc = () => {};
|
|
9
|
+
const returnPromise = new Promise((resolve, reject) => {
|
|
10
|
+
resolveFunc = resolve;
|
|
11
|
+
rejectFunc = reject;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (!callback) {
|
|
15
|
+
callback = (err, result) => {
|
|
16
|
+
if (err) return rejectFunc(err);
|
|
17
|
+
resolveFunc(result);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
if (utils.getType(archive) === "Function") {
|
|
23
|
+
callback = archive;
|
|
24
|
+
archive = true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (utils.getType(archive) !== "Boolean") {
|
|
28
|
+
throw new Error("archive parameter must be a boolean");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!Array.isArray(threadIDs)) {
|
|
32
|
+
threadIDs = [threadIDs];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const form = {
|
|
36
|
+
should_archive: archive
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
threadIDs.forEach(id => {
|
|
40
|
+
form[`thread_fbids[${id}]`] = true;
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const res = await defaultFuncs.post(
|
|
44
|
+
"https://www.facebook.com/ajax/mercury/change_archived_status.php",
|
|
45
|
+
ctx.jar,
|
|
46
|
+
form
|
|
47
|
+
).then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
48
|
+
|
|
49
|
+
if (res && res.error) {
|
|
50
|
+
throw res;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
callback(null, { success: true });
|
|
54
|
+
} catch (err) {
|
|
55
|
+
utils.error("changeArchivedStatus", err);
|
|
56
|
+
callback(err);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return returnPromise;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (defaultFuncs, api, ctx) => {
|
|
6
|
+
async function handleUpload(image) {
|
|
7
|
+
const form = {
|
|
8
|
+
profile_id: ctx.userID,
|
|
9
|
+
photo_source: 57,
|
|
10
|
+
av: ctx.userID,
|
|
11
|
+
file: image
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return defaultFuncs.postFormData(
|
|
15
|
+
"https://www.facebook.com/profile/picture/upload/",
|
|
16
|
+
ctx.jar,
|
|
17
|
+
form,
|
|
18
|
+
{}
|
|
19
|
+
).then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
20
|
+
.then(resData => {
|
|
21
|
+
if (resData.error) throw resData;
|
|
22
|
+
return resData;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return async function changeAvatar(image, caption, timestamp, callback) {
|
|
27
|
+
let resolveFunc = () => {};
|
|
28
|
+
let rejectFunc = () => {};
|
|
29
|
+
const returnPromise = new Promise((resolve, reject) => {
|
|
30
|
+
resolveFunc = resolve;
|
|
31
|
+
rejectFunc = reject;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (!timestamp && utils.getType(caption) === "Number") {
|
|
35
|
+
timestamp = caption;
|
|
36
|
+
caption = "";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!timestamp && !callback && (utils.getType(caption) === "Function")) {
|
|
40
|
+
callback = caption;
|
|
41
|
+
caption = "";
|
|
42
|
+
timestamp = null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!callback) {
|
|
46
|
+
callback = (err, data) => {
|
|
47
|
+
if (err) return rejectFunc(err);
|
|
48
|
+
resolveFunc(data);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
if (!utils.isReadableStream(image)) {
|
|
54
|
+
throw new Error("Image is not a readable stream");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const payload = await handleUpload(image);
|
|
58
|
+
|
|
59
|
+
const form = {
|
|
60
|
+
av: ctx.i_userID || ctx.userID,
|
|
61
|
+
fb_api_req_friendly_name: "ProfileCometProfilePictureSetMutation",
|
|
62
|
+
fb_api_caller_class: "RelayModern",
|
|
63
|
+
doc_id: "5066134240065849",
|
|
64
|
+
variables: JSON.stringify({
|
|
65
|
+
input: {
|
|
66
|
+
caption: caption || "",
|
|
67
|
+
existing_photo_id: payload.payload.fbid,
|
|
68
|
+
expiration_time: timestamp,
|
|
69
|
+
profile_id: ctx.i_userID || ctx.userID,
|
|
70
|
+
profile_pic_method: "EXISTING",
|
|
71
|
+
profile_pic_source: "TIMELINE",
|
|
72
|
+
scaled_crop_rect: {
|
|
73
|
+
height: 1,
|
|
74
|
+
width: 1,
|
|
75
|
+
x: 0,
|
|
76
|
+
y: 0
|
|
77
|
+
},
|
|
78
|
+
skip_cropping: true,
|
|
79
|
+
actor_id: ctx.i_userID || ctx.userID,
|
|
80
|
+
client_mutation_id: Math.round(Math.random() * 19).toString()
|
|
81
|
+
},
|
|
82
|
+
isPage: false,
|
|
83
|
+
isProfile: true,
|
|
84
|
+
scale: 3
|
|
85
|
+
})
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const res = await defaultFuncs.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
|
|
89
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
90
|
+
|
|
91
|
+
if (res.errors) {
|
|
92
|
+
throw res;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
callback(null, res[0].data.profile_picture_set);
|
|
96
|
+
} catch (err) {
|
|
97
|
+
utils.error("changeAvatar", err);
|
|
98
|
+
callback(err);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return returnPromise;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (defaultFuncs, api, ctx) => {
|
|
6
|
+
return async function changeBio(bio, publish, callback) {
|
|
7
|
+
let resolveFunc = () => {};
|
|
8
|
+
let rejectFunc = () => {};
|
|
9
|
+
const returnPromise = new Promise((resolve, reject) => {
|
|
10
|
+
resolveFunc = resolve;
|
|
11
|
+
rejectFunc = reject;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (!callback) {
|
|
15
|
+
if (utils.getType(publish) === "Function") {
|
|
16
|
+
callback = publish;
|
|
17
|
+
publish = false;
|
|
18
|
+
} else {
|
|
19
|
+
callback = (err) => {
|
|
20
|
+
if (err) return rejectFunc(err);
|
|
21
|
+
resolveFunc();
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (utils.getType(publish) !== "Boolean") {
|
|
27
|
+
publish = false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (utils.getType(bio) !== "String") {
|
|
31
|
+
bio = "";
|
|
32
|
+
publish = false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const form = {
|
|
37
|
+
fb_api_caller_class: "RelayModern",
|
|
38
|
+
fb_api_req_friendly_name: "ProfileCometSetBioMutation",
|
|
39
|
+
doc_id: "2725043627607610",
|
|
40
|
+
variables: JSON.stringify({
|
|
41
|
+
input: {
|
|
42
|
+
bio: bio,
|
|
43
|
+
publish_bio_feed_story: publish,
|
|
44
|
+
actor_id: ctx.i_userID || ctx.userID,
|
|
45
|
+
client_mutation_id: Math.round(Math.random() * 1024).toString()
|
|
46
|
+
},
|
|
47
|
+
hasProfileTileViewID: false,
|
|
48
|
+
profileTileViewID: null,
|
|
49
|
+
scale: 1
|
|
50
|
+
}),
|
|
51
|
+
av: ctx.i_userID || ctx.userID
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const res = await defaultFuncs.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
|
|
55
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
56
|
+
|
|
57
|
+
if (res.errors) {
|
|
58
|
+
throw res;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
callback(null, { success: true });
|
|
62
|
+
} catch (err) {
|
|
63
|
+
utils.error("changeBio", err);
|
|
64
|
+
callback(err);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return returnPromise;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (defaultFuncs, api, ctx) => {
|
|
6
|
+
return async function changeBlockedStatus(userID, block, callback) {
|
|
7
|
+
let resolveFunc = () => {};
|
|
8
|
+
let rejectFunc = () => {};
|
|
9
|
+
const returnPromise = new Promise((resolve, reject) => {
|
|
10
|
+
resolveFunc = resolve;
|
|
11
|
+
rejectFunc = reject;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (!callback) {
|
|
15
|
+
callback = (err, result) => {
|
|
16
|
+
if (err) return rejectFunc(err);
|
|
17
|
+
resolveFunc(result);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
if (utils.getType(block) === "Function") {
|
|
23
|
+
callback = block;
|
|
24
|
+
block = true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (utils.getType(block) !== "Boolean") {
|
|
28
|
+
throw new Error("block parameter must be a boolean");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const form = {
|
|
32
|
+
fbid: userID,
|
|
33
|
+
block: block
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const res = await defaultFuncs.post(
|
|
37
|
+
"https://www.facebook.com/ajax/profile/manage_blocking.php",
|
|
38
|
+
ctx.jar,
|
|
39
|
+
form
|
|
40
|
+
).then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
41
|
+
|
|
42
|
+
if (res && res.error) {
|
|
43
|
+
throw res;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return callback(null, { success: true, blocked: block });
|
|
47
|
+
} catch (err) {
|
|
48
|
+
utils.error("changeBlockedStatus", err);
|
|
49
|
+
callback(err);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return returnPromise;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (defaultFuncs, api, ctx) => {
|
|
6
|
+
async function handleUpload(image) {
|
|
7
|
+
const form = {
|
|
8
|
+
images_only: "true",
|
|
9
|
+
"attachment[]": image
|
|
10
|
+
};
|
|
11
|
+
return defaultFuncs
|
|
12
|
+
.postFormData("https://upload.facebook.com/ajax/mercury/upload.php", ctx.jar, form, {})
|
|
13
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
14
|
+
.then(resData => {
|
|
15
|
+
if (resData.error) throw resData;
|
|
16
|
+
return resData.payload.metadata[0];
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return async function changeGroupImage(image, threadID, callback) {
|
|
21
|
+
let resolveFunc = () => {};
|
|
22
|
+
let rejectFunc = () => {};
|
|
23
|
+
const returnPromise = new Promise((resolve, reject) => {
|
|
24
|
+
resolveFunc = resolve;
|
|
25
|
+
rejectFunc = reject;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (!callback) {
|
|
29
|
+
callback = (err, result) => {
|
|
30
|
+
if (err) return rejectFunc(err);
|
|
31
|
+
resolveFunc(result);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
if (!ctx.mqttClient) {
|
|
37
|
+
throw new Error("Not connected to MQTT. Please use listenMqtt first.");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!threadID || typeof threadID !== "string") {
|
|
41
|
+
throw new Error("Invalid threadID");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!utils.isReadableStream(image)) {
|
|
45
|
+
throw new Error("image must be a readable stream");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const reqID = ++ctx.wsReqNumber;
|
|
49
|
+
const taskID = ++ctx.wsTaskNumber;
|
|
50
|
+
|
|
51
|
+
let responseHandled = false;
|
|
52
|
+
const onResponse = (topic, message) => {
|
|
53
|
+
if (topic !== "/ls_resp" || responseHandled) return;
|
|
54
|
+
let jsonMsg;
|
|
55
|
+
try {
|
|
56
|
+
jsonMsg = JSON.parse(message.toString());
|
|
57
|
+
jsonMsg.payload = JSON.parse(jsonMsg.payload);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (jsonMsg.request_id !== reqID) return;
|
|
62
|
+
responseHandled = true;
|
|
63
|
+
clearTimeout(timeout);
|
|
64
|
+
ctx.mqttClient.removeListener("message", onResponse);
|
|
65
|
+
callback(null, { success: true, response: jsonMsg.payload });
|
|
66
|
+
resolveFunc({ success: true, response: jsonMsg.payload });
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const timeout = setTimeout(() => {
|
|
70
|
+
if (!responseHandled) {
|
|
71
|
+
responseHandled = true;
|
|
72
|
+
ctx.mqttClient.removeListener("message", onResponse);
|
|
73
|
+
const err = new Error("MQTT request timeout");
|
|
74
|
+
callback(err);
|
|
75
|
+
rejectFunc(err);
|
|
76
|
+
}
|
|
77
|
+
}, 30000);
|
|
78
|
+
|
|
79
|
+
ctx.mqttClient.on("message", onResponse);
|
|
80
|
+
|
|
81
|
+
const payload = await handleUpload(image);
|
|
82
|
+
const imageID = payload.image_id;
|
|
83
|
+
|
|
84
|
+
const taskPayload = {
|
|
85
|
+
thread_key: threadID,
|
|
86
|
+
image_id: imageID,
|
|
87
|
+
sync_group: 1
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const mqttPayload = {
|
|
91
|
+
epoch_id: utils.generateOfflineThreadingID(),
|
|
92
|
+
tasks: [
|
|
93
|
+
{
|
|
94
|
+
failure_count: null,
|
|
95
|
+
label: "37",
|
|
96
|
+
payload: JSON.stringify(taskPayload),
|
|
97
|
+
queue_name: "thread_image",
|
|
98
|
+
task_id: taskID
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
version_id: "8798795233522156"
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const request = {
|
|
105
|
+
app_id: "2220391788200892",
|
|
106
|
+
payload: JSON.stringify(mqttPayload),
|
|
107
|
+
request_id: reqID,
|
|
108
|
+
type: 3
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
ctx.mqttClient.publish("/ls_req", JSON.stringify(request), {
|
|
112
|
+
qos: 1,
|
|
113
|
+
retain: false
|
|
114
|
+
}, (err) => {
|
|
115
|
+
if (err && !responseHandled) {
|
|
116
|
+
responseHandled = true;
|
|
117
|
+
clearTimeout(timeout);
|
|
118
|
+
ctx.mqttClient.removeListener("message", onResponse);
|
|
119
|
+
callback(err);
|
|
120
|
+
rejectFunc(err);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
} catch (err) {
|
|
124
|
+
if (!responseHandled) {
|
|
125
|
+
responseHandled = true;
|
|
126
|
+
clearTimeout(timeout);
|
|
127
|
+
ctx.mqttClient.removeListener("message", onResponse);
|
|
128
|
+
utils.error("changeGroupImage", err);
|
|
129
|
+
callback(err);
|
|
130
|
+
rejectFunc(err);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return returnPromise;
|
|
135
|
+
};
|
|
136
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (defaultFuncs, api, ctx) => {
|
|
6
|
+
return async function changeThreadColor(color, threadID, callback) {
|
|
7
|
+
let reqID = ++ctx.wsReqNumber;
|
|
8
|
+
let resolveFunc = () => {};
|
|
9
|
+
let rejectFunc = () => {};
|
|
10
|
+
const returnPromise = new Promise((resolve, reject) => {
|
|
11
|
+
resolveFunc = resolve;
|
|
12
|
+
rejectFunc = reject;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
if (!callback) {
|
|
16
|
+
callback = (err, data) => {
|
|
17
|
+
if (err) return rejectFunc(err);
|
|
18
|
+
resolveFunc(data);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
if (!ctx.mqttClient) {
|
|
24
|
+
throw new Error("Not connected to MQTT. Please use listenMqtt first.");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const content = {
|
|
28
|
+
app_id: "2220391788200892",
|
|
29
|
+
payload: JSON.stringify({
|
|
30
|
+
data_trace_id: null,
|
|
31
|
+
epoch_id: parseInt(utils.generateOfflineThreadingID()),
|
|
32
|
+
tasks: [
|
|
33
|
+
{
|
|
34
|
+
failure_count: null,
|
|
35
|
+
label: "43",
|
|
36
|
+
payload: JSON.stringify({
|
|
37
|
+
thread_key: threadID,
|
|
38
|
+
theme_fbid: color,
|
|
39
|
+
source: null,
|
|
40
|
+
sync_group: 1,
|
|
41
|
+
payload: null
|
|
42
|
+
}),
|
|
43
|
+
queue_name: "thread_theme",
|
|
44
|
+
task_id: ++ctx.wsTaskNumber
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
version_id: "8798795233522156"
|
|
48
|
+
}),
|
|
49
|
+
request_id: reqID,
|
|
50
|
+
type: 3
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
let responseHandled = false;
|
|
54
|
+
|
|
55
|
+
const handleRes = (topic, message) => {
|
|
56
|
+
if (responseHandled) return;
|
|
57
|
+
if (topic !== "/ls_resp") return;
|
|
58
|
+
let jsonMsg;
|
|
59
|
+
try {
|
|
60
|
+
jsonMsg = JSON.parse(message.toString());
|
|
61
|
+
jsonMsg.payload = JSON.parse(jsonMsg.payload);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (jsonMsg.request_id !== reqID) return;
|
|
66
|
+
responseHandled = true;
|
|
67
|
+
clearTimeout(timeout);
|
|
68
|
+
ctx.mqttClient.removeListener("message", handleRes);
|
|
69
|
+
try {
|
|
70
|
+
const msgID = jsonMsg.payload.step[1][2][2][1][2];
|
|
71
|
+
const msgReplace = jsonMsg.payload.step[1][2][2][1][4];
|
|
72
|
+
const bodies = {
|
|
73
|
+
body: msgReplace,
|
|
74
|
+
messageID: msgID
|
|
75
|
+
};
|
|
76
|
+
callback(null, bodies);
|
|
77
|
+
resolveFunc(bodies);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
callback(null, { success: true });
|
|
80
|
+
resolveFunc({ success: true });
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const timeout = setTimeout(() => {
|
|
85
|
+
if (!responseHandled) {
|
|
86
|
+
responseHandled = true;
|
|
87
|
+
ctx.mqttClient.removeListener("message", handleRes);
|
|
88
|
+
const err = new Error("MQTT request timeout");
|
|
89
|
+
callback(err);
|
|
90
|
+
rejectFunc(err);
|
|
91
|
+
}
|
|
92
|
+
}, 30000);
|
|
93
|
+
|
|
94
|
+
ctx.mqttClient.on("message", handleRes);
|
|
95
|
+
|
|
96
|
+
ctx.mqttClient.publish("/ls_req", JSON.stringify(content), {
|
|
97
|
+
qos: 1,
|
|
98
|
+
retain: false
|
|
99
|
+
}, (err) => {
|
|
100
|
+
if (err && !responseHandled) {
|
|
101
|
+
responseHandled = true;
|
|
102
|
+
clearTimeout(timeout);
|
|
103
|
+
ctx.mqttClient.removeListener("message", handleRes);
|
|
104
|
+
callback(err);
|
|
105
|
+
rejectFunc(err);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} catch (err) {
|
|
109
|
+
utils.error("changeThreadColor", err);
|
|
110
|
+
callback(err);
|
|
111
|
+
rejectFunc(err);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return returnPromise;
|
|
115
|
+
};
|
|
116
|
+
};
|