fca-project-haxor 1.1.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. package/.gitattributes +2 -0
  2. package/.prettierrc +4 -0
  3. package/Extra/Database/index.js +469 -0
  4. package/Extra/ExtraAddons.js +82 -0
  5. package/Extra/ExtraFindUID.js +62 -0
  6. package/Extra/ExtraGetThread.js +340 -0
  7. package/Extra/ExtraScreenShot.js +430 -0
  8. package/Extra/ExtraUptimeRobot.js +38 -0
  9. package/Extra/Html/Classic/script.js +119 -0
  10. package/Extra/Html/Classic/style.css +8 -0
  11. package/Extra/Security/AES_256_GCM/index.js +0 -0
  12. package/Extra/Security/Base/Step_1.js +6 -0
  13. package/Extra/Security/Base/Step_2.js +22 -0
  14. package/Extra/Security/Base/Step_3.js +22 -0
  15. package/Extra/Security/Base/index.js +173 -0
  16. package/Extra/Security/Index.js +5 -0
  17. package/Extra/Security/Step_1.js +6 -0
  18. package/Extra/Security/Step_2.js +22 -0
  19. package/Extra/Security/Step_3.js +22 -0
  20. package/Extra/Src/Change_Environment.js +24 -0
  21. package/Extra/Src/Check_Update.js +66 -0
  22. package/Extra/Src/History.js +115 -0
  23. package/Extra/Src/Instant_Update.js +65 -0
  24. package/Extra/Src/Last-Run.js +65 -0
  25. package/Extra/Src/Premium.js +81 -0
  26. package/Extra/Src/Release_Memory.js +41 -0
  27. package/Extra/Src/Websocket.js +213 -0
  28. package/Extra/Src/image/checkmate.jpg +0 -0
  29. package/Extra/Src/uuid.js +137 -0
  30. package/Func/AcceptAgreement.js +31 -0
  31. package/Func/ClearCache.js +64 -0
  32. package/Func/ReportV1.js +54 -0
  33. package/LICENSE +21 -0
  34. package/Language/index.json +217 -0
  35. package/Main.js +1217 -0
  36. package/README.md +139 -0
  37. package/SECURITY.md +18 -0
  38. package/broadcast.js +40 -0
  39. package/index.js +387 -0
  40. package/logger.js +67 -0
  41. package/package.json +92 -0
  42. package/src/Dev_Horizon_Data.js +125 -0
  43. package/src/Premium.js +25 -0
  44. package/src/Screenshot.js +83 -0
  45. package/src/addExternalModule.js +16 -0
  46. package/src/addUserToGroup.js +79 -0
  47. package/src/changeAdminStatus.js +79 -0
  48. package/src/changeArchivedStatus.js +41 -0
  49. package/src/changeAvt.js +85 -0
  50. package/src/changeBio.js +65 -0
  51. package/src/changeBlockedStatus.js +36 -0
  52. package/src/changeGroupImage.js +106 -0
  53. package/src/changeNickname.js +45 -0
  54. package/src/changeThreadColor.js +62 -0
  55. package/src/changeThreadEmoji.js +42 -0
  56. package/src/createNewGroup.js +70 -0
  57. package/src/createPoll.js +60 -0
  58. package/src/deleteMessage.js +45 -0
  59. package/src/deleteThread.js +43 -0
  60. package/src/forwardAttachment.js +48 -0
  61. package/src/getAccessToken.js +28 -0
  62. package/src/getCurrentUserID.js +7 -0
  63. package/src/getEmojiUrl.js +27 -0
  64. package/src/getFriendsList.js +73 -0
  65. package/src/getMessage.js +80 -0
  66. package/src/getThreadHistory.js +537 -0
  67. package/src/getThreadInfo.js +425 -0
  68. package/src/getThreadList.js +213 -0
  69. package/src/getThreadMain.js +220 -0
  70. package/src/getThreadPictures.js +59 -0
  71. package/src/getUID.js +59 -0
  72. package/src/getUserID.js +62 -0
  73. package/src/getUserInfo.js +113 -0
  74. package/src/getUserInfoMain.js +65 -0
  75. package/src/getUserInfoV2.js +32 -0
  76. package/src/getUserInfoV3.js +63 -0
  77. package/src/getUserInfoV4.js +55 -0
  78. package/src/getUserInfoV5.js +61 -0
  79. package/src/handleFriendRequest.js +46 -0
  80. package/src/handleMessageRequest.js +49 -0
  81. package/src/httpGet.js +49 -0
  82. package/src/httpPost.js +48 -0
  83. package/src/httpPostFormData.js +41 -0
  84. package/src/listenMqtt.js +787 -0
  85. package/src/logout.js +68 -0
  86. package/src/markAsDelivered.js +48 -0
  87. package/src/markAsRead.js +70 -0
  88. package/src/markAsReadAll.js +43 -0
  89. package/src/markAsSeen.js +51 -0
  90. package/src/muteThread.js +47 -0
  91. package/src/removeUserFromGroup.js +49 -0
  92. package/src/resolvePhotoUrl.js +37 -0
  93. package/src/searchForThread.js +43 -0
  94. package/src/sendMessage.js +455 -0
  95. package/src/sendTypingIndicator.js +80 -0
  96. package/src/setMessageReaction.js +109 -0
  97. package/src/setPostReaction.js +102 -0
  98. package/src/setTitle.js +74 -0
  99. package/src/threadColors.js +39 -0
  100. package/src/unfriend.js +43 -0
  101. package/src/unsendMessage.js +40 -0
  102. package/test/Database_Test.js +4 -0
  103. package/test/Db2.js +530 -0
  104. package/test/Haxor_Database/A_README.md +1 -0
  105. package/test/Haxor_Database/Database.db +0 -0
  106. package/test/data/shareAttach.js +146 -0
  107. package/test/data/something.mov +0 -0
  108. package/test/data/test.png +0 -0
  109. package/test/data/test.txt +7 -0
  110. package/test/env/.env +0 -0
  111. package/test/example-config.json +18 -0
  112. package/test/example-db.db +0 -0
  113. package/test/memoryleak.js +18 -0
  114. package/test/test-page.js +140 -0
  115. package/test/test.js +385 -0
  116. package/test/testv2.js +18 -0
  117. package/utils.js +1683 -0
