rapido-fca 0.0.10 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/index.js +4 -4
  3. package/package.json +15 -16
  4. package/readme.md +237 -39
  5. package/src/Screenshot.js +83 -0
  6. package/src/addExternalModule.js +19 -23
  7. package/src/addUserToGroup.js +99 -97
  8. package/src/changeAdminStatus.js +86 -62
  9. package/src/changeArchivedStatus.js +49 -49
  10. package/src/changeAvatar.js +118 -108
  11. package/src/changeBio.js +63 -64
  12. package/src/changeBlockedStatus.js +40 -38
  13. package/src/changeGroupImage.js +129 -126
  14. package/src/changeNickname.js +49 -49
  15. package/src/changeThreadColor.js +53 -53
  16. package/src/changeThreadEmoji.js +45 -45
  17. package/src/createNewGroup.js +74 -72
  18. package/src/createPoll.js +59 -59
  19. package/src/deleteMessage.js +50 -50
  20. package/src/deleteThread.js +50 -50
  21. package/src/editMessage.js +51 -49
  22. package/src/forwardAttachment.js +54 -54
  23. package/src/getCurrentUserID.js +3 -3
  24. package/src/getEmojiUrl.js +17 -17
  25. package/src/getFriendsList.js +67 -67
  26. package/src/getMessage.js +806 -767
  27. package/src/getThreadHistory.js +656 -642
  28. package/src/getThreadInfo.js +1 -1
  29. package/src/getThreadList.js +199 -227
  30. package/src/getThreadPictures.js +51 -71
  31. package/src/getUserID.js +53 -58
  32. package/src/getUserInfo.js +52 -60
  33. package/src/handleFriendRequest.js +41 -65
  34. package/src/handleMessageRequest.js +42 -60
  35. package/src/httpGet.js +49 -57
  36. package/src/httpPost.js +48 -57
  37. package/src/listenMqtt.js +827 -827
  38. package/src/listenMqtt.txt +827 -0
  39. package/src/logout.js +61 -61
  40. package/src/markAsDelivered.js +42 -53
  41. package/src/markAsRead.js +59 -69
  42. package/src/markAsReadAll.js +32 -42
  43. package/src/markAsSeen.js +43 -54
  44. package/src/muteThread.js +40 -47
  45. package/src/postFormData.txt +46 -0
  46. package/src/refreshFb_dtsg.js +77 -69
  47. package/src/removeUserFromGroup.js +67 -67
  48. package/src/resolvePhotoUrl.js +34 -34
  49. package/src/searchForThread.js +43 -43
  50. package/src/sendMessage.js +80 -228
  51. package/src/sendTypingIndicator.js +86 -88
  52. package/src/setPostReaction.js +90 -87
  53. package/src/setTitle.js +76 -72
  54. package/src/threadColors.js +121 -121
  55. package/src/unfriend.js +43 -43
  56. package/src/unsendMessage.js +34 -38
  57. package/src/uploadAttachment.js +80 -81
  58. package/src/httpPostFormData.js +0 -63
  59. package/src/setEmojiReaction.js +0 -59
  60. package/src/videoAttachment.js +0 -76
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
 
3
- const utils = require("../utils");
4
- const log = require("npmlog");
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+ var bluebird = require("bluebird");
5
6
 
