nexus-fca 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.
Files changed (180) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/DOCS.md +2047 -0
  3. package/Fca_Database/database.sqlite +0 -0
  4. package/LICENSE-MIT +21 -0
  5. package/README.md +240 -0
  6. package/docs/README.md +9 -0
  7. package/docs/addExternalModule.md +15 -0
  8. package/docs/addUserToGroup.md +20 -0
  9. package/docs/changeAdminStatus.md +21 -0
  10. package/docs/changeArchivedStatus.md +19 -0
  11. package/docs/changeAvatar.md +21 -0
  12. package/docs/changeAvatarV2.md +18 -0
  13. package/docs/changeBio.md +15 -0
  14. package/docs/changeBlockedStatus.md +16 -0
  15. package/docs/changeBlockedStatusMqtt.md +16 -0
  16. package/docs/changeCover.md +15 -0
  17. package/docs/changeGroupImage.md +16 -0
  18. package/docs/changeName.md +18 -0
  19. package/docs/changeNickname.md +17 -0
  20. package/docs/changeThreadColor.md +16 -0
  21. package/docs/changeThreadEmoji.md +16 -0
  22. package/docs/changeUsername.md +15 -0
  23. package/docs/createCommentPost.md +16 -0
  24. package/docs/createNewGroup.md +16 -0
  25. package/docs/createPoll.md +17 -0
  26. package/docs/createPost.md +15 -0
  27. package/docs/deleteMessage.md +15 -0
  28. package/docs/deleteThread.md +15 -0
  29. package/docs/editMessage.md +16 -0
  30. package/docs/follow.md +15 -0
  31. package/docs/forwardAttachment.md +16 -0
  32. package/docs/getAccess.md +17 -0
  33. package/docs/getAvatarUser.md +15 -0
  34. package/docs/getBotInitialData.md +14 -0
  35. package/docs/getCtx.md +14 -0
  36. package/docs/getCurrentUserID.md +12 -0
  37. package/docs/getEmojiUrl.md +17 -0
  38. package/docs/getFriendsList.md +14 -0
  39. package/docs/getMessage.md +15 -0
  40. package/docs/getOptions.md +14 -0
  41. package/docs/getRegion.md +14 -0
  42. package/docs/getThreadHistory.md +17 -0
  43. package/docs/getThreadHistoryDeprecated.md +17 -0
  44. package/docs/getThreadInfo.md +15 -0
  45. package/docs/getThreadInfoDeprecated.md +17 -0
  46. package/docs/getThreadList.md +17 -0
  47. package/docs/getThreadListDeprecated.md +17 -0
  48. package/docs/getThreadPictures.md +17 -0
  49. package/docs/getUID.md +15 -0
  50. package/docs/getUserID.md +15 -0
  51. package/docs/getUserInfo.md +15 -0
  52. package/docs/handleFriendRequest.md +16 -0
  53. package/docs/handleMessageRequest.md +16 -0
  54. package/docs/httpGet.md +15 -0
  55. package/docs/httpPost.md +16 -0
  56. package/docs/httpPostFormData.md +16 -0
  57. package/docs/listenMqtt.md +17 -0
  58. package/docs/listenNotification.md +14 -0
  59. package/docs/logout.md +14 -0
  60. package/docs/markAsDelivered.md +16 -0
  61. package/docs/markAsRead.md +16 -0
  62. package/docs/markAsReadAll.md +14 -0
  63. package/docs/markAsSeen.md +15 -0
  64. package/docs/muteThread.md +16 -0
  65. package/docs/pinMessage.md +17 -0
  66. package/docs/postFormData.md +16 -0
  67. package/docs/refreshFb_dtsg.md +14 -0
  68. package/docs/removeUserFromGroup.md +16 -0
  69. package/docs/resolvePhotoUrl.md +15 -0
  70. package/docs/searchForThread.md +15 -0
  71. package/docs/searchStickers.md +15 -0
  72. package/docs/sendComment.md +16 -0
  73. package/docs/sendMessage.md +16 -0
  74. package/docs/sendMessageMqtt.md +16 -0
  75. package/docs/sendTypingIndicator.md +15 -0
  76. package/docs/setMessageReaction.md +17 -0
  77. package/docs/setMessageReactionMqtt.md +16 -0
  78. package/docs/setPostReaction.md +16 -0
  79. package/docs/setProfileGuard.md +15 -0
  80. package/docs/setStoryReaction.md +16 -0
  81. package/docs/setTitle.md +16 -0
  82. package/docs/shareContact.md +16 -0
  83. package/docs/shareLink.md +16 -0
  84. package/docs/stopListenMqtt.md +8 -0
  85. package/docs/threadColors.md +11 -0
  86. package/docs/unfriend.md +15 -0
  87. package/docs/unsendMessage.md +15 -0
  88. package/docs/uploadAttachment.md +15 -0
  89. package/fca-config.json +7 -0
  90. package/index.d.ts +618 -0
  91. package/index.js +361 -0
  92. package/lib/database/models/index.js +47 -0
  93. package/lib/database/models/thread.js +31 -0
  94. package/lib/database/threadData.js +93 -0
  95. package/lib/logger.js +24 -0
  96. package/lib/login.js +0 -0
  97. package/package.json +90 -0
  98. package/src/addExternalModule.js +19 -0
  99. package/src/addUserToGroup.js +113 -0
  100. package/src/changeAdminStatus.js +79 -0
  101. package/src/changeArchivedStatus.js +55 -0
  102. package/src/changeAvatar.js +126 -0
  103. package/src/changeAvatarV2.js +77 -0
  104. package/src/changeBio.js +77 -0
  105. package/src/changeBlockedStatus.js +47 -0
  106. package/src/changeBlockedStatusMqtt.js +71 -0
  107. package/src/changeCover.js +72 -0
  108. package/src/changeGroupImage.js +132 -0
  109. package/src/changeName.js +79 -0
  110. package/src/changeNickname.js +59 -0
  111. package/src/changeThreadColor.js +65 -0
  112. package/src/changeThreadEmoji.js +55 -0
  113. package/src/changeUsername.js +58 -0
  114. package/src/createCommentPost.js +225 -0
  115. package/src/createNewGroup.js +86 -0
  116. package/src/createPoll.js +71 -0
  117. package/src/createPost.js +276 -0
  118. package/src/deleteMessage.js +56 -0
  119. package/src/deleteThread.js +56 -0
  120. package/src/editMessage.js +57 -0
  121. package/src/follow.js +54 -0
  122. package/src/forwardAttachment.js +60 -0
  123. package/src/getAccess.js +67 -0
  124. package/src/getAvatarUser.js +56 -0
  125. package/src/getBotInitialData.js +37 -0
  126. package/src/getCtx.js +6 -0
  127. package/src/getCurrentUserID.js +7 -0
  128. package/src/getEmojiUrl.js +29 -0
  129. package/src/getFriendsList.js +83 -0
  130. package/src/getMessage.js +796 -0
  131. package/src/getOptions.js +6 -0
  132. package/src/getRegion.js +8 -0
  133. package/src/getThreadHistory.js +666 -0
  134. package/src/getThreadHistoryDeprecated.js +55 -0
  135. package/src/getThreadInfo.js +535 -0
  136. package/src/getThreadInfoDeprecated.js +49 -0
  137. package/src/getThreadList.js +192 -0
  138. package/src/getThreadListDeprecated.js +54 -0
  139. package/src/getThreadPictures.js +79 -0
  140. package/src/getUID.js +67 -0
  141. package/src/getUserID.js +66 -0
  142. package/src/getUserInfo.js +80 -0
  143. package/src/handleFriendRequest.js +61 -0
  144. package/src/handleMessageRequest.js +65 -0
  145. package/src/httpGet.js +57 -0
  146. package/src/httpPost.js +57 -0
  147. package/src/httpPostFormData.js +63 -0
  148. package/src/listenMqtt.js +1039 -0
  149. package/src/listenNotification.js +65 -0
  150. package/src/logout.js +75 -0
  151. package/src/markAsDelivered.js +58 -0
  152. package/src/markAsRead.js +80 -0
  153. package/src/markAsReadAll.js +50 -0
  154. package/src/markAsSeen.js +59 -0
  155. package/src/muteThread.js +52 -0
  156. package/src/pinMessage.js +59 -0
  157. package/src/postFormData.js +46 -0
  158. package/src/refreshFb_dtsg.js +66 -0
  159. package/src/removeUserFromGroup.js +79 -0
  160. package/src/resolvePhotoUrl.js +45 -0
  161. package/src/searchForThread.js +53 -0
  162. package/src/searchStickers.js +51 -0
  163. package/src/sendComment.js +63 -0
  164. package/src/sendMessage.js +328 -0
  165. package/src/sendMessageMqtt.js +316 -0
  166. package/src/sendTypingIndicator.js +103 -0
  167. package/src/setMessageReaction.js +119 -0
  168. package/src/setMessageReactionMqtt.js +61 -0
  169. package/src/setPostReaction.js +109 -0
  170. package/src/setProfileGuard.js +45 -0
  171. package/src/setStoryReaction.js +62 -0
  172. package/src/setTitle.js +86 -0
  173. package/src/shareContact.js +49 -0
  174. package/src/shareLink.js +59 -0
  175. package/src/stopListenMqtt.js +21 -0
  176. package/src/threadColors.js +131 -0
  177. package/src/unfriend.js +52 -0
  178. package/src/unsendMessage.js +49 -0
  179. package/src/uploadAttachment.js +95 -0
  180. package/utils.js +1432 -0
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function addUserToGroup(userID, threadID, callback) {
8
+ let resolveFunc = function () { };
9
+ let rejectFunc = function () { };
10
+ const returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (
16
+ !callback &&
17
+ (utils.getType(threadID) === "Function" ||
18
+ utils.getType(threadID) === "AsyncFunction")
19
+ ) {
20
+ throw new utils.CustomError({ error: "please pass a threadID as a second argument." });
21
+ }
22
+
23
+ if (!callback) {
24
+ callback = function (err) {
25
+ if (err) {
26
+ return rejectFunc(err);
27
+ }
28
+ resolveFunc();
29
+ };
30
+ }
31
+
32
+ if (
33
+ utils.getType(threadID) !== "Number" &&
34
+ utils.getType(threadID) !== "String"
35
+ ) {
36
+ throw new utils.CustomError({
37
+ error:
38
+ "ThreadID should be of type Number or String and not " +
39
+ utils.getType(threadID) +
40
+ "."
41
+ });
42
+ }
43
+
44
+ if (utils.getType(userID) !== "Array") {
45
+ userID = [userID];
46
+ }
47
+
48
+ const messageAndOTID = utils.generateOfflineThreadingID();
49
+ const form = {
50
+ client: "mercury",
51
+ action_type: "ma-type:log-message",
52
+ author: "fbid:" + (ctx.i_userID || ctx.userID),
53
+ thread_id: "",
54
+ timestamp: Date.now(),
55
+ timestamp_absolute: "Today",
56
+ timestamp_relative: utils.generateTimestampRelative(),
57
+ timestamp_time_passed: "0",
58
+ is_unread: false,
59
+ is_cleared: false,
60
+ is_forward: false,
61
+ is_filtered_content: false,
62
+ is_filtered_content_bh: false,
63
+ is_filtered_content_account: false,
64
+ is_spoof_warning: false,
65
+ source: "source:chat:web",
66
+ "source_tags[0]": "source:chat",
67
+ log_message_type: "log:subscribe",
68
+ status: "0",
69
+ offline_threading_id: messageAndOTID,
70
+ message_id: messageAndOTID,
71
+ threading_id: utils.generateThreadingID(ctx.clientID),
72
+ manual_retry_cnt: "0",
73
+ thread_fbid: threadID
74
+ };
75
+
76
+ for (let i = 0; i < userID.length; i++) {
77
+ if (
78
+ utils.getType(userID[i]) !== "Number" &&
79
+ utils.getType(userID[i]) !== "String"
80
+ ) {
81
+ throw new utils.CustomError({
82
+ error:
83
+ "Elements of userID should be of type Number or String and not " +
84
+ utils.getType(userID[i]) +
85
+ "."
86
+ });
87
+ }
88
+
89
+ form["log_message_data[added_participants][" + i + "]"] =
90
+ "fbid:" + userID[i];
91
+ }
92
+
93
+ defaultFuncs
94
+ .post("https://www.facebook.com/messaging/send/", ctx.jar, form)
95
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
96
+ .then(function (resData) {
97
+ if (!resData) {
98
+ throw new utils.CustomError({ error: "Add to group failed." });
99
+ }
100
+ if (resData.error) {
101
+ throw new utils.CustomError(resData);
102
+ }
103
+
104
+ return callback();
105
+ })
106
+ .catch(function (err) {
107
+ log.error("addUserToGroup", err);
108
+ return callback(err);
109
+ });
110
+
111
+ return returnPromise;
112
+ };
113
+ };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function changeAdminStatus(threadID, adminIDs, adminStatus, callback) {
8
+ if (utils.getType(threadID) !== "String") {
9
+ throw new utils.CustomError({ error: "changeAdminStatus: threadID must be a string" });
10
+ }
11
+
12
+ if (utils.getType(adminIDs) === "String") {
13
+ adminIDs = [adminIDs];
14
+ }
15
+
16
+ if (utils.getType(adminIDs) !== "Array") {
17
+ throw new utils.CustomError({ error: "changeAdminStatus: adminIDs must be an array or string" });
18
+ }
19
+
20
+ if (utils.getType(adminStatus) !== "Boolean") {
21
+ throw new utils.CustomError({ error: "changeAdminStatus: adminStatus must be a string" });
22
+ }
23
+
24
+ let resolveFunc = function () { };
25
+ let rejectFunc = function () { };
26
+ const returnPromise = new Promise(function (resolve, reject) {
27
+ resolveFunc = resolve;
28
+ rejectFunc = reject;
29
+ });
30
+
31
+ if (!callback) {
32
+ callback = function (err) {
33
+ if (err) {
34
+ return rejectFunc(err);
35
+ }
36
+ resolveFunc();
37
+ };
38
+ }
39
+
40
+ if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
41
+ throw new utils.CustomError({ error: "changeAdminStatus: callback is not a function" });
42
+ }
43
+
44
+ const form = {
45
+ "thread_fbid": threadID
46
+ };
47
+
48
+ let i = 0;
49
+ for (const u of adminIDs) {
50
+ form[`admin_ids[${i++}]`] = u;
51
+ }
52
+ form["add"] = adminStatus;
53
+
54
+ defaultFuncs
55
+ .post("https://www.facebook.com/messaging/save_admins/?dpr=1", ctx.jar, form)
56
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
57
+ .then(function (resData) {
58
+ if (resData.error) {
59
+ switch (resData.error) {
60
+ case 1976004:
61
+ throw new utils.CustomError({ error: "Cannot alter admin status: you are not an admin.", rawResponse: resData });
62
+ case 1357031:
63
+ throw new utils.CustomError({ error: "Cannot alter admin status: this thread is not a group chat.", rawResponse: resData });
64
+ default:
65
+ throw new utils.CustomError({ error: "Cannot alter admin status: unknown error.", rawResponse: resData });
66
+ }
67
+ }
68
+
69
+ callback();
70
+ })
71
+ .catch(function (err) {
72
+ log.error("changeAdminStatus", err);
73
+ return callback(err);
74
+ });
75
+
76
+ return returnPromise;
77
+ };
78
+ };
79
+
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function changeArchivedStatus(threadOrThreads, archive, callback) {
8
+ let resolveFunc = function () { };
9
+ let rejectFunc = function () { };
10
+ const returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ callback = function (err) {
17
+ if (err) {
18
+ return rejectFunc(err);
19
+ }
20
+ resolveFunc();
21
+ };
22
+ }
23
+
24
+ const form = {};
25
+
26
+ if (utils.getType(threadOrThreads) === "Array") {
27
+ for (let i = 0; i < threadOrThreads.length; i++) {
28
+ form["ids[" + threadOrThreads[i] + "]"] = archive;
29
+ }
30
+ } else {
31
+ form["ids[" + threadOrThreads + "]"] = archive;
32
+ }
33
+
34
+ defaultFuncs
35
+ .post(
36
+ "https://www.facebook.com/ajax/mercury/change_archived_status.php",
37
+ ctx.jar,
38
+ form
39
+ )
40
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
41
+ .then(function (resData) {
42
+ if (resData.error) {
43
+ throw resData;
44
+ }
45
+
46
+ return callback();
47
+ })
48
+ .catch(function (err) {
49
+ log.error("changeArchivedStatus", err);
50
+ return callback(err);
51
+ });
52
+
53
+ return returnPromise;
54
+ };
55
+ };
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ function handleUpload(image, callback) {
8
+ const uploads = [];
9
+
10
+ const form = {
11
+ profile_id: ctx.i_userID || ctx.userID,
12
+ photo_source: 57,
13
+ av: ctx.i_userID || ctx.userID,
14
+ file: image
15
+ };
16
+
17
+ uploads.push(
18
+ defaultFuncs
19
+ .postFormData(
20
+ "https://www.facebook.com/profile/picture/upload/",
21
+ ctx.jar,
22
+ form,
23
+ {}
24
+ )
25
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
26
+ .then(function (resData) {
27
+ if (resData.error) {
28
+ throw resData;
29
+ }
30
+ return resData;
31
+ })
32
+ );
33
+
34
+ // resolve all promises
35
+ Promise
36
+ .all(uploads)
37
+ .then(function (resData) {
38
+ callback(null, resData);
39
+ })
40
+ .catch(function (err) {
41
+ log.error("handleUpload", err);
42
+ return callback(err);
43
+ });
44
+ }
45
+
46
+ return function changeAvatar(image, caption = "", timestamp = null, callback) {
47
+ let resolveFunc = function () { };
48
+ let rejectFunc = function () { };
49
+ const returnPromise = new Promise(function (resolve, reject) {
50
+ resolveFunc = resolve;
51
+ rejectFunc = reject;
52
+ });
53
+
54
+ if (!timestamp && utils.getType(caption) === "Number") {
55
+ timestamp = caption;
56
+ caption = "";
57
+ }
58
+
59
+ if (!timestamp && !callback && (utils.getType(caption) == "Function" || utils.getType(caption) == "AsyncFunction")) {
60
+ callback = caption;
61
+ caption = "";
62
+ timestamp = null;
63
+ }
64
+
65
+ if (!callback) callback = function (err, data) {
66
+ if (err) {
67
+ return rejectFunc(err);
68
+ }
69
+ resolveFunc(data);
70
+ };
71
+
72
+ if (!utils.isReadableStream(image))
73
+ return callback("Image is not a readable stream");
74
+
75
+ handleUpload(image, function (err, payload) {
76
+ if (err) {
77
+ return callback(err);
78
+ }
79
+
80
+ const form = {
81
+ av: ctx.i_userID || ctx.userID,
82
+ fb_api_req_friendly_name: "ProfileCometProfilePictureSetMutation",
83
+ fb_api_caller_class: "RelayModern",
84
+ doc_id: "5066134240065849",
85
+ variables: JSON.stringify({
86
+ input: {
87
+ caption,
88
+ existing_photo_id: payload[0].payload.fbid,
89
+ expiration_time: timestamp,
90
+ profile_id: ctx.i_userID || ctx.userID,
91
+ profile_pic_method: "EXISTING",
92
+ profile_pic_source: "TIMELINE",
93
+ scaled_crop_rect: {
94
+ height: 1,
95
+ width: 1,
96
+ x: 0,
97
+ y: 0
98
+ },
99
+ skip_cropping: true,
100
+ actor_id: ctx.i_userID || ctx.userID,
101
+ client_mutation_id: Math.round(Math.random() * 19).toString()
102
+ },
103
+ isPage: false,
104
+ isProfile: true,
105
+ scale: 3
106
+ })
107
+ };
108
+
109
+ defaultFuncs
110
+ .post("https://www.facebook.com/api/graphql/", ctx.jar, form)
111
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
112
+ .then(function (resData) {
113
+ if (resData.errors) {
114
+ throw resData;
115
+ }
116
+ return callback(null, resData[0].data.profile_picture_set);
117
+ })
118
+ .catch(function (err) {
119
+ log.error("changeAvatar", err);
120
+ return callback(err);
121
+ });
122
+ });
123
+
124
+ return returnPromise;
125
+ };
126
+ };
@@ -0,0 +1,77 @@
1
+ // Nexus-FCA: Advanced and Safe Facebook Chat API
2
+ // changeAvatarV2.js - Change user avatar with advanced options
3
+
4
+ const { rateLimiter, safeMode, isUserAllowed } = require('../utils');
5
+
6
+ /**
7
+ * Change the user's Facebook avatar with advanced safety checks.
8
+ * @param {Object} defaultFuncs - Default functions from Nexus-FCA context
9
+ * @param {Object} api - Nexus-FCA API object
10
+ * @param {Object} ctx - Nexus-FCA context
11
+ * @returns {Function}
12
+ */
13
+ module.exports = function changeAvatarV2(defaultFuncs, api, ctx) {
14
+ /**
15
+ * Change avatar with file stream or URL, with validation and rate limiting.
16
+ * @param {Object} options - { stream, url }
17
+ * @param {Function} callback
18
+ */
19
+ const lastChange = { time: 0 };
20
+ return function(options, callback) {
21
+ // Extract userID from context (for rate limiting and allow/block list)
22
+ const userID = ctx.userID || (ctx.globalOptions && ctx.globalOptions.userID) || 'unknown';
23
+
24
+ // Safe mode disables avatar change
25
+ if (safeMode) {
26
+ return callback(new Error("Avatar change is disabled in Nexus-FCA safe mode."));
27
+ }
28
+ // Allow/block list check
29
+ if (!isUserAllowed(userID)) {
30
+ return callback(new Error("You are not allowed to change the avatar."));
31
+ }
32
+ // Rate limiting (per user)
33
+ if (!rateLimiter.check(userID, 'changeAvatarV2')) {
34
+ return callback(new Error("Rate limit exceeded. Please wait before changing avatar again."));
35
+ }
36
+
37
+ // Safety: Only allow change every 5 minutes
38
+ const now = Date.now();
39
+ if (now - lastChange.time < 5 * 60 * 1000) {
40
+ return callback(new Error("Avatar can only be changed every 5 minutes for safety."));
41
+ }
42
+ lastChange.time = now;
43
+
44
+ // Input validation
45
+ if (!options || (!options.stream && !options.url)) {
46
+ return callback(new Error("You must provide a file stream or image URL."));
47
+ }
48
+ if (options.url && !/^https?:\/\//.test(options.url)) {
49
+ return callback(new Error("Invalid image URL."));
50
+ }
51
+
52
+ // Prepare form data
53
+ const form = {};
54
+ if (options.stream) {
55
+ form.file = options.stream;
56
+ } else if (options.url) {
57
+ form.url = options.url;
58
+ }
59
+
60
+ // Use the existing postFormData util for upload
61
+ defaultFuncs.postFormData(
62
+ "https://www.facebook.com/profile/picture/upload/",
63
+ ctx.jar,
64
+ form
65
+ )
66
+ .then(res => {
67
+ if (res.statusCode === 200) {
68
+ callback(null, { success: true, message: "Avatar changed successfully." });
69
+ } else {
70
+ callback(new Error("Failed to change avatar. Status: " + res.statusCode));
71
+ }
72
+ })
73
+ .catch(err => {
74
+ callback(new Error("Avatar change failed: " + err.message));
75
+ });
76
+ };
77
+ };
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function changeBio(bio, publish, callback) {
8
+ let resolveFunc = function () { };
9
+ let rejectFunc = function () { };
10
+ const returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ if (utils.getType(publish) == "Function" || utils.getType(publish) == "AsyncFunction") {
17
+ callback = publish;
18
+ } else {
19
+ callback = function (err) {
20
+ if (err) {
21
+ return rejectFunc(err);
22
+ }
23
+ resolveFunc();
24
+ };
25
+ }
26
+ }
27
+
28
+ if (utils.getType(publish) != "Boolean") {
29
+ publish = false;
30
+ }
31
+
32
+ if (utils.getType(bio) != "String") {
33
+ bio = "";
34
+ publish = false;
35
+ }
36
+
37
+ const form = {
38
+ fb_api_caller_class: "RelayModern",
39
+ fb_api_req_friendly_name: "ProfileCometSetBioMutation",
40
+ // This doc_is is valid as of May 23, 2020
41
+ doc_id: "2725043627607610",
42
+ variables: JSON.stringify({
43
+ input: {
44
+ bio: bio,
45
+ publish_bio_feed_story: publish,
46
+ actor_id: ctx.i_userID || ctx.userID,
47
+ client_mutation_id: Math.round(Math.random() * 1024).toString()
48
+ },
49
+ hasProfileTileViewID: false,
50
+ profileTileViewID: null,
51
+ scale: 1
52
+ }),
53
+ av: ctx.i_userID || ctx.userID
54
+ };
55
+
56
+ defaultFuncs
57
+ .post(
58
+ "https://www.facebook.com/api/graphql/",
59
+ ctx.jar,
60
+ form
61
+ )
62
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
63
+ .then(function (resData) {
64
+ if (resData.errors) {
65
+ throw resData;
66
+ }
67
+
68
+ return callback();
69
+ })
70
+ .catch(function (err) {
71
+ log.error("changeBio", err);
72
+ return callback(err);
73
+ });
74
+
75
+ return returnPromise;
76
+ };
77
+ };
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function changeBlockedStatus(userID, block, callback) {
8
+ let resolveFunc = function () { };
9
+ let rejectFunc = function () { };
10
+ const returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ callback = function (err) {
17
+ if (err) {
18
+ return rejectFunc(err);
19
+ }
20
+ resolveFunc();
21
+ };
22
+ }
23
+
24
+ defaultFuncs
25
+ .post(
26
+ `https://www.facebook.com/messaging/${block ? "" : "un"}block_messages/`,
27
+ ctx.jar,
28
+ {
29
+ fbid: userID
30
+ }
31
+ )
32
+ .then(utils.saveCookies(ctx.jar))
33
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
34
+ .then(function (resData) {
35
+ if (resData.error) {
36
+ throw resData;
37
+ }
38
+
39
+ return callback();
40
+ })
41
+ .catch(function (err) {
42
+ log.error("changeBlockedStatus", err);
43
+ return callback(err);
44
+ });
45
+ return returnPromise;
46
+ };
47
+ };
@@ -0,0 +1,71 @@
1
+ // Nexus-FCA: Advanced and Safe Facebook Chat API
2
+ // changeBlockedStatusMqtt.js - Block/unblock users via MQTT
3
+
4
+ const { generateOfflineThreadingID, getCurrentTimestamp, getGUID } = require('../utils.js');
5
+
6
+ function isCallable(func) {
7
+ try {
8
+ Reflect.apply(func, null, []);
9
+ return true;
10
+ } catch (error) {
11
+ return false;
12
+ }
13
+ }
14
+
15
+ module.exports = function (defaultFuncs, api, ctx) {
16
+ return function changeBlockedStatusMqtt(userID, status, type, callback) {
17
+ if (!ctx.mqttClient) {
18
+ throw new Error('Not connected to MQTT');
19
+ }
20
+
21
+ ctx.wsReqNumber += 1;
22
+ ctx.wsTaskNumber += 1;
23
+
24
+ const label = '334';
25
+ let userBlockAction = 0;
26
+
27
+ switch (type) {
28
+ case 'messenger':
29
+ userBlockAction = status ? 1 : 0;
30
+ break;
31
+ case 'facebook':
32
+ userBlockAction = status ? 3 : 2;
33
+ break;
34
+ default:
35
+ throw new Error('Invalid type');
36
+ }
37
+
38
+ const taskPayload = {
39
+ blockee_id: userID,
40
+ request_id: getGUID(),
41
+ user_block_action: userBlockAction,
42
+ };
43
+ const payload = JSON.stringify(taskPayload);
44
+ const version = '25393437286970779';
45
+
46
+ const task = {
47
+ failure_count: null,
48
+ label: label,
49
+ payload: payload,
50
+ queue_name: 'native_sync_block',
51
+ task_id: ctx.wsTaskNumber,
52
+ };
53
+
54
+ const content = {
55
+ app_id: '2220391788200892',
56
+ payload: JSON.stringify({
57
+ tasks: [task],
58
+ epoch_id: parseInt(generateOfflineThreadingID()),
59
+ version_id: version,
60
+ }),
61
+ request_id: ctx.wsReqNumber,
62
+ type: 3,
63
+ };
64
+
65
+ if (isCallable(callback)) {
66
+ ctx.reqCallbacks[ctx.wsReqNumber] = callback;
67
+ }
68
+
69
+ ctx.mqttClient.publish('/ls_req', JSON.stringify(content), { qos: 1, retain: false });
70
+ };
71
+ };