fca-project-orion 1.1.3 → 1.1.4

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