6
- const allowedProperties = {
7
+ var allowedProperties = {
7
8
  attachment: true,
8
9
  url: true,
9
10
  sticker: true,
@@ -11,65 +12,27 @@ const allowedProperties = {
11
12
  emojiSize: true,
12
13
  body: true,
13
14
  mentions: true,
14
- location: true
15
+ location: true,
15
16
  };
16
17
 
17
- function removeSpecialChar(inputString) { // remove char banned by facebook
18
- if (typeof inputString !== "string")
19
- return inputString;
20
- // Convert string to Buffer
21
- const buffer = Buffer.from(inputString, 'utf8');
22
-
23
- // Filter buffer start with ef b8 8f
24
- let filteredBuffer = Buffer.alloc(0);
25
- for (let i = 0; i < buffer.length; i++) {
26
- if (buffer[i] === 0xEF && buffer[i + 1] === 0xB8 && buffer[i + 2] === 0x8F) {
27
- i += 2; // Skip 3 bytes of buffer starting with ef b8 8f
28
- } else {
29
- filteredBuffer = Buffer.concat([filteredBuffer, buffer.slice(i, i + 1)]);
30
- }
31
- }
32
-
33
- // Convert filtered buffer to string
34
- const convertedString = filteredBuffer.toString('utf8');
35
-
36
- return convertedString;
37
- }
38
-
39
18
  module.exports = function (defaultFuncs, api, ctx) {
40
19
  function uploadAttachment(attachments, callback) {
41
- const uploads = [];
20
+ var uploads = [];
42
21
 
43
22
  // create an array of promises
44
- for (let i = 0; i < attachments.length; i++) {
45
- if (!utils.isReadableStream(attachments[i])) {
46
- throw {
47
- error:
48
- "Attachment should be a readable stream and not " +
49
- utils.getType(attachments[i]) +
50
- "."
51
- };
52
- }
53
-
54
- const form = {
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 = {
55
26
  upload_1024: attachments[i],
56
27
  voice_clip: "true"
57
28
  };
58
29
 
59
30
  uploads.push(
60
31
  defaultFuncs
61
- .postFormData(
62
- "https://upload.facebook.com/ajax/mercury/upload.php",
63
- ctx.jar,
64
- form,
65
- {}
66
- )
32
+ .postFormData("https://upload.facebook.com/ajax/mercury/upload.php", ctx.jar, form, {}, {})
67
33
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
68
34
  .then(function (resData) {
69
- if (resData.error) {
70
- throw resData;
71
- }
72
-
35
+ if (resData.error) throw resData;
73
36
  // We have to return the data unformatted unless we want to change it
74
37
  // back in sendMessage.
75
38
  return resData.payload.metadata[0];
@@ -78,11 +41,9 @@ module.exports = function (defaultFuncs, api, ctx) {
78
41
  }
79
42
 
80
43
  // resolve all promises
81
- Promise
44
+ bluebird
82
45
  .all(uploads)
83
- .then(function (resData) {
84
- callback(null, resData);
85
- })
46
+ .then(resData => callback(null, resData))
86
47
  .catch(function (err) {
87
48
  log.error("uploadAttachment", err);
88
49
  return callback(err);
@@ -90,28 +51,18 @@ module.exports = function (defaultFuncs, api, ctx) {
90
51
  }
91
52
 
92
53
  function getUrl(url, callback) {
93
- const form = {
54
+ var form = {
94
55
  image_height: 960,
95
56
  image_width: 960,
96
57
  uri: url
97
58
  };
98
59
 
99
60
  defaultFuncs
100
- .post(
101
- "https://www.facebook.com/message_share_attachment/fromURI/",
102
- ctx.jar,
103
- form
104
- )
61
+ .post("https://www.facebook.com/message_share_attachment/fromURI/", ctx.jar, form)
105
62
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
106
63
  .then(function (resData) {
107
- if (resData.error) {
108
- return callback(resData);
109
- }
110
-
111
- if (!resData.payload) {
112
- return callback({ error: "Invalid url" });
113
- }
114
-
64
+ if (resData.error) return callback(resData);
65
+ if (!resData.payload) return callback({ error: "Invalid url" });
115
66
  callback(null, resData.payload.share_data.share_params);
116
67
  })
117
68
  .catch(function (err) {
@@ -127,51 +78,41 @@ module.exports = function (defaultFuncs, api, ctx) {
127
78
  // 2. User is sending a message to a specific user.
128
79
  // 3. No additional form params and the message goes to an existing group chat.
129
80
  if (utils.getType(threadID) === "Array") {
130
- for (let i = 0; i < threadID.length; i++) {
131
- form["specific_to_list[" + i + "]"] = "fbid:" + threadID[i];
132
- }
133
- form["specific_to_list[" + threadID.length + "]"] = "fbid:" + (ctx.i_userID || ctx.userID);
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;
134
83
  form["client_thread_id"] = "root:" + messageAndOTID;
135
84
  log.info("sendMessage", "Sending message to multiple users: " + threadID);
136
- } else {
85
+ }
86
+ else {
137
87
  // This means that threadID is the id of a user, and the chat
138
88
  // is a single person chat
139
89
  if (isSingleUser) {
140
90
  form["specific_to_list[0]"] = "fbid:" + threadID;
141
- form["specific_to_list[1]"] = "fbid:" + (ctx.i_userID || ctx.userID);
91
+ form["specific_to_list[1]"] = "fbid:" + ctx.userID;
142
92
  form["other_user_fbid"] = threadID;
143
- } else {
144
- form["thread_fbid"] = threadID;
145
93
  }
94
+ else form["thread_fbid"] = threadID;
146
95
  }
147
96
 
148
97
  if (ctx.globalOptions.pageID) {
149
98
  form["author"] = "fbid:" + ctx.globalOptions.pageID;
150
99
  form["specific_to_list[1]"] = "fbid:" + ctx.globalOptions.pageID;
151
- form["creator_info[creatorID]"] = ctx.i_userID || ctx.userID;
100
+ form["creator_info[creatorID]"] = ctx.userID;
152
101
  form["creator_info[creatorType]"] = "direct_admin";
153
102
  form["creator_info[labelType]"] = "sent_message";
154
103
  form["creator_info[pageID]"] = ctx.globalOptions.pageID;
155
104
  form["request_user_id"] = ctx.globalOptions.pageID;
156
- form["creator_info[profileURI]"] =
157
- "https://www.facebook.com/profile.php?id=" + (ctx.i_userID || ctx.userID);
105
+ form["creator_info[profileURI]"] = "https://www.facebook.com/profile.php?id=" + ctx.userID;
158
106
  }
159
107
 
160
108
  defaultFuncs
161
109
  .post("https://www.facebook.com/messaging/send/", ctx.jar, form)
162
110
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
163
111
  .then(function (resData) {
164
- if (!resData) {
165
- return callback({ error: "Send message failed." });
166
- }
167
-
112
+ if (!resData) return callback({ error: "Send message failed." });
168
113
  if (resData.error) {
169
114
  if (resData.error === 1545012) {
170
- log.warn(
171
- "sendMessage",
172
- "Got error 1545012. This might mean that you're not part of the conversation " +
173
- threadID
174
- );
115
+ log.warn("sendMessage", "Got error 1545012. This might mean that you're not part of the conversation " + threadID);
175
116
  }
176
117
  else {
177
118
  log.error("sendMessage", resData);
@@ -179,7 +120,7 @@ module.exports = function (defaultFuncs, api, ctx) {
179
120
  return callback(resData);
180
121
  }
181
122
 
182
- const messageInfo = resData.payload.actions.reduce(function (p, v) {
123
+ var messageInfo = resData.payload.actions.reduce(function (p, v) {
183
124
  return (
184
125
  {
185
126
  threadID: v.thread_fbid,
@@ -193,9 +134,7 @@ module.exports = function (defaultFuncs, api, ctx) {
193
134
  })
194
135
  .catch(function (err) {
195
136
  log.error("sendMessage", err);
196
- if (utils.getType(err) == "Object" && err.error === "Not logged in.") {
197
- ctx.loggedIn = false;
198
- }
137
+ if (utils.getType(err) == "Object" && err.error === "Not logged in.") ctx.loggedIn = false;
199
138
  return callback(err);
200
139
  });
201
140
  }
@@ -204,15 +143,10 @@ module.exports = function (defaultFuncs, api, ctx) {
204
143
  // We're doing a query to this to check if the given id is the id of
205
144
  // a user or of a group chat. The form will be different depending
206
145
  // on that.
207
- if (utils.getType(threadID) === "Array") {
208
- sendContent(form, threadID, false, messageAndOTID, callback);
209
- } else {
210
- if (utils.getType(isGroup) != "Boolean") {
211
- // Removed the use of api.getUserInfo() in the old version to reduce account lockout
212
- sendContent(form, threadID, threadID.toString().length < 16, messageAndOTID, callback);
213
- } else {
214
- sendContent(form, threadID, !isGroup, messageAndOTID, callback);
215
- }
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);
216
150
  }
217
151
  }
218
152
 
@@ -220,57 +154,35 @@ module.exports = function (defaultFuncs, api, ctx) {
220
154
  if (msg.url) {
221
155
  form["shareable_attachment[share_type]"] = "100";
222
156
  getUrl(msg.url, function (err, params) {
223
- if (err) {
224
- return callback(err);
225
- }
226
-
157
+ if (err) return callback(err);
227
158
  form["shareable_attachment[share_params]"] = params;
228
159
  cb();
229
160
  });
230
- } else {
231
- cb();
232
161
  }
162
+ else cb();
233
163
  }
234
164
 
235
165
  function handleLocation(msg, form, callback, cb) {
236
166
  if (msg.location) {
237
- if (msg.location.latitude == null || msg.location.longitude == null) {
238
- return callback({ error: "location property needs both latitude and longitude" });
239
- }
240
-
167
+ if (msg.location.latitude == null || msg.location.longitude == null) return callback({ error: "location property needs both latitude and longitude" });
241
168
  form["location_attachment[coordinates][latitude]"] = msg.location.latitude;
242
169
  form["location_attachment[coordinates][longitude]"] = msg.location.longitude;
243
170
  form["location_attachment[is_current_location]"] = !!msg.location.current;
244
171
  }
245
-
246
172
  cb();
247
173
  }
248
174
 
249
175
  function handleSticker(msg, form, callback, cb) {
250
- if (msg.sticker) {
251
- form["sticker_id"] = msg.sticker;
252
- }
176
+ if (msg.sticker) form["sticker_id"] = msg.sticker;
253
177
  cb();
254
178
  }
255
179
 
256
180
  function handleEmoji(msg, form, callback, cb) {
257
- if (msg.emojiSize != null && msg.emoji == null) {
258
- return callback({ error: "emoji property is empty" });
259
- }
181
+ if (msg.emojiSize != null && msg.emoji == null) return callback({ error: "emoji property is empty" });
260
182
  if (msg.emoji) {
261
- if (msg.emojiSize == null) {
262
- msg.emojiSize = "medium";
263
- }
264
- if (
265
- msg.emojiSize != "small" &&
266
- msg.emojiSize != "medium" &&
267
- msg.emojiSize != "large"
268
- ) {
269
- return callback({ error: "emojiSize property is invalid" });
270
- }
271
- if (form["body"] != null && form["body"] != "") {
272
- return callback({ error: "body is not empty" });
273
- }
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" });
274
186
  form["body"] = msg.emoji;
275
187
  form["tags[0]"] = "hot_emoji_size:" + msg.emojiSize;
276
188
  }
@@ -285,52 +197,39 @@ module.exports = function (defaultFuncs, api, ctx) {
285
197
  form["video_ids"] = [];
286
198
  form["audio_ids"] = [];
287
199
 
288
- if (utils.getType(msg.attachment) !== "Array") {
289
- msg.attachment = [msg.attachment];
290
- }
291
-
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
+ }
292
206
  uploadAttachment(msg.attachment, function (err, files) {
293
- if (err) {
294
- return callback(err);
295
- }
296
-
207
+ if (err) return callback(err);
297
208
  files.forEach(function (file) {
298
- const key = Object.keys(file);
299
- const type = key[0]; // image_id, file_id, etc
209
+ var key = Object.keys(file);
210
+ var type = key[0]; // image_id, file_id, etc
300
211
  form["" + type + "s"].push(file[type]); // push the id
301
212
  });
302
213
  cb();
303
214
  });
304
- } else {
305
- cb();
306
215
  }
216
+ else cb();
307
217
  }
308
218
 
309
219
  function handleMention(msg, form, callback, cb) {
310
220
  if (msg.mentions) {
311
221
  for (let i = 0; i < msg.mentions.length; i++) {
312
222
  const mention = msg.mentions[i];
313
-
314
223
  const tag = mention.tag;
315
- if (typeof tag !== "string") {
316
- return callback({ error: "Mention tags must be strings." });
317
- }
318
-
224
+ if (typeof tag !== "string") return callback({ error: "Mention tags must be strings." });
319
225
  const offset = msg.body.indexOf(tag, mention.fromIndex || 0);
320
-
321
- if (offset < 0) {
322
- log.warn(
323
- "handleMention",
324
- 'Mention for "' + tag + '" not found in message string.'
325
- );
326
- }
327
-
328
- if (mention.id == null) {
329
- log.warn("handleMention", "Mention id should be non-null.");
330
- }
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.");
331
228
 
332
229
  const id = mention.id || 0;
333
- form["profile_xmd[" + i + "][offset]"] = offset;
230
+ const emptyChar = '\u200E';
231
+ form["body"] = emptyChar + msg.body;
232
+ form["profile_xmd[" + i + "][offset]"] = offset + 1;
334
233
  form["profile_xmd[" + i + "][length]"] = tag.length;
335
234
  form["profile_xmd[" + i + "][id]"] = id;
336
235
  form["profile_xmd[" + i + "][type]"] = "p";
@@ -341,94 +240,47 @@ module.exports = function (defaultFuncs, api, ctx) {
341
240
 
342
241
  return function sendMessage(msg, threadID, callback, replyToMessage, isGroup) {
343
242
  typeof isGroup == "undefined" ? isGroup = null : "";
344
- if (
345
- !callback &&
346
- (utils.getType(threadID) === "Function" ||
347
- utils.getType(threadID) === "AsyncFunction")
348
- ) {
349
- return threadID({ error: "Pass a threadID as a second argument." });
350
- }
351
- if (
352
- !replyToMessage &&
353
- utils.getType(callback) === "String"
354
- ) {
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") {
355
245
  replyToMessage = callback;
356
246
  callback = function () { };
357
247
  }
358
248
 
359
- let resolveFunc = function () { };
360
- let rejectFunc = function () { };
361
- const returnPromise = new Promise(function (resolve, reject) {
249
+ var resolveFunc = function () { };
250
+ var rejectFunc = function () { };
251
+ var returnPromise = new Promise(function (resolve, reject) {
362
252
  resolveFunc = resolve;
363
253
  rejectFunc = reject;
364
254
  });
365
255
 
366
256
  if (!callback) {
367
- callback = function (err, friendList) {
368
- if (err) {
369
- return rejectFunc(err);
370
- }
371
- resolveFunc(friendList);
257
+ callback = function (err, data) {
258
+ if (err) return rejectFunc(err);
259
+ resolveFunc(data);
372
260
  };
373
261
  }
374
262
 
375
- const msgType = utils.getType(msg);
376
- const threadIDType = utils.getType(threadID);
377
- const messageIDType = utils.getType(replyToMessage);
263
+ var msgType = utils.getType(msg);
264
+ var threadIDType = utils.getType(threadID);
265
+ var messageIDType = utils.getType(replyToMessage);
378
266
 
379
- if (msgType !== "String" && msgType !== "Object") {
380
- return callback({
381
- error:
382
- "Message should be of type string or object and not " + msgType + "."
383
- });
384
- }
267
+ if (msgType !== "String" && msgType !== "Object") return callback({ error: "Message should be of type string or object and not " + msgType + "." });
385
268
 
386
269
  // Changing this to accomodate an array of users
387
- if (
388
- threadIDType !== "Array" &&
389
- threadIDType !== "Number" &&
390
- threadIDType !== "String"
391
- ) {
392
- return callback({
393
- error:
394
- "ThreadID should be of type number, string, or array and not " +
395
- threadIDType +
396
- "."
397
- });
398
- }
399
-
400
- if (replyToMessage && messageIDType !== 'String') {
401
- return callback({
402
- error:
403
- "MessageID should be of type string and not " +
404
- threadIDType +
405
- "."
406
- });
407
- }
408
-
409
- if (msgType === "String") {
410
- msg = { body: msg };
411
- }
412
-
413
- if (utils.getType(msg.body) === "String") {
414
- msg.body = removeSpecialChar(msg.body);
415
- }
270
+ if (threadIDType !== "Array" && threadIDType !== "Number" && threadIDType !== "String") return callback({ error: "ThreadID should be of type number, string, or array and not " + threadIDType + "." });
416
271
 
417
- const disallowedProperties = Object.keys(msg).filter(
418
- prop => !allowedProperties[prop]
419
- );
420
- if (disallowedProperties.length > 0) {
421
- return callback({
422
- error: "Dissallowed props: `" + disallowedProperties.join(", ") + "`"
423
- });
424
- }
272
+ if (replyToMessage && messageIDType !== 'String') return callback({ error: "MessageID should be of type string and not " + threadIDType + "." });
425
273
 
426
- const messageAndOTID = utils.generateOfflineThreadingID();
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(", ") + "`" });
427
277
 
428
- const form = {
278
+ var messageAndOTID = utils.generateOfflineThreadingID();
279
+ // console.log(messageAndOTID)
280
+ var form = {
429
281
  client: "mercury",
430
282
  action_type: "ma-type:user-generated-message",
431
- author: "fbid:" + (ctx.i_userID || ctx.userID),
283
+ author: "fbid:" + ctx.userID,
432
284
  timestamp: Date.now(),
433
285
  timestamp_absolute: "Today",
434
286
  timestamp_relative: utils.generateTimestampRelative(),
@@ -457,6 +309,7 @@ module.exports = function (defaultFuncs, api, ctx) {
457
309
  signatureID: utils.getSignatureID(),
458
310
  replied_to_message_id: replyToMessage
459
311
  };
312
+ // console.log(form)
460
313
 
461
314
  handleLocation(msg, form, callback, () =>
462
315
  handleSticker(msg, form, callback, () =>
@@ -471,7 +324,6 @@ module.exports = function (defaultFuncs, api, ctx) {
471
324
  )
472
325
  )
473
326
  );
474
-
475
327
  return returnPromise;
476
328
  };
477
- };
329
+ };