@cexy/hoonfca 1.0.0 → 1.0.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.
Files changed (188) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +451 -43
  3. package/examples/login-with-cookies.js +102 -0
  4. package/examples/verify.js +70 -0
  5. package/index.js +1 -466
  6. package/package.json +98 -6
  7. package/src/apis/addExternalModule.js +24 -0
  8. package/src/apis/addUserToGroup.js +108 -0
  9. package/src/apis/changeAdminStatus.js +148 -0
  10. package/src/apis/changeArchivedStatus.js +61 -0
  11. package/src/apis/changeAvatar.js +103 -0
  12. package/src/apis/changeBio.js +69 -0
  13. package/src/apis/changeBlockedStatus.js +54 -0
  14. package/src/apis/changeGroupImage.js +136 -0
  15. package/src/apis/changeThreadColor.js +116 -0
  16. package/src/{changeThreadEmoji.js → apis/changeThreadEmoji.js} +7 -8
  17. package/src/apis/comment.js +207 -0
  18. package/src/apis/createAITheme.js +129 -0
  19. package/src/apis/createNewGroup.js +79 -0
  20. package/src/apis/createPoll.js +73 -0
  21. package/src/apis/deleteMessage.js +44 -0
  22. package/src/apis/deleteThread.js +52 -0
  23. package/src/apis/e2ee.js +17 -0
  24. package/src/apis/editMessage.js +70 -0
  25. package/src/apis/emoji.js +124 -0
  26. package/src/apis/fetchThemeData.js +82 -0
  27. package/src/apis/follow.js +81 -0
  28. package/src/apis/forwardMessage.js +52 -0
  29. package/src/apis/friend.js +243 -0
  30. package/src/apis/gcmember.js +122 -0
  31. package/src/apis/gcname.js +123 -0
  32. package/src/apis/gcrule.js +119 -0
  33. package/src/apis/getAccess.js +111 -0
  34. package/src/apis/getBotInfo.js +88 -0
  35. package/src/apis/getBotInitialData.js +43 -0
  36. package/src/apis/getFriendsList.js +79 -0
  37. package/src/apis/getMessage.js +423 -0
  38. package/src/apis/getTheme.js +95 -0
  39. package/src/apis/getThemeInfo.js +116 -0
  40. package/src/apis/getThreadHistory.js +239 -0
  41. package/src/apis/getThreadInfo.js +267 -0
  42. package/src/apis/getThreadList.js +232 -0
  43. package/src/apis/getThreadPictures.js +58 -0
  44. package/src/apis/getUserID.js +117 -0
  45. package/src/apis/getUserInfo.js +513 -0
  46. package/src/apis/getUserInfoV2.js +146 -0
  47. package/src/apis/handleMessageRequest.js +50 -0
  48. package/src/apis/httpGet.js +63 -0
  49. package/src/apis/httpPost.js +89 -0
  50. package/src/apis/httpPostFormData.js +69 -0
  51. package/src/apis/listenMqtt.js +1236 -0
  52. package/src/apis/listenSpeed.js +179 -0
  53. package/src/apis/logout.js +87 -0
  54. package/src/apis/markAsDelivered.js +47 -0
  55. package/src/apis/markAsRead.js +99 -0
  56. package/src/apis/markAsReadAll.js +40 -0
  57. package/src/apis/markAsSeen.js +70 -0
  58. package/src/apis/mqttDeltaValue.js +278 -0
  59. package/src/apis/muteThread.js +45 -0
  60. package/src/apis/nickname.js +132 -0
  61. package/src/apis/notes.js +163 -0
  62. package/src/apis/pinMessage.js +150 -0
  63. package/src/apis/produceMetaTheme.js +180 -0
  64. package/src/apis/realtime.js +182 -0
  65. package/src/apis/removeUserFromGroup.js +117 -0
  66. package/src/apis/resolvePhotoUrl.js +58 -0
  67. package/src/apis/searchForThread.js +154 -0
  68. package/src/apis/sendMessage.js +354 -0
  69. package/src/apis/sendMessageMqtt.js +249 -0
  70. package/src/apis/sendTypingIndicator.js +91 -0
  71. package/src/apis/setMessageReaction.js +27 -0
  72. package/src/apis/setMessageReactionMqtt.js +61 -0
  73. package/src/apis/setThreadTheme.js +260 -0
  74. package/src/apis/setThreadThemeMqtt.js +94 -0
  75. package/src/apis/share.js +107 -0
  76. package/src/apis/shareContact.js +66 -0
  77. package/src/apis/stickers.js +257 -0
  78. package/src/apis/story.js +181 -0
  79. package/src/apis/theme.js +233 -0
  80. package/src/apis/unfriend.js +47 -0
  81. package/src/apis/unsendMessage.js +17 -0
  82. package/src/engine/client.js +92 -0
  83. package/src/engine/models/buildAPI.js +152 -0
  84. package/src/engine/models/loginHelper.js +519 -0
  85. package/src/engine/models/setOptions.js +88 -0
  86. package/src/security/e2ee.js +109 -0
  87. package/src/types/index.d.ts +498 -0
  88. package/src/utils/antiSuspension.js +506 -0
  89. package/src/utils/auth-helpers.js +149 -0
  90. package/src/utils/autoReLogin.js +336 -0
  91. package/src/utils/axios.js +436 -0
  92. package/src/utils/cache.js +54 -0
  93. package/src/utils/clients.js +282 -0
  94. package/src/utils/constants.js +410 -0
  95. package/src/utils/formatters/data/formatAttachment.js +370 -0
  96. package/src/utils/formatters/data/formatDelta.js +109 -0
  97. package/src/utils/formatters/index.js +159 -0
  98. package/src/utils/formatters/value/formatCookie.js +91 -0
  99. package/src/utils/formatters/value/formatDate.js +36 -0
  100. package/src/utils/formatters/value/formatID.js +16 -0
  101. package/src/utils/formatters.js +1373 -0
  102. package/src/utils/headers.js +230 -0
  103. package/src/utils/index.js +153 -0
  104. package/src/utils/monitoring.js +333 -0
  105. package/src/utils/rateLimiter.js +319 -0
  106. package/src/utils/tokenRefresh.js +657 -0
  107. package/src/utils/user-agents.js +238 -0
  108. package/src/utils/validation.js +157 -0
  109. package/replit.nix +0 -3
  110. package/src/addExternalModule.js +0 -25
  111. package/src/addUserToGroup.js +0 -98
  112. package/src/changeAdminStatus.js +0 -98
  113. package/src/changeArchivedStatus.js +0 -51
  114. package/src/changeAvatar.js +0 -89
  115. package/src/changeBio.js +0 -74
  116. package/src/changeBlockedStatus.js +0 -45
  117. package/src/changeBlockedStatusMqtt.js +0 -65
  118. package/src/changeCover.js +0 -92
  119. package/src/changeGroupImage.js +0 -110
  120. package/src/changeName.js +0 -106
  121. package/src/changeNickname.js +0 -58
  122. package/src/changeThreadColor.js +0 -62
  123. package/src/changeUsername.js +0 -80
  124. package/src/createCommentPost.js +0 -196
  125. package/src/createNewGroup.js +0 -81
  126. package/src/createPoll.js +0 -64
  127. package/src/createPost.js +0 -285
  128. package/src/data/getThreadInfo.json +0 -1
  129. package/src/deleteMessage.js +0 -55
  130. package/src/deleteThread.js +0 -55
  131. package/src/editMessage.js +0 -66
  132. package/src/follow.js +0 -71
  133. package/src/forwardAttachment.js +0 -57
  134. package/src/getAccess.js +0 -130
  135. package/src/getAvatarUser.js +0 -88
  136. package/src/getBotInitialData.js +0 -59
  137. package/src/getCtx.js +0 -5
  138. package/src/getCurrentUserID.js +0 -5
  139. package/src/getEmojiUrl.js +0 -18
  140. package/src/getFriendsList.js +0 -81
  141. package/src/getMessage.js +0 -827
  142. package/src/getOptions.js +0 -5
  143. package/src/getRegion.js +0 -7
  144. package/src/getThreadHistory.js +0 -496
  145. package/src/getThreadHistoryDeprecated.js +0 -95
  146. package/src/getThreadInfo.js +0 -194
  147. package/src/getThreadInfoDeprecated.js +0 -77
  148. package/src/getThreadList.js +0 -219
  149. package/src/getThreadListDeprecated.js +0 -86
  150. package/src/getThreadPictures.js +0 -85
  151. package/src/getUserID.js +0 -67
  152. package/src/getUserInfo.js +0 -89
  153. package/src/handleFriendRequest.js +0 -56
  154. package/src/handleMessageRequest.js +0 -65
  155. package/src/httpGet.js +0 -53
  156. package/src/httpPost.js +0 -53
  157. package/src/httpPostFormData.js +0 -58
  158. package/src/listenMqtt.js +0 -683
  159. package/src/listenNotification.js +0 -96
  160. package/src/logout.js +0 -77
  161. package/src/markAsDelivered.js +0 -53
  162. package/src/markAsRead.js +0 -74
  163. package/src/markAsReadAll.js +0 -46
  164. package/src/markAsSeen.js +0 -57
  165. package/src/muteThread.js +0 -49
  166. package/src/pinMessage.js +0 -60
  167. package/src/refreshFb_dtsg.js +0 -75
  168. package/src/removeUserFromGroup.js +0 -59
  169. package/src/resolvePhotoUrl.js +0 -47
  170. package/src/searchForThread.js +0 -55
  171. package/src/searchStickers.js +0 -59
  172. package/src/sendMessage.js +0 -444
  173. package/src/sendMessageMqtt.js +0 -326
  174. package/src/sendTypingIndicator.js +0 -54
  175. package/src/setMessageReaction.js +0 -126
  176. package/src/setMessageReactionMqtt.js +0 -74
  177. package/src/setPostReaction.js +0 -103
  178. package/src/setProfileGuard.js +0 -66
  179. package/src/setStoryReaction.js +0 -97
  180. package/src/setTitle.js +0 -100
  181. package/src/shareContact.js +0 -101
  182. package/src/shareLink.js +0 -105
  183. package/src/stopListenMqtt.js +0 -47
  184. package/src/threadColors.js +0 -119
  185. package/src/unfriend.js +0 -58
  186. package/src/unsendMessage.js +0 -51
  187. package/src/uploadAttachment.js +0 -98
  188. package/utils.js +0 -919
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+
3
+ const utils = require('../utils');
4
+
5
+ module.exports = (defaultFuncs, api, ctx) => {
6
+ return async function addUserToGroup(userID, threadID, 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 (!ctx.mqttClient) {
23
+ throw new Error("Not connected to MQTT. Please use listenMqtt first.");
24
+ }
25
+
26
+ if (utils.getType(threadID) !== "Number" && utils.getType(threadID) !== "String") {
27
+ throw new Error("ThreadID should be of type Number or String");
28
+ }
29
+
30
+ if (utils.getType(userID) !== "Array") {
31
+ userID = [userID];
32
+ }
33
+
34
+ const reqID = ++ctx.wsReqNumber;
35
+ const taskID = ++ctx.wsTaskNumber;
36
+
37
+ const payload = {
38
+ epoch_id: utils.generateOfflineThreadingID(),
39
+ tasks: [
40
+ {
41
+ failure_count: null,
42
+ label: "23",
43
+ payload: JSON.stringify({
44
+ thread_key: threadID,
45
+ contact_ids: userID,
46
+ sync_group: 1
47
+ }),
48
+ queue_name: threadID.toString(),
49
+ task_id: taskID
50
+ }
51
+ ],
52
+ version_id: "24502707779384158"
53
+ };
54
+
55
+ const form = JSON.stringify({
56
+ app_id: "772021112871879",
57
+ payload: JSON.stringify(payload),
58
+ request_id: reqID,
59
+ type: 3
60
+ });
61
+
62
+ let responseHandled = false;
63
+ const handleRes = (topic, message) => {
64
+ if (topic !== "/ls_resp" || responseHandled) return;
65
+ let jsonMsg;
66
+ try {
67
+ jsonMsg = JSON.parse(message.toString());
68
+ jsonMsg.payload = JSON.parse(jsonMsg.payload);
69
+ } catch {
70
+ return;
71
+ }
72
+ if (jsonMsg.request_id !== reqID) return;
73
+ responseHandled = true;
74
+ clearTimeout(timeout);
75
+ ctx.mqttClient.removeListener("message", handleRes);
76
+ callback(null, { success: true, response: jsonMsg.payload });
77
+ resolveFunc({ success: true, response: jsonMsg.payload });
78
+ };
79
+
80
+ const timeout = setTimeout(() => {
81
+ if (!responseHandled) {
82
+ responseHandled = true;
83
+ ctx.mqttClient.removeListener("message", handleRes);
84
+ const err = new Error("MQTT request timeout");
85
+ callback(err);
86
+ rejectFunc(err);
87
+ }
88
+ }, 30000);
89
+
90
+ ctx.mqttClient.on("message", handleRes);
91
+ ctx.mqttClient.publish("/ls_req", form, { qos: 1, retain: false }, (err) => {
92
+ if (err && !responseHandled) {
93
+ responseHandled = true;
94
+ clearTimeout(timeout);
95
+ ctx.mqttClient.removeListener("message", handleRes);
96
+ callback(err);
97
+ rejectFunc(err);
98
+ }
99
+ });
100
+ } catch (err) {
101
+ utils.error("addUserToGroup", err);
102
+ callback(err);
103
+ rejectFunc(err);
104
+ }
105
+
106
+ return returnPromise;
107
+ };
108
+ };
@@ -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
+ };