@@ -0,0 +1,455 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Fixed or Colored By: @HarryWakazaki
5
+ * 21/4/2022
6
+ *
7
+ * Remodel By: https://www.facebook.com/icotacteeee
8
+ * Added: Custom Font
9
+ * 11/26/2023
10
+ */
11
+
12
+ var utils = require("../utils");
13
+ var log = require("npmlog");
14
+ var bluebird = require("bluebird");
15
+ var fs = require('fs-extra');
16
+
17
+ if (global.Fca.Require.FastConfig.CustomFont) {
18
+ var projecthaxor = {
19
+ CustomFont: true
20
+ }
21
+ } else {
22
+ var projecthaxor = {
23
+ CustomFont: false
24
+ }
25
+ }
26
+
27
+ var allowedProperties = {
28
+ attachment: true,
29
+ url: true,
30
+ sticker: true,
31
+ emoji: true,
32
+ emojiSize: true,
33
+ body: true,
34
+ mentions: true,
35
+ location: true,
36
+ font: true
37
+ };
38
+
39
+ var AntiText = "Your criminal activity was detected while attempting to send an Appstate file";
40
+ var Location_Stack;
41
+
42
+ module.exports = function(defaultFuncs, api, ctx) {
43
+ let font = {
44
+ a: "𝖺",
45
+ b: "𝖻",
46
+ c: "𝖼",
47
+ d: "𝖽",
48
+ e: "𝖾",
49
+ f: "𝖿",
50
+ g: "𝗀",
51
+ h: "𝗁",
52
+ i: "𝗂",
53
+ j: "𝗃",
54
+ k: "𝗄",
55
+ l: "𝗅",
56
+ m: "𝗆",
57
+ n: "𝗇",
58
+ o: "𝗈",
59
+ p: "𝗉",
60
+ q: "𝗊",
61
+ r: "𝗋",
62
+ s: "𝗌",
63
+ t: "𝗍",
64
+ u: "𝗎",
65
+ v: "𝗏",
66
+ w: "𝗐",
67
+ x: "𝗑",
68
+ y: "𝗒",
69
+ z: "𝗓",
70
+ A: "𝖠",
71
+ B: "𝖡",
72
+ C: "𝖢",
73
+ D: "𝖣",
74
+ E: "𝖤",
75
+ F: "𝖥",
76
+ G: "𝖦",
77
+ H: "𝖧",
78
+ I: "𝖨",
79
+ J: "𝖩",
80
+ K: "𝖪",
81
+ L: "𝖫",
82
+ M: "𝖬",
83
+ N: "𝖭",
84
+ O: "𝖮",
85
+ P: "𝖯",
86
+ Q: "𝖰",
87
+ R: "𝖱",
88
+ S: "𝖲",
89
+ T: "𝖳",
90
+ U: "𝖴",
91
+ V: "𝖵",
92
+ W: "𝖶",
93
+ X: "𝖷",
94
+ Y: "𝖸",
95
+ Z: "𝖹",
96
+ };
97
+ function replaceCharacters(inputString) {
98
+ const replacedString = inputString.replace(/[A-Za-z]/g, (char) => {
99
+ return font[char] || char;
100
+ });
101
+ return replacedString;
102
+ }
103
+
104
+ function uploadAttachment(attachments, callback) {
105
+ var uploads = [];
106
+
107
+ // create an array of promises
108
+ for (var i = 0; i < attachments.length; i++) {
109
+ if (!utils.isReadableStream(attachments[i])) throw { error: "Attachment should be a readable stream and not " + utils.getType(attachments[i]) + "." };
110
+ var form = {
111
+ upload_1024: attachments[i],
112
+ voice_clip: "true"
113
+ };
114
+
115
+ uploads.push(
116
+ defaultFuncs
117
+ .postFormData("https://upload.facebook.com/ajax/mercury/upload.php", ctx.jar, form, {})
118
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
119
+ .then(function(resData) {
120
+ if (resData.error) throw resData;
121
+ // We have to return the data unformatted unless we want to change it
122
+ // back in sendMessage.
123
+ return resData.payload.metadata[0];
124
+ })
125
+ );
126
+ }
127
+
128
+ // resolve all promises
129
+ bluebird
130
+ .all(uploads)
131
+ .then(resData => callback(null, resData)
132
+ )
133
+ .catch(function(err) {
134
+ log.error("uploadAttachment", err);
135
+ return callback(err);
136
+ });
137
+ }
138
+
139
+ function getUrl(url, callback) {
140
+ var form = {
141
+ image_height: 960,
142
+ image_width: 960,
143
+ uri: url
144
+ };
145
+
146
+ defaultFuncs
147
+ .post("https://www.facebook.com/message_share_attachment/fromURI/", ctx.jar, form)
148
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
149
+ .then(function(resData) {
150
+ if (resData.error) return callback(resData);
151
+ if (!resData.payload) return callback({ error: "Invalid url" });
152
+ callback(null, resData.payload.share_data.share_params);
153
+ })
154
+ .catch(function(err) {
155
+ log.error("getUrl", err);
156
+ return callback(err);
157
+ });
158
+ }
159
+
160
+ function sendContent(form, threadID, isSingleUser, messageAndOTID, callback) {
161
+ // There are three cases here:
162
+ // 1. threadID is of type array, where we're starting a new group chat with users
163
+ // specified in the array.
164
+ // 2. User is sending a message to a specific user.
165
+ // 3. No additional form params and the message goes to an existing group chat.
166
+ if (utils.getType(threadID) === "Array") {
167
+ for (var i = 0; i < threadID.length; i++) form["specific_to_list[" + i + "]"] = "fbid:" + threadID[i];
168
+ form["specific_to_list[" + threadID.length + "]"] = "fbid:" + ctx.userID;
169
+ form["client_thread_id"] = "root:" + messageAndOTID;
170
+ log.info("sendMessage", "Sending message to multiple users: " + threadID);
171
+ }
172
+ else {
173
+ // This means that threadID is the id of a user, and the chat
174
+ // is a single person chat
175
+ if (isSingleUser) {
176
+ form["specific_to_list[0]"] = "fbid:" + threadID;
177
+ form["specific_to_list[1]"] = "fbid:" + ctx.userID;
178
+ form["other_user_fbid"] = threadID;
179
+ }
180
+ else form["thread_fbid"] = threadID;
181
+ }
182
+
183
+ if (ctx.globalOptions.pageID) {
184
+ form["author"] = "fbid:" + ctx.globalOptions.pageID;
185
+ form["specific_to_list[1]"] = "fbid:" + ctx.globalOptions.pageID;
186
+ form["creator_info[creatorID]"] = ctx.userID;
187
+ form["creator_info[creatorType]"] = "direct_admin";
188
+ form["creator_info[labelType]"] = "sent_message";
189
+ form["creator_info[pageID]"] = ctx.globalOptions.pageID;
190
+ form["request_user_id"] = ctx.globalOptions.pageID;
191
+ form["creator_info[profileURI]"] = "https://www.facebook.com/profile.php?id=" + ctx.userID;
192
+ }
193
+
194
+ if (global.Fca.Require.FastConfig.AntiSendAppState == true) {
195
+ try {
196
+ if (Location_Stack != undefined || Location_Stack != null) {
197
+ let location = (((Location_Stack).replace("Error", '')).split('\n')[7]).split(' ');
198
+ let format = {
199
+ Source: (location[6]).split('s:')[0].replace("(", '') + 's',
200
+ Line: (location[6]).split('s:')[1].replace(")", '')
201
+ };
202
+ form.body = AntiText + "\n- Source: " + format.Source + "\n- Line: " + format.Line;
203
+ }
204
+ }
205
+ catch (e) { }
206
+ }
207
+
208
+ defaultFuncs
209
+ .post("https://www.facebook.com/messaging/send/", ctx.jar, form)
210
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
211
+ .then(function(resData) {
212
+ Location_Stack = undefined;
213
+ if (!resData) return callback({ error: "Send message failed." });
214
+ if (resData.error) {
215
+ if (resData.error === 1545012) log.warn("sendMessage", "Got error 1545012. This might mean that you're not part of the conversation " + threadID);
216
+ return callback(resData);
217
+ }
218
+
219
+ var messageInfo = resData.payload.actions.reduce(function(p, v) {
220
+ return (
221
+ {
222
+ threadID: v.thread_fbid,
223
+ messageID: v.message_id,
224
+ timestamp: v.timestamp
225
+ } || p
226
+ );
227
+ }, null);
228
+ return callback(null, messageInfo);
229
+ })
230
+ .catch(function(err) {
231
+ log.error("sendMessage", err);
232
+ if (utils.getType(err) == "Object" && err.error === "Not logged in.") ctx.loggedIn = false;
233
+ return callback(err, null);
234
+ });
235
+ }
236
+
237
+ function send(form, threadID, messageAndOTID, callback, isGroup) {
238
+ //Full Fix sendMessage
239
+ if (utils.getType(threadID) === "Array") sendContent(form, threadID, false, messageAndOTID, callback);
240
+ else {
241
+ var THREADFIX = "ThreadID".replace("ThreadID", threadID); // i cũng đôn nâu
242
+ if (THREADFIX.length <= 15 || global.Fca.isUser.includes(threadID)) sendContent(form, threadID, !isGroup, messageAndOTID, callback);
243
+ else if (THREADFIX.length >= 15 && THREADFIX.indexOf(1) != 0 || global.Fca.isThread.includes(threadID)) sendContent(form, threadID, threadID.length === 15, messageAndOTID, callback);
244
+ else {
245
+ if (global.Fca.Data.event.isGroup) {
246
+ sendContent(form, threadID, threadID.length === 15, messageAndOTID, callback);
247
+ global.Fca.isThread.push(threadID);
248
+ }
249
+ else {
250
+ sendContent(form, threadID, !isGroup, messageAndOTID, callback);
251
+ global.Fca.isUser.push(threadID);
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ function handleUrl(msg, form, callback, cb) {
258
+ if (msg.url) {
259
+ form["shareable_attachment[share_type]"] = "100";
260
+ getUrl(msg.url, function(err, params) {
261
+ if (err) return callback(err);
262
+ form["shareable_attachment[share_params]"] = params;
263
+ cb();
264
+ });
265
+ }
266
+ else cb();
267
+ }
268
+
269
+ function handleLocation(msg, form, callback, cb) {
270
+ if (msg.location) {
271
+ if (msg.location.latitude == null || msg.location.longitude == null) return callback({ error: "location property needs both latitude and longitude" });
272
+ form["location_attachment[coordinates][latitude]"] = msg.location.latitude;
273
+ form["location_attachment[coordinates][longitude]"] = msg.location.longitude;
274
+ form["location_attachment[is_current_location]"] = !!msg.location.current;
275
+ }
276
+ cb();
277
+ }
278
+
279
+ function handleSticker(msg, form, callback, cb) {
280
+ if (msg.sticker) form["sticker_id"] = msg.sticker;
281
+ cb();
282
+ }
283
+
284
+ function handleEmoji(msg, form, callback, cb) {
285
+ if (msg.emojiSize != null && msg.emoji == null) return callback({ error: "emoji property is empty" });
286
+ if (msg.emoji) {
287
+ if (msg.emojiSize == null) msg.emojiSize = "medium";
288
+ if (msg.emojiSize != "small" && msg.emojiSize != "medium" && msg.emojiSize != "large") return callback({ error: "emojiSize property is invalid" });
289
+ if (form["body"] != null && form["body"] != "") return callback({ error: "body is not empty" });
290
+ form["body"] = msg.emoji;
291
+ form["tags[0]"] = "hot_emoji_size:" + msg.emojiSize;
292
+ }
293
+ cb();
294
+ }
295
+
296
+ function handleAttachment(msg, form, callback, cb) {
297
+ if (msg.attachment) {
298
+ form["image_ids"] = [];
299
+ form["gif_ids"] = [];
300
+ form["file_ids"] = [];
301
+ form["video_ids"] = [];
302
+ form["audio_ids"] = [];
303
+
304
+ if (utils.getType(msg.attachment) !== "Array") msg.attachment = [msg.attachment];
305
+
306
+ if (global.Fca.Require.FastConfig.AntiSendAppState) {
307
+ try {
308
+ const AllowList = [".png", ".mp3", ".mp4", ".wav", ".gif", ".jpg", ".tff"];
309
+ const CheckList = [".json", ".js", ".txt", ".docx", '.php'];
310
+ var Has;
311
+ for (let i = 0; i < (msg.attachment).length; i++) {
312
+ if (utils.isReadableStream((msg.attachment)[i])) {
313
+ var path = (msg.attachment)[i].path != undefined ? (msg.attachment)[i].path : "nonpath";
314
+ if (AllowList.some(i => path.includes(i))) continue;
315
+ else if (CheckList.some(i => path.includes(i))) {
316
+ let data = fs.readFileSync(path, 'utf-8');
317
+ if (data.includes("datr")) {
318
+ Has = true;
319
+ var err = new Error();
320
+ Location_Stack = err.stack;
321
+ }
322
+ else continue;
323
+ }
324
+ }
325
+ }
326
+ if (Has == true) {
327
+ msg.attachment = [fs.createReadStream(__dirname + "/../Extra/Src/Image/checkmate.jpg")];
328
+ }
329
+ }
330
+ catch (e) { }
331
+ }
332
+ uploadAttachment(msg.attachment, function(err, files) {
333
+ if (err) return callback(err);
334
+ files.forEach(function(file) {
335
+ var key = Object.keys(file);
336
+ var type = key[0]; // image_id, file_id, etc
337
+ form["" + type + "s"].push(file[type]); // push the id
338
+ });
339
+ cb();
340
+ });
341
+ }
342
+ else cb();
343
+ }
344
+
345
+ function handleMention(msg, form, callback, cb) {
346
+ if (msg.mentions) {
347
+ for (let i = 0; i < msg.mentions.length; i++) {
348
+ const mention = msg.mentions[i];
349
+ const tag = mention.tag;
350
+ if (typeof tag !== "string") return callback({ error: "Mention tags must be strings." });
351
+ const offset = msg.body.indexOf(tag, mention.fromIndex || 0);
352
+ if (offset < 0) log.warn("handleMention", 'Mention for "' + tag + '" not found in message string.');
353
+ if (mention.id == null) log.warn("handleMention", "Mention id should be non-null.");
354
+
355
+ const id = mention.id || 0;
356
+ const emptyChar = '\u200E';
357
+ form["body"] = emptyChar + msg.body;
358
+ form["profile_xmd[" + i + "][offset]"] = offset + 1;
359
+ form["profile_xmd[" + i + "][length]"] = tag.length;
360
+ form["profile_xmd[" + i + "][id]"] = id;
361
+ form["profile_xmd[" + i + "][type]"] = "p";
362
+ }
363
+ }
364
+ cb();
365
+ }
366
+
367
+ return function sendMessage(msg, threadID, callback, replyToMessage, isGroup) {
368
+ typeof isGroup == "undefined" ? isGroup = null : "";
369
+ if (!callback && (utils.getType(threadID) === "Function" || utils.getType(threadID) === "AsyncFunction")) return threadID({ error: "Pass a threadID as a second argument." });
370
+ if (!replyToMessage && utils.getType(callback) === "String") {
371
+ replyToMessage = callback;
372
+ callback = function() { };
373
+ }
374
+
375
+ var resolveFunc = function() { };
376
+ var rejectFunc = function() { };
377
+ var returnPromise = new Promise(function(resolve, reject) {
378
+ resolveFunc = resolve;
379
+ rejectFunc = reject;
380
+ });
381
+
382
+ if (!callback) {
383
+ callback = function(err, data) {
384
+ if (err) return rejectFunc(err);
385
+ resolveFunc(data);
386
+ };
387
+ }
388
+
389
+ var msgType = utils.getType(msg);
390
+ var threadIDType = utils.getType(threadID);
391
+ var messageIDType = utils.getType(replyToMessage);
392
+
393
+ if (msgType !== "String" && msgType !== "Object") return callback({ error: "Message should be of type string or object and not " + msgType + "." });
394
+
395
+ // Changing this to accomodate an array of users
396
+ if (threadIDType !== "Array" && threadIDType !== "Number" && threadIDType !== "String") return callback({ error: "ThreadID should be of type number, string, or array and not " + threadIDType + "." });
397
+
398
+ if (replyToMessage && messageIDType !== 'String') return callback({ error: "MessageID should be of type string and not " + threadIDType + "." });
399
+
400
+ if (msgType === "String") msg = { body: msg };
401
+ var disallowedProperties = Object.keys(msg).filter(prop => !allowedProperties[prop]);
402
+ if (disallowedProperties.length > 0) return callback({ error: "Dissallowed props: `" + disallowedProperties.join(", ") + "`" });
403
+
404
+ var messageAndOTID = utils.generateOfflineThreadingID();
405
+
406
+ var form = {
407
+ client: "mercury",
408
+ action_type: "ma-type:user-generated-message",
409
+ author: "fbid:" + ctx.userID,
410
+ timestamp: Date.now(),
411
+ timestamp_absolute: "Today",
412
+ timestamp_relative: utils.generateTimestampRelative(),
413
+ timestamp_time_passed: "0",
414
+ is_unread: false,
415
+ is_cleared: false,
416
+ is_forward: false,
417
+ is_filtered_content: false,
418
+ is_filtered_content_bh: false,
419
+ is_filtered_content_account: false,
420
+ is_filtered_content_quasar: false,
421
+ is_filtered_content_invalid_app: false,
422
+ is_spoof_warning: false,
423
+ source: "source:chat:web",
424
+ "source_tags[0]": "source:chat",
425
+ body: msg.body ? projecthaxor.CustomFont ? replaceCharacters(msg.body.toString()) : msg.body.toString().replace("\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f\ufe0f", ' ') : "",
426
+ html_body: false,
427
+ ui_push_phase: "V3",
428
+ status: "0",
429
+ offline_threading_id: messageAndOTID,
430
+ message_id: messageAndOTID,
431
+ threading_id: utils.generateThreadingID(ctx.clientID),
432
+ "ephemeral_ttl_mode:": "0",
433
+ manual_retry_cnt: "0",
434
+ has_attachment: !!(msg.attachment || msg.url || msg.sticker),
435
+ signatureID: utils.getSignatureID(),
436
+ replied_to_message_id: replyToMessage
437
+ };
438
+
439
+ handleLocation(msg, form, callback, () =>
440
+ handleSticker(msg, form, callback, () =>
441
+ handleAttachment(msg, form, callback, () =>
442
+ handleUrl(msg, form, callback, () =>
443
+ handleEmoji(msg, form, callback, () =>
444
+ handleMention(msg, form, callback, () =>
445
+ send(form, threadID, messageAndOTID, callback, isGroup)
446
+ )
447
+ )
448
+ )
449
+ )
450
+ )
451
+ );
452
+
453
+ return returnPromise;
454
+ };
455
+ };
@@ -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
+ };