fca-rqzax-remake 0.0.1-security → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fca-rqzax-remake might be problematic. Click here for more details.

Files changed (69) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -0
  2. package/.cache/replit/modules.stamp +0 -0
  3. package/.cache/replit/nix/env.json +1 -0
  4. package/.gitattributes +2 -0
  5. package/.travis.yml +6 -0
  6. package/CHANGELOG.md +2 -0
  7. package/DOCS.md +1738 -0
  8. package/LICENSE-MIT +21 -0
  9. package/README.md +213 -3
  10. package/index.js +542 -0
  11. package/package.json +65 -3
  12. package/replit.nix +9 -0
  13. package/src/addExternalModule.js +16 -0
  14. package/src/addUserToGroup.js +78 -0
  15. package/src/changeAdminStatus.js +79 -0
  16. package/src/changeArchivedStatus.js +41 -0
  17. package/src/changeBio.js +65 -0
  18. package/src/changeBlockedStatus.js +36 -0
  19. package/src/changeGroupImage.js +106 -0
  20. package/src/changeNickname.js +45 -0
  21. package/src/changeThreadColor.js +62 -0
  22. package/src/changeThreadEmoji.js +42 -0
  23. package/src/createNewGroup.js +70 -0
  24. package/src/createPoll.js +60 -0
  25. package/src/deleteMessage.js +45 -0
  26. package/src/deleteThread.js +43 -0
  27. package/src/forwardAttachment.js +48 -0
  28. package/src/getCurrentUserID.js +7 -0
  29. package/src/getEmojiUrl.js +27 -0
  30. package/src/getFriendsList.js +73 -0
  31. package/src/getThreadHistory.js +537 -0
  32. package/src/getThreadHistoryDeprecated.js +71 -0
  33. package/src/getThreadInfo.js +171 -0
  34. package/src/getThreadInfoDeprecated.js +56 -0
  35. package/src/getThreadList.js +213 -0
  36. package/src/getThreadListDeprecated.js +46 -0
  37. package/src/getThreadPictures.js +59 -0
  38. package/src/getUserID.js +62 -0
  39. package/src/getUserInfo.js +66 -0
  40. package/src/handleFriendRequest.js +46 -0
  41. package/src/handleMessageRequest.js +49 -0
  42. package/src/httpGet.js +49 -0
  43. package/src/httpPost.js +48 -0
  44. package/src/listenMqtt.js +654 -0
  45. package/src/logout.js +68 -0
  46. package/src/markAsDelivered.js +48 -0
  47. package/src/markAsRead.js +70 -0
  48. package/src/markAsReadAll.js +43 -0
  49. package/src/markAsSeen.js +51 -0
  50. package/src/muteThread.js +47 -0
  51. package/src/removeUserFromGroup.js +49 -0
  52. package/src/resolvePhotoUrl.js +37 -0
  53. package/src/searchForThread.js +43 -0
  54. package/src/sendMessage.js +321 -0
  55. package/src/sendTypingIndicator.js +80 -0
  56. package/src/setMessageReaction.js +109 -0
  57. package/src/setPostReaction.js +64 -0
  58. package/src/setTitle.js +74 -0
  59. package/src/threadColors.js +41 -0
  60. package/src/unfriend.js +43 -0
  61. package/src/unsendMessage.js +40 -0
  62. package/test/data/shareAttach.js +146 -0
  63. package/test/data/something.mov +0 -0
  64. package/test/data/test.png +0 -0
  65. package/test/data/test.txt +7 -0
  66. package/test/example-config.json +18 -0
  67. package/test/test-page.js +140 -0
  68. package/test/test.js +385 -0
  69. package/utils.js +1234 -0
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+ var bluebird = require("bluebird");
6
+
7
+ var allowedProperties = {
8
+ attachment: true,
9
+ url: true,
10
+ sticker: true,
11
+ emoji: true,
12
+ emojiSize: true,
13
+ body: true,
14
+ mentions: true,
15
+ location: true,
16
+ };
17
+
18
+ module.exports = function (defaultFuncs, api, ctx) {
19
+ function uploadAttachment(attachments, callback) {
20
+ var uploads = [];
21
+
22
+ // create an array of promises
23
+ for (var i = 0; i < attachments.length; i++) {
24
+ if (!utils.isReadableStream(attachments[i])) throw { error: "Attachment should be a readable stream and not " + utils.getType(attachments[i]) + "." };
25
+ var form = {
26
+ upload_1024: attachments[i],
27
+ voice_clip: "true"
28
+ };
29
+
30
+ uploads.push(
31
+ defaultFuncs
32
+ .postFormData("https://upload.facebook.com/ajax/mercury/upload.php", ctx.jar, form, {})
33
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
34
+ .then(function (resData) {
35
+ if (resData.error) throw resData;
36
+ // We have to return the data unformatted unless we want to change it
37
+ // back in sendMessage.
38
+ return resData.payload.metadata[0];
39
+ })
40
+ );
41
+ }
42
+
43
+ // resolve all promises
44
+ bluebird
45
+ .all(uploads)
46
+ .then(resData => callback(null, resData)
47
+ )
48
+ .catch(function (err) {
49
+ log.error("uploadAttachment", err);
50
+ return callback(err);
51
+ });
52
+ }
53
+
54
+ function getUrl(url, callback) {
55
+ var form = {
56
+ image_height: 960,
57
+ image_width: 960,
58
+ uri: url
59
+ };
60
+
61
+ defaultFuncs
62
+ .post("https://www.facebook.com/message_share_attachment/fromURI/", ctx.jar, form)
63
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
64
+ .then(function (resData) {
65
+ if (resData.error) return callback(resData);
66
+ if (!resData.payload) return callback({ error: "Invalid url" });
67
+ callback(null, resData.payload.share_data.share_params);
68
+ })
69
+ .catch(function (err) {
70
+ log.error("getUrl", err);
71
+ return callback(err);
72
+ });
73
+ }
74
+
75
+ function sendContent(form, threadID, isSingleUser, messageAndOTID, callback) {
76
+ // There are three cases here:
77
+ // 1. threadID is of type array, where we're starting a new group chat with users
78
+ // specified in the array.
79
+ // 2. User is sending a message to a specific user.
80
+ // 3. No additional form params and the message goes to an existing group chat.
81
+ if (utils.getType(threadID) === "Array") {
82
+ for (var i = 0; i < threadID.length; i++) form["specific_to_list[" + i + "]"] = "fbid:" + threadID[i];
83
+ form["specific_to_list[" + threadID.length + "]"] = "fbid:" + ctx.userID;
84
+ form["client_thread_id"] = "root:" + messageAndOTID;
85
+ log.info("sendMessage", "Sending message to multiple users: " + threadID);
86
+ }
87
+ else {
88
+ // This means that threadID is the id of a user, and the chat
89
+ // is a single person chat
90
+ if (isSingleUser) {
91
+ form["specific_to_list[0]"] = "fbid:" + threadID;
92
+ form["specific_to_list[1]"] = "fbid:" + ctx.userID;
93
+ form["other_user_fbid"] = threadID;
94
+ }
95
+ else form["thread_fbid"] = threadID;
96
+ }
97
+
98
+ if (ctx.globalOptions.pageID) {
99
+ form["author"] = "fbid:" + ctx.globalOptions.pageID;
100
+ form["specific_to_list[1]"] = "fbid:" + ctx.globalOptions.pageID;
101
+ form["creator_info[creatorID]"] = ctx.userID;
102
+ form["creator_info[creatorType]"] = "direct_admin";
103
+ form["creator_info[labelType]"] = "sent_message";
104
+ form["creator_info[pageID]"] = ctx.globalOptions.pageID;
105
+ form["request_user_id"] = ctx.globalOptions.pageID;
106
+ form["creator_info[profileURI]"] = "https://www.facebook.com/profile.php?id=" + ctx.userID;
107
+ }
108
+
109
+ defaultFuncs
110
+ .post("https://www.facebook.com/messaging/send/", ctx.jar, form)
111
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
112
+ .then(function (resData) {
113
+ if (!resData) return callback({ error: "Send message failed." });
114
+ if (resData.error) {
115
+ if (resData.error === 1545012) log.warn("sendMessage", "Got error 1545012. This might mean that you're not part of the conversation " + threadID);
116
+ return callback(resData);
117
+ }
118
+
119
+ var messageInfo = resData.payload.actions.reduce(function (p, v) {
120
+ return (
121
+ {
122
+ threadID: v.thread_fbid,
123
+ messageID: v.message_id,
124
+ timestamp: v.timestamp
125
+ } || p
126
+ );
127
+ }, null);
128
+
129
+ return callback(null, messageInfo);
130
+ })
131
+ .catch(function (err) {
132
+ log.error("sendMessage", err);
133
+ if (utils.getType(err) == "Object" && err.error === "Not logged in.") ctx.loggedIn = false;
134
+ return callback(err);
135
+ });
136
+ }
137
+
138
+ function send(form, threadID, messageAndOTID, callback, isGroup) {
139
+ // We're doing a query to this to check if the given id is the id of
140
+ // a user or of a group chat. The form will be different depending
141
+ // on that.
142
+ if (utils.getType(threadID) === "Array") sendContent(form, threadID, false, messageAndOTID, callback);
143
+ else {
144
+ if (utils.getType(isGroup) != "Boolean") sendContent(form, threadID, threadID.length === 15, messageAndOTID, callback);
145
+ else sendContent(form, threadID, !isGroup, messageAndOTID, callback);
146
+ }
147
+ }
148
+
149
+ function handleUrl(msg, form, callback, cb) {
150
+ if (msg.url) {
151
+ form["shareable_attachment[share_type]"] = "100";
152
+ getUrl(msg.url, function (err, params) {
153
+ if (err) return callback(err);
154
+ form["shareable_attachment[share_params]"] = params;
155
+ cb();
156
+ });
157
+ }
158
+ else cb();
159
+ }
160
+
161
+ function handleLocation(msg, form, callback, cb) {
162
+ if (msg.location) {
163
+ if (msg.location.latitude == null || msg.location.longitude == null) return callback({ error: "location property needs both latitude and longitude" });
164
+ form["location_attachment[coordinates][latitude]"] = msg.location.latitude;
165
+ form["location_attachment[coordinates][longitude]"] = msg.location.longitude;
166
+ form["location_attachment[is_current_location]"] = !!msg.location.current;
167
+ }
168
+ cb();
169
+ }
170
+
171
+ function handleSticker(msg, form, callback, cb) {
172
+ if (msg.sticker) form["sticker_id"] = msg.sticker;
173
+ cb();
174
+ }
175
+
176
+ function handleEmoji(msg, form, callback, cb) {
177
+ if (msg.emojiSize != null && msg.emoji == null) return callback({ error: "emoji property is empty" });
178
+ if (msg.emoji) {
179
+ if (msg.emojiSize == null) msg.emojiSize = "medium";
180
+ if (msg.emojiSize != "small" && msg.emojiSize != "medium" && msg.emojiSize != "large") return callback({ error: "emojiSize property is invalid" });
181
+ if (form["body"] != null && form["body"] != "") return callback({ error: "body is not empty" });
182
+ form["body"] = msg.emoji;
183
+ form["tags[0]"] = "hot_emoji_size:" + msg.emojiSize;
184
+ }
185
+ cb();
186
+ }
187
+
188
+ function handleAttachment(msg, form, callback, cb) {
189
+ if (msg.attachment) {
190
+ form["image_ids"] = [];
191
+ form["gif_ids"] = [];
192
+ form["file_ids"] = [];
193
+ form["video_ids"] = [];
194
+ form["audio_ids"] = [];
195
+
196
+ if (utils.getType(msg.attachment) !== "Array") msg.attachment = [msg.attachment];
197
+
198
+ uploadAttachment(msg.attachment, function (err, files) {
199
+ if (err) return callback(err);
200
+ files.forEach(function (file) {
201
+ var key = Object.keys(file);
202
+ var type = key[0]; // image_id, file_id, etc
203
+ form["" + type + "s"].push(file[type]); // push the id
204
+ });
205
+ cb();
206
+ });
207
+ }
208
+ else cb();
209
+ }
210
+
211
+ function handleMention(msg, form, callback, cb) {
212
+ if (msg.mentions) {
213
+ for (let i = 0; i < msg.mentions.length; i++) {
214
+ const mention = msg.mentions[i];
215
+ const tag = mention.tag;
216
+ if (typeof tag !== "string") return callback({ error: "Mention tags must be strings." });
217
+ const offset = msg.body.indexOf(tag, mention.fromIndex || 0);
218
+ if (offset < 0) log.warn("handleMention", 'Mention for "' + tag + '" not found in message string.');
219
+ if (mention.id == null) log.warn("handleMention", "Mention id should be non-null.");
220
+
221
+ const id = mention.id || 0;
222
+ const emptyChar = '\u200E';
223
+ form["body"] = emptyChar + msg.body;
224
+ form["profile_xmd[" + i + "][offset]"] = offset + 1;
225
+ form["profile_xmd[" + i + "][length]"] = tag.length;
226
+ form["profile_xmd[" + i + "][id]"] = id;
227
+ form["profile_xmd[" + i + "][type]"] = "p";
228
+ }
229
+ }
230
+ cb();
231
+ }
232
+
233
+ return function sendMessage(msg, threadID, callback, replyToMessage, isGroup) {
234
+ typeof isGroup == "undefined" ? isGroup = null : "";
235
+ if (!callback && (utils.getType(threadID) === "Function" || utils.getType(threadID) === "AsyncFunction")) return threadID({ error: "Pass a threadID as a second argument." });
236
+ if (!replyToMessage && utils.getType(callback) === "String") {
237
+ replyToMessage = callback;
238
+ callback = function () { };
239
+ }
240
+
241
+ var resolveFunc = function () { };
242
+ var rejectFunc = function () { };
243
+ var returnPromise = new Promise(function (resolve, reject) {
244
+ resolveFunc = resolve;
245
+ rejectFunc = reject;
246
+ });
247
+
248
+ if (!callback) {
249
+ callback = function (err, data) {
250
+ if (err) return rejectFunc(err);
251
+ resolveFunc(data);
252
+ };
253
+ }
254
+
255
+ var msgType = utils.getType(msg);
256
+ var threadIDType = utils.getType(threadID);
257
+ var messageIDType = utils.getType(replyToMessage);
258
+
259
+ if (msgType !== "String" && msgType !== "Object") return callback({ error: "Message should be of type string or object and not " + msgType + "." });
260
+
261
+ // Changing this to accomodate an array of users
262
+ if (threadIDType !== "Array" && threadIDType !== "Number" && threadIDType !== "String") return callback({ error: "ThreadID should be of type number, string, or array and not " + threadIDType + "." });
263
+
264
+ if (replyToMessage && messageIDType !== 'String') return callback({ error: "MessageID should be of type string and not " + threadIDType + "." });
265
+
266
+ if (msgType === "String") msg = { body: msg };
267
+ var disallowedProperties = Object.keys(msg).filter(prop => !allowedProperties[prop]);
268
+ if (disallowedProperties.length > 0) return callback({ error: "Dissallowed props: `" + disallowedProperties.join(", ") + "`" });
269
+
270
+ var messageAndOTID = utils.generateOfflineThreadingID();
271
+
272
+ var form = {
273
+ client: "mercury",
274
+ action_type: "ma-type:user-generated-message",
275
+ author: "fbid:" + ctx.userID,
276
+ timestamp: Date.now(),
277
+ timestamp_absolute: "Today",
278
+ timestamp_relative: utils.generateTimestampRelative(),
279
+ timestamp_time_passed: "0",
280
+ is_unread: false,
281
+ is_cleared: false,
282
+ is_forward: false,
283
+ is_filtered_content: false,
284
+ is_filtered_content_bh: false,
285
+ is_filtered_content_account: false,
286
+ is_filtered_content_quasar: false,
287
+ is_filtered_content_invalid_app: false,
288
+ is_spoof_warning: false,
289
+ source: "source:chat:web",
290
+ "source_tags[0]": "source:chat",
291
+ body: msg.body ? msg.body.toString() : "",
292
+ html_body: false,
293
+ ui_push_phase: "V3",
294
+ status: "0",
295
+ offline_threading_id: messageAndOTID,
296
+ message_id: messageAndOTID,
297
+ threading_id: utils.generateThreadingID(ctx.clientID),
298
+ "ephemeral_ttl_mode:": "0",
299
+ manual_retry_cnt: "0",
300
+ has_attachment: !!(msg.attachment || msg.url || msg.sticker),
301
+ signatureID: utils.getSignatureID(),
302
+ replied_to_message_id: replyToMessage
303
+ };
304
+
305
+ handleLocation(msg, form, callback, () =>
306
+ handleSticker(msg, form, callback, () =>
307
+ handleAttachment(msg, form, callback, () =>
308
+ handleUrl(msg, form, callback, () =>
309
+ handleEmoji(msg, form, callback, () =>
310
+ handleMention(msg, form, callback, () =>
311
+ send(form, threadID, messageAndOTID, callback, isGroup)
312
+ )
313
+ )
314
+ )
315
+ )
316
+ )
317
+ );
318
+
319
+ return returnPromise;
320
+ };
321
+ };
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ function makeTypingIndicator(typ, threadID, callback, isGroup) {
8
+ var form = {
9
+ typ: +typ,
10
+ to: "",
11
+ source: "mercury-chat",
12
+ thread: threadID
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 (utils.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(utils.parseAndCheckLogin(ctx, defaultFuncs))
24
+ .then(function (resData) {
25
+ if (resData.error) throw resData;
26
+ return callback();
27
+ })
28
+ .catch(function (err) {
29
+ log.error("sendTypingIndicator", err);
30
+ if (utils.getType(err) == "Object" && err.error === "Not logged in") {
31
+ ctx.loggedIn = false;
32
+ }
33
+ return callback(err);
34
+ });
35
+ }
36
+ else {
37
+ api.getUserInfo(threadID, function (err, res) {
38
+ if (err) return callback(err);
39
+ // If id is single person chat
40
+ if (Object.keys(res).length > 0) form.to = threadID;
41
+ defaultFuncs
42
+ .post("https://www.facebook.com/ajax/messaging/typ.php", ctx.jar, form)
43
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
44
+ .then(function (resData) {
45
+ if (resData.error) throw resData;
46
+ return callback();
47
+ })
48
+ .catch(function (err) {
49
+ log.error("sendTypingIndicator", err);
50
+ if (utils.getType(err) == "Object" && err.error === "Not logged in.") ctx.loggedIn = false;
51
+ return callback(err);
52
+ });
53
+ });
54
+ }
55
+ }
56
+
57
+ return function sendTypingIndicator(threadID, callback, isGroup) {
58
+ if (
59
+ utils.getType(callback) !== "Function" &&
60
+ utils.getType(callback) !== "AsyncFunction"
61
+ ) {
62
+ if (callback) log.warn("sendTypingIndicator", "callback is not a function - ignoring.");
63
+ callback = () => { };
64
+ }
65
+
66
+ makeTypingIndicator(true, threadID, callback, isGroup);
67
+
68
+ return function end(cb) {
69
+ if (
70
+ utils.getType(cb) !== "Function" &&
71
+ utils.getType(cb) !== "AsyncFunction"
72
+ ) {
73
+ if (cb) log.warn("sendTypingIndicator", "callback is not a function - ignoring.");
74
+ cb = () => { };
75
+ }
76
+
77
+ makeTypingIndicator(false, threadID, cb, isGroup);
78
+ };
79
+ };
80
+ };
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function setMessageReaction(reaction, messageID, callback, forceCustomReaction) {
8
+ var resolveFunc = function () { };
9
+ var rejectFunc = function () { };
10
+ var returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ callback = function (err, data) {
17
+ if (err) return rejectFunc(err);
18
+ resolveFunc(data);
19
+ };
20
+ }
21
+
22
+ switch (reaction) {
23
+ case "\uD83D\uDE0D": //:heart_eyes:
24
+ case "\uD83D\uDE06": //:laughing:
25
+ case "\uD83D\uDE2E": //:open_mouth:
26
+ case "\uD83D\uDE22": //:cry:
27
+ case "\uD83D\uDE20": //:angry:
28
+ case "\uD83D\uDC4D": //:thumbsup:
29
+ case "\uD83D\uDC4E": //:thumbsdown:
30
+ case "\u2764": //:heart:
31
+ case "\uD83D\uDC97": //:glowingheart:
32
+ case "":
33
+ //valid
34
+ break;
35
+ case ":heart_eyes:":
36
+ case ":love:":
37
+ reaction = "\uD83D\uDE0D";
38
+ break;
39
+ case ":laughing:":
40
+ case ":haha:":
41
+ reaction = "\uD83D\uDE06";
42
+ break;
43
+ case ":open_mouth:":
44
+ case ":wow:":
45
+ reaction = "\uD83D\uDE2E";
46
+ break;
47
+ case ":cry:":
48
+ case ":sad:":
49
+ reaction = "\uD83D\uDE22";
50
+ break;
51
+ case ":angry:":
52
+ reaction = "\uD83D\uDE20";
53
+ break;
54
+ case ":thumbsup:":
55
+ case ":like:":
56
+ reaction = "\uD83D\uDC4D";
57
+ break;
58
+ case ":thumbsdown:":
59
+ case ":dislike:":
60
+ reaction = "\uD83D\uDC4E";
61
+ break;
62
+ case ":heart:":
63
+ reaction = "\u2764";
64
+ break;
65
+ case ":glowingheart:":
66
+ reaction = "\uD83D\uDC97";
67
+ break;
68
+ default:
69
+ if (forceCustomReaction) break;
70
+ return callback({ error: "Reaction is not a valid emoji." });
71
+ }
72
+
73
+ var variables = {
74
+ data: {
75
+ client_mutation_id: ctx.clientMutationId++,
76
+ actor_id: ctx.userID,
77
+ action: reaction == "" ? "REMOVE_REACTION" : "ADD_REACTION",
78
+ message_id: messageID,
79
+ reaction: reaction
80
+ }
81
+ };
82
+
83
+ var qs = {
84
+ doc_id: "1491398900900362",
85
+ variables: JSON.stringify(variables),
86
+ dpr: 1
87
+ };
88
+
89
+ defaultFuncs
90
+ .postFormData(
91
+ "https://www.facebook.com/webgraphql/mutation/",
92
+ ctx.jar,
93
+ {},
94
+ qs
95
+ )
96
+ .then(utils.parseAndCheckLogin(ctx.jar, defaultFuncs))
97
+ .then(function (resData) {
98
+ if (!resData) throw { error: "setReaction returned empty object." };
99
+ if (resData.error) throw resData;
100
+ callback(null);
101
+ })
102
+ .catch(function (err) {
103
+ log.error("setReaction", err);
104
+ return callback(err);
105
+ });
106
+
107
+ return returnPromise;
108
+ };
109
+ };
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function postReaction(postID, type, callback) {
8
+ var resolveFunc = function () { };
9
+ var rejectFunc = function () { };
10
+ var returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ callback = function (err, data) {
17
+ if (err) return rejectFunc(err);
18
+ resolveFunc(data);
19
+ };
20
+ }
21
+
22
+ var map = {
23
+ like: 1,
24
+ heart: 2,
25
+ wow: 3,
26
+ haha: 4,
27
+ sad: 7,
28
+ angry: 8
29
+ };
30
+ if (typeof type != "number") {
31
+ type = map[type.toLocaleLowerCase()];
32
+ if (!type) type = 1;
33
+ }
34
+ var form = {
35
+ av: ctx.userID,
36
+ fb_api_caller_class: "RelayModern",
37
+ fb_api_req_friendly_name: "UFI2FeedbackReactMutation",
38
+ //This doc_id is valid as of January 17th, 2020
39
+ doc_id: "2580813318646067",
40
+ variables: JSON.stringify({
41
+ input: {
42
+ client_mutation_id: "7",
43
+ actor_id: ctx.userID,
44
+ feedback_reaction: type
45
+ },
46
+ useDefaultActor: true
47
+ })
48
+ };
49
+
50
+ defaultFuncs
51
+ .post("https://www.facebook.com/api/graphql/", ctx.jar, form)
52
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
53
+ .then(function (resData) {
54
+ if (resData.error) throw resData;
55
+ return callback();
56
+ })
57
+ .catch(function (err) {
58
+ log.error("setPostReaction", err);
59
+ return callback(err);
60
+ });
61
+
62
+ return returnPromise;
63
+ };
64
+ };
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function setTitle(newTitle, threadID, callback) {
8
+ if (
9
+ !callback &&
10
+ (utils.getType(threadID) === "Function" ||
11
+ utils.getType(threadID) === "AsyncFunction")
12
+ ) throw { error: "please pass a threadID as a second argument." };
13
+
14
+
15
+ var resolveFunc = function () { };
16
+ var rejectFunc = function () { };
17
+ var 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
+ var messageAndOTID = utils.generateOfflineThreadingID();
30
+ var form = {
31
+ client: "mercury",
32
+ action_type: "ma-type:log-message",
33
+ author: "fbid:" + ctx.userID,
34
+ author_email: "",
35
+ coordinates: "",
36
+ timestamp: Date.now(),
37
+ timestamp_absolute: "Today",
38
+ timestamp_relative: utils.generateTimestampRelative(),
39
+ timestamp_time_passed: "0",
40
+ is_unread: false,
41
+ is_cleared: false,
42
+ is_forward: false,
43
+ is_filtered_content: false,
44
+ is_spoof_warning: false,
45
+ source: "source:chat:web",
46
+ "source_tags[0]": "source:chat",
47
+ status: "0",
48
+ offline_threading_id: messageAndOTID,
49
+ message_id: messageAndOTID,
50
+ threading_id: utils.generateThreadingID(ctx.clientID),
51
+ manual_retry_cnt: "0",
52
+ thread_fbid: threadID,
53
+ thread_name: newTitle,
54
+ thread_id: threadID,
55
+ log_message_type: "log:thread-name"
56
+ };
57
+
58
+ defaultFuncs
59
+ .post("https://www.facebook.com/messaging/set_thread_name/", ctx.jar, form)
60
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
61
+ .then(function (resData) {
62
+ if (resData.error && resData.error === 1545012) throw { error: "Cannot change chat title: Not member of chat." };
63
+ if (resData.error && resData.error === 1545003) throw { error: "Cannot set title of single-user chat." };
64
+ if (resData.error) throw resData;
65
+ return callback();
66
+ })
67
+ .catch(function (err) {
68
+ log.error("setTitle", err);
69
+ return callback(err);
70
+ });
71
+
72
+ return returnPromise;
73
+ };
74
+ };
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ module.exports = function (_defaultFuncs, _api, _ctx) {
4
+ // Currently the only colors that can be passed to api.changeThreadColor(); may change if Facebook adds more
5
+ return {
6
+
7
+ //#region This part is for backward compatibly
8
+ //trying to match the color one-by-one. kill me plz
9
+ MessengerBlue: "196241301102133", //DefaultBlue
10
+ Viking: "1928399724138152", //TealBlue
11
+ GoldenPoppy: "174636906462322", //Yellow
12
+ RadicalRed: "2129984390566328", //Red
13
+ Shocking: "2058653964378557", //LavenderPurple
14
+ FreeSpeechGreen: "2136751179887052", //Green
15
+ Pumpkin: "175615189761153", //Orange
16
+ LightCoral: "980963458735625", //CoralPink
17
+ MediumSlateBlue: "234137870477637", //BrightPurple
18
+ DeepSkyBlue: "2442142322678320", //AquaBlue
19
+ BrilliantRose: "169463077092846", //HotPink
20
+ //i've tried my best, everything else can't be mapped. (or is it?) -UIRI 2020
21
+ //#endregion
22
+
23
+ DefaultBlue: "196241301102133",
24
+ HotPink: "169463077092846",
25
+ AquaBlue: "2442142322678320",
26
+ BrightPurple: "234137870477637",
27
+ CoralPink: "980963458735625",
28
+ Orange: "175615189761153",
29
+ Green: "2136751179887052",
30
+ LavenderPurple: "2058653964378557",
31
+ Red: "2129984390566328",
32
+ Yellow: "174636906462322",
33
+ TealBlue: "1928399724138152",
34
+ Aqua: "417639218648241",
35
+ Mango: "930060997172551",
36
+ Berry: "164535220883264",
37
+ Citrus: "370940413392601",
38
+ Candy: "205488546921017",
39
+ //StarWars: "809305022860427" Removed.
40
+ };
41
+ };