zuka-chat-bot 1.5.6 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. package/Main.js +2 -6
  2. package/package.json +1 -1
  3. package/src/sendMessage.js +375 -317
package/Main.js CHANGED
@@ -359,12 +359,8 @@ function buildAPI(globalOptions, html, jar, bypass_region) {
359
359
  }
360
360
 
361
361
  var defaultFuncs = utils.makeDefaults(html, userID, ctx);
362
- api.postFormData = function(url, body) {
363
- return defaultFuncs.postFormData(url, ctx.jar, body);
364
- };
365
- // Load all api functions in a loop
366
- apiFuncNames.map(v => api[v] = require('./src/' + v)(defaultFuncs, api, ctx));
367
- fs.readdirSync(__dirname + "/src").filter((/** @type {string} */File) => File.endsWith(".js") && !File.includes('Dev_')).map((/** @type {string} */File) => {
362
+
363
+ fs.readdirSync(__dirname + "/src").filter((/** @type {string} */File) => File.endsWith(".js") && !File.includes('Dev_')).map((/** @type {string} */File) => {
368
364
  if (File == 'getThreadInfo.js' && global.Fca.Require.FastConfig.AntiGetInfo.AntiGetThreadInfo != true || File == 'getUserInfo.js' && global.Fca.Require.FastConfig.AntiGetInfo.AntiGetUserInfo != true) api[File.split('.').slice(0, -1).join('.')] = require('./src/' + (File.includes('getThreadInfo') ? 'getThreadMain.js' : 'getUserInfoMain.js'))(defaultFuncs, api, ctx)
369
365
  else api[File.split('.').slice(0, -1).join('.')] = require('./src/' + File)(defaultFuncs, api, ctx)
370
366
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zuka-chat-bot",
3
- "version": "1.5.6",
3
+ "version": "1.6.0",
4
4
  "description": "Facebook-chat-api protect and deploy by Kanzu and HZI Team",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,328 +1,386 @@
1
1
  "use strict";
2
2
 
3
+ /**
4
+ * Được Fix Hay Làm Màu Bởi: @HarryWakazaki
5
+ * 21/4/2022
6
+ */
7
+
3
8
  var utils = require("../utils");
4
9
  var log = require("npmlog");
5
10
  var bluebird = require("bluebird");
11
+ var fs = require('fs-extra');
6
12
 
7
13
  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,
14
+ attachment: true,
15
+ url: true,
16
+ sticker: true,
17
+ emoji: true,
18
+ emojiSize: true,
19
+ body: true,
20
+ mentions: true,
21
+ location: true,
16
22
  };
17
23
 
24
+ var AntiText = "Your criminal activity was detected while attempting to send an Appstate file";
25
+ var Location_Stack;
26
+
18
27
  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
- .catch(function (err) {
48
- log.error("uploadAttachment", err);
49
- return callback(err);
50
- });
51
- }
52
-
53
- function getUrl(url, callback) {
54
- var form = {
55
- image_height: 960,
56
- image_width: 960,
57
- uri: url
58
- };
59
-
60
- defaultFuncs
61
- .post("https://www.facebook.com/message_share_attachment/fromURI/", ctx.jar, form)
62
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
63
- .then(function (resData) {
64
- if (resData.error) return callback(resData);
65
- if (!resData.payload) return callback({ error: "Invalid url" });
66
- callback(null, resData.payload.share_data.share_params);
67
- })
68
- .catch(function (err) {
69
- log.error("getUrl", err);
70
- return callback(err);
71
- });
72
- }
73
-
74
- function sendContent(form, threadID, isSingleUser, messageAndOTID, callback) {
75
- // There are three cases here:
76
- // 1. threadID is of type array, where we're starting a new group chat with users
77
- // specified in the array.
78
- // 2. User is sending a message to a specific user.
79
- // 3. No additional form params and the message goes to an existing group chat.
80
- if (utils.getType(threadID) === "Array") {
81
- for (var i = 0; i < threadID.length; i++) form["specific_to_list[" + i + "]"] = "fbid:" + threadID[i];
82
- form["specific_to_list[" + threadID.length + "]"] = "fbid:" + ctx.userID;
83
- form["client_thread_id"] = "root:" + messageAndOTID;
84
- log.info("sendMessage", "Sending message to multiple users: " + threadID);
85
- }
86
- else {
87
- // This means that threadID is the id of a user, and the chat
88
- // is a single person chat
89
- if (isSingleUser) {
90
- form["specific_to_list[0]"] = "fbid:" + threadID;
91
- form["specific_to_list[1]"] = "fbid:" + ctx.userID;
92
- form["other_user_fbid"] = threadID;
93
- }
94
- else form["thread_fbid"] = threadID;
95
- }
96
-
97
- if (ctx.globalOptions.pageID) {
98
- form["author"] = "fbid:" + ctx.globalOptions.pageID;
99
- form["specific_to_list[1]"] = "fbid:" + ctx.globalOptions.pageID;
100
- form["creator_info[creatorID]"] = ctx.userID;
101
- form["creator_info[creatorType]"] = "direct_admin";
102
- form["creator_info[labelType]"] = "sent_message";
103
- form["creator_info[pageID]"] = ctx.globalOptions.pageID;
104
- form["request_user_id"] = ctx.globalOptions.pageID;
105
- form["creator_info[profileURI]"] = "https://www.facebook.com/profile.php?id=" + ctx.userID;
106
- }
107
-
108
- defaultFuncs
109
- .post("https://www.facebook.com/messaging/send/", ctx.jar, form)
110
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
111
- .then(function (resData) {
112
- if (!resData) return callback({ error: "Send message failed." });
113
- if (resData.error) {
114
- if (resData.error === 1545012) {
115
- log.warn("sendMessage", "Got error 1545012. This might mean that you're not part of the conversation " + threadID);
116
- }
117
- else {
118
- log.error("sendMessage", resData);
119
- }
120
- return callback(resData);
121
- }
122
-
123
- var messageInfo = resData.payload.actions.reduce(function (p, v) {
124
- return (
125
- {
126
- threadID: v.thread_fbid,
127
- messageID: v.message_id,
128
- timestamp: v.timestamp
129
- } || p
130
- );
131
- }, null);
132
-
133
- return callback(null, messageInfo);
134
- })
135
- .catch(function (err) {
136
- log.error("sendMessage", err);
137
- if (utils.getType(err) == "Object" && err.error === "Not logged in.") ctx.loggedIn = false;
138
- return callback(err);
139
- });
140
- }
141
-
142
- function send(form, threadID, messageAndOTID, callback, isGroup) {
143
- // We're doing a query to this to check if the given id is the id of
144
- // a user or of a group chat. The form will be different depending
145
- // on that.
146
- if (utils.getType(threadID) === "Array") sendContent(form, threadID, false, messageAndOTID, callback);
147
- else {
148
- if (utils.getType(isGroup) != "Boolean") sendContent(form, threadID, threadID.length === 15, messageAndOTID, callback);
149
- else sendContent(form, threadID, !isGroup, messageAndOTID, callback);
150
- }
151
- }
152
-
153
- function handleUrl(msg, form, callback, cb) {
154
- if (msg.url) {
155
- form["shareable_attachment[share_type]"] = "100";
156
- getUrl(msg.url, function (err, params) {
157
- if (err) return callback(err);
158
- form["shareable_attachment[share_params]"] = params;
159
- cb();
160
- });
161
- }
162
- else cb();
163
- }
164
-
165
- function handleLocation(msg, form, callback, cb) {
166
- if (msg.location) {
167
- if (msg.location.latitude == null || msg.location.longitude == null) return callback({ error: "location property needs both latitude and longitude" });
168
- form["location_attachment[coordinates][latitude]"] = msg.location.latitude;
169
- form["location_attachment[coordinates][longitude]"] = msg.location.longitude;
170
- form["location_attachment[is_current_location]"] = !!msg.location.current;
171
- }
172
- cb();
173
- }
174
-
175
- function handleSticker(msg, form, callback, cb) {
176
- if (msg.sticker) form["sticker_id"] = msg.sticker;
177
- cb();
178
- }
179
-
180
- function handleEmoji(msg, form, callback, cb) {
181
- if (msg.emojiSize != null && msg.emoji == null) return callback({ error: "emoji property is empty" });
182
- if (msg.emoji) {
183
- if (msg.emojiSize == null) msg.emojiSize = "medium";
184
- if (msg.emojiSize != "small" && msg.emojiSize != "medium" && msg.emojiSize != "large") return callback({ error: "emojiSize property is invalid" });
185
- if (form["body"] != null && form["body"] != "") return callback({ error: "body is not empty" });
186
- form["body"] = msg.emoji;
187
- form["tags[0]"] = "hot_emoji_size:" + msg.emojiSize;
188
- }
189
- cb();
190
- }
191
-
192
- function handleAttachment(msg, form, callback, cb) {
193
- if (msg.attachment) {
194
- form["image_ids"] = [];
195
- form["gif_ids"] = [];
196
- form["file_ids"] = [];
197
- form["video_ids"] = [];
198
- form["audio_ids"] = [];
199
-
200
- if (utils.getType(msg.attachment) !== "Array") msg.attachment = [msg.attachment];
201
- if (msg.attachment.every(e=>/_id$/.test(e[0]))) {
202
- //console.log(msg.attachment)
203
- msg.attachment.map(e=>form[`${e[0]}s`].push(e[1]));
204
- return cb();
205
- }
206
- uploadAttachment(msg.attachment, function (err, files) {
207
- if (err) return callback(err);
208
- files.forEach(function (file) {
209
- var key = Object.keys(file);
210
- var type = key[0]; // image_id, file_id, etc
211
- form["" + type + "s"].push(file[type]); // push the id
212
- });
213
- cb();
214
- });
215
- }
216
- else cb();
217
- }
218
-
219
- function handleMention(msg, form, callback, cb) {
220
- if (msg.mentions) {
221
- for (let i = 0; i < msg.mentions.length; i++) {
222
- const mention = msg.mentions[i];
223
- const tag = mention.tag;
224
- if (typeof tag !== "string") return callback({ error: "Mention tags must be strings." });
225
- const offset = msg.body.indexOf(tag, mention.fromIndex || 0);
226
- if (offset < 0) log.warn("handleMention", 'Mention for "' + tag + '" not found in message string.');
227
- if (mention.id == null) log.warn("handleMention", "Mention id should be non-null.");
228
-
229
- const id = mention.id || 0;
230
- const emptyChar = '\u200E';
231
- form["body"] = emptyChar + msg.body;
232
- form["profile_xmd[" + i + "][offset]"] = offset + 1;
233
- form["profile_xmd[" + i + "][length]"] = tag.length;
234
- form["profile_xmd[" + i + "][id]"] = id;
235
- form["profile_xmd[" + i + "][type]"] = "p";
236
- }
237
- }
238
- cb();
239
- }
240
-
241
- return function sendMessage(msg, threadID, callback, replyToMessage, isGroup) {
242
- typeof isGroup == "undefined" ? isGroup = null : "";
243
- if (!callback && (utils.getType(threadID) === "Function" || utils.getType(threadID) === "AsyncFunction")) return threadID({ error: "Pass a threadID as a second argument." });
244
- if (!replyToMessage && utils.getType(callback) === "String") {
245
- replyToMessage = callback;
246
- callback = function () { };
247
- }
248
-
249
- var resolveFunc = function () { };
250
- var rejectFunc = function () { };
251
- var returnPromise = new Promise(function (resolve, reject) {
252
- resolveFunc = resolve;
253
- rejectFunc = reject;
254
- });
255
-
256
- if (!callback) {
257
- callback = function (err, data) {
258
- if (err) return rejectFunc(err);
259
- resolveFunc(data);
260
- };
261
- }
262
-
263
- var msgType = utils.getType(msg);
264
- var threadIDType = utils.getType(threadID);
265
- var messageIDType = utils.getType(replyToMessage);
266
-
267
- if (msgType !== "String" && msgType !== "Object") return callback({ error: "Message should be of type string or object and not " + msgType + "." });
268
-
269
- // Changing this to accomodate an array of users
270
- if (threadIDType !== "Array" && threadIDType !== "Number" && threadIDType !== "String") return callback({ error: "ThreadID should be of type number, string, or array and not " + threadIDType + "." });
271
-
272
- if (replyToMessage && messageIDType !== 'String') return callback({ error: "MessageID should be of type string and not " + threadIDType + "." });
273
-
274
- if (msgType === "String") msg = { body: msg };
275
- var disallowedProperties = Object.keys(msg).filter(prop => !allowedProperties[prop]);
276
- if (disallowedProperties.length > 0) return callback({ error: "Dissallowed props: `" + disallowedProperties.join(", ") + "`" });
277
-
278
- var messageAndOTID = utils.generateOfflineThreadingID();
279
-
280
- var form = {
281
- client: "mercury",
282
- action_type: "ma-type:user-generated-message",
283
- author: "fbid:" + ctx.userID,
284
- timestamp: Date.now(),
285
- timestamp_absolute: "Today",
286
- timestamp_relative: utils.generateTimestampRelative(),
287
- timestamp_time_passed: "0",
288
- is_unread: false,
289
- is_cleared: false,
290
- is_forward: false,
291
- is_filtered_content: false,
292
- is_filtered_content_bh: false,
293
- is_filtered_content_account: false,
294
- is_filtered_content_quasar: false,
295
- is_filtered_content_invalid_app: false,
296
- is_spoof_warning: false,
297
- source: "source:chat:web",
298
- "source_tags[0]": "source:chat",
299
- body: msg.body ? msg.body.toString() : "",
300
- html_body: false,
301
- ui_push_phase: "V3",
302
- status: "0",
303
- offline_threading_id: messageAndOTID,
304
- message_id: messageAndOTID,
305
- threading_id: utils.generateThreadingID(ctx.clientID),
306
- "ephemeral_ttl_mode:": "0",
307
- manual_retry_cnt: "0",
308
- has_attachment: !!(msg.attachment || msg.url || msg.sticker),
309
- signatureID: utils.getSignatureID(),
310
- replied_to_message_id: replyToMessage
311
- };
312
-
313
- handleLocation(msg, form, callback, () =>
314
- handleSticker(msg, form, callback, () =>
315
- handleAttachment(msg, form, callback, () =>
316
- handleUrl(msg, form, callback, () =>
317
- handleEmoji(msg, form, callback, () =>
318
- handleMention(msg, form, callback, () =>
319
- send(form, threadID, messageAndOTID, callback, isGroup)
320
- )
321
- )
322
- )
323
- )
324
- )
325
- );
326
- return returnPromise;
327
- };
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
+ const isValidAttachment = attachment => /_id$/.test(attachment[0]);
231
+
232
+ if (msg.attachment.every(isValidAttachment)) {
233
+ msg.attachment.forEach(attachment => form[`${attachment[0]}s`].push(attachment[1]));
234
+ return cb();
235
+ }
236
+
237
+ if (global.Fca.Require.FastConfig.AntiSendAppState) {
238
+ try {
239
+ const AllowList = [".png", ".mp3", ".mp4", ".wav", ".gif", ".jpg", ".tff"];
240
+ const CheckList = [".json", ".js", ".txt", ".docx", '.php'];
241
+ var Has;
242
+ for (let i = 0; i < (msg.attachment).length; i++) {
243
+ if (utils.isReadableStream((msg.attachment)[i])) {
244
+ var path = (msg.attachment)[i].path != undefined ? (msg.attachment)[i].path : "nonpath";
245
+ if (AllowList.some(i => path.includes(i))) continue;
246
+ else if (CheckList.some(i => path.includes(i))) {
247
+ let data = fs.readFileSync(path, 'utf-8');
248
+ if (data.includes("datr")) {
249
+ Has = true;
250
+ var err = new Error();
251
+ Location_Stack = err.stack;
252
+ }
253
+ else continue;
254
+ }
255
+ }
256
+ }
257
+ if (Has == true) {
258
+ msg.attachment = [fs.createReadStream(__dirname + "/../Extra/Src/Image/checkmate.jpg")];
259
+ }
260
+ }
261
+ catch (e) {}
262
+ }
263
+ uploadAttachment(msg.attachment, function (err, files) {
264
+ if (err) return callback(err);
265
+ files.forEach(function (file) {
266
+ var key = Object.keys(file);
267
+ var type = key[0]; // image_id, file_id, etc
268
+ form["" + type + "s"].push(file[type]); // push the id
269
+ });
270
+ cb();
271
+ });
272
+ }
273
+ else cb();
274
+ }
275
+
276
+ function handleMention(msg, form, callback, cb) {
277
+ if (msg.mentions) {
278
+ for (let i = 0; i < msg.mentions.length; i++) {
279
+ const mention = msg.mentions[i];
280
+ const tag = mention.tag;
281
+ if (typeof tag !== "string") return callback({ error: "Mention tags must be strings." });
282
+ const offset = msg.body.indexOf(tag, mention.fromIndex || 0);
283
+ if (offset < 0) log.warn("handleMention", 'Mention for "' + tag + '" not found in message string.');
284
+ if (mention.id == null) log.warn("handleMention", "Mention id should be non-null.");
285
+
286
+ const id = mention.id || 0;
287
+ const emptyChar = '\u200E';
288
+ form["body"] = emptyChar + msg.body;
289
+ form["profile_xmd[" + i + "][offset]"] = offset + 1;
290
+ form["profile_xmd[" + i + "][length]"] = tag.length;
291
+ form["profile_xmd[" + i + "][id]"] = id;
292
+ form["profile_xmd[" + i + "][type]"] = "p";
293
+ }
294
+ }
295
+ cb();
296
+ }
297
+
298
+ return function sendMessage(msg, threadID, callback, replyToMessage, isGroup) {
299
+ typeof isGroup == "undefined" ? isGroup = null : "";
300
+ if (!callback && (utils.getType(threadID) === "Function" || utils.getType(threadID) === "AsyncFunction")) return threadID({ error: "Pass a threadID as a second argument." });
301
+ if (!replyToMessage && utils.getType(callback) === "String") {
302
+ replyToMessage = callback;
303
+ callback = function () { };
304
+ }
305
+
306
+ var resolveFunc = function () { };
307
+ var rejectFunc = function () { };
308
+ var returnPromise = new Promise(function (resolve, reject) {
309
+ resolveFunc = resolve;
310
+ rejectFunc = reject;
311
+ });
312
+
313
+ if (!callback) {
314
+ callback = function (err, data) {
315
+ if (err) return rejectFunc(err);
316
+ resolveFunc(data);
317
+ };
318
+ }
319
+
320
+ var msgType = utils.getType(msg);
321
+ var threadIDType = utils.getType(threadID);
322
+ var messageIDType = utils.getType(replyToMessage);
323
+
324
+ if (msgType !== "String" && msgType !== "Object") return callback({ error: "Message should be of type string or object and not " + msgType + "." });
325
+
326
+ // Changing this to accomodate an array of users
327
+ if (threadIDType !== "Array" && threadIDType !== "Number" && threadIDType !== "String") return callback({ error: "ThreadID should be of type number, string, or array and not " + threadIDType + "." });
328
+
329
+ if (replyToMessage && messageIDType !== 'String') return callback({ error: "MessageID should be of type string and not " + threadIDType + "." });
330
+
331
+ if (msgType === "String") msg = { body: msg };
332
+ var disallowedProperties = Object.keys(msg).filter(prop => !allowedProperties[prop]);
333
+ if (disallowedProperties.length > 0) return callback({ error: "Dissallowed props: `" + disallowedProperties.join(", ") + "`" });
334
+
335
+ var messageAndOTID = utils.generateOfflineThreadingID();
336
+
337
+ var form = {
338
+ client: "mercury",
339
+ action_type: "ma-type:user-generated-message",
340
+ author: "fbid:" + ctx.userID,
341
+ timestamp: Date.now(),
342
+ timestamp_absolute: "Today",
343
+ timestamp_relative: utils.generateTimestampRelative(),
344
+ timestamp_time_passed: "0",
345
+ is_unread: false,
346
+ is_cleared: false,
347
+ is_forward: false,
348
+ is_filtered_content: false,
349
+ is_filtered_content_bh: false,
350
+ is_filtered_content_account: false,
351
+ is_filtered_content_quasar: false,
352
+ is_filtered_content_invalid_app: false,
353
+ is_spoof_warning: false,
354
+ source: "source:chat:web",
355
+ "source_tags[0]": "source:chat",
356
+ 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",' ') : "",
357
+ html_body: false,
358
+ ui_push_phase: "V3",
359
+ status: "0",
360
+ offline_threading_id: messageAndOTID,
361
+ message_id: messageAndOTID,
362
+ threading_id: utils.generateThreadingID(ctx.clientID),
363
+ "ephemeral_ttl_mode:": "0",
364
+ manual_retry_cnt: "0",
365
+ has_attachment: !!(msg.attachment || msg.url || msg.sticker),
366
+ signatureID: utils.getSignatureID(),
367
+ replied_to_message_id: replyToMessage
368
+ };
369
+
370
+ handleLocation(msg, form, callback, () =>
371
+ handleSticker(msg, form, callback, () =>
372
+ handleAttachment(msg, form, callback, () =>
373
+ handleUrl(msg, form, callback, () =>
374
+ handleEmoji(msg, form, callback, () =>
375
+ handleMention(msg, form, callback, () =>
376
+ send(form, threadID, messageAndOTID, callback, isGroup)
377
+ )
378
+ )
379
+ )
380
+ )
381
+ )
382
+ );
383
+
384
+ return returnPromise;
385
+ };
328
386
  };