alicezetion 1.0.9 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -1
  2. package/.cache/replit/nix/env.json +1 -1
  3. package/index.js +558 -490
  4. package/leiamnash/addExternalModule.js +19 -0
  5. package/{src → leiamnash}/addUserToGroup.js +52 -16
  6. package/leiamnash/changeAdminStatus.js +79 -0
  7. package/leiamnash/changeArchivedStatus.js +55 -0
  8. package/{src → leiamnash}/changeBio.js +19 -6
  9. package/{src → leiamnash}/changeBlockedStatus.js +14 -3
  10. package/{src → leiamnash}/changeGroupImage.js +40 -16
  11. package/leiamnash/changeNickname.js +59 -0
  12. package/{src → leiamnash}/changeThreadColor.js +20 -10
  13. package/leiamnash/changeThreadEmoji.js +55 -0
  14. package/leiamnash/chat.js +459 -0
  15. package/{src → leiamnash}/createNewGroup.js +28 -12
  16. package/{src → leiamnash}/createPoll.js +25 -13
  17. package/leiamnash/deleteMessage.js +56 -0
  18. package/leiamnash/deleteThread.js +56 -0
  19. package/leiamnash/forwardAttachment.js +60 -0
  20. package/{src → leiamnash}/getCurrentUserID.js +1 -1
  21. package/{src → leiamnash}/getEmojiUrl.js +4 -2
  22. package/{src → leiamnash}/getFriendsList.js +21 -10
  23. package/{src → leiamnash}/getThreadHistory.js +166 -58
  24. package/{src → leiamnash}/getThreadHistoryDeprecated.js +42 -20
  25. package/{src → leiamnash}/getThreadInfo.js +60 -25
  26. package/leiamnash/getThreadInfoDeprecated.js +80 -0
  27. package/{src → leiamnash}/getThreadList.js +66 -41
  28. package/leiamnash/getThreadListDeprecated.js +75 -0
  29. package/leiamnash/getThreadPictures.js +79 -0
  30. package/{src → leiamnash}/getUserID.js +14 -9
  31. package/{src → leiamnash}/getUserInfo.js +18 -12
  32. package/leiamnash/handleFriendRequest.js +61 -0
  33. package/leiamnash/handleMessageRequest.js +65 -0
  34. package/{src → leiamnash}/httpGet.js +17 -12
  35. package/{src → leiamnash}/httpPost.js +17 -12
  36. package/leiamnash/listenMqtt.js +687 -0
  37. package/{src → leiamnash}/logout.js +20 -13
  38. package/{src → leiamnash}/markAsDelivered.js +22 -11
  39. package/{src → leiamnash}/markAsRead.js +21 -11
  40. package/{src → leiamnash}/markAsReadAll.js +20 -10
  41. package/{src → leiamnash}/markAsSeen.js +18 -7
  42. package/{src → leiamnash}/muteThread.js +18 -11
  43. package/leiamnash/removeUserFromGroup.js +79 -0
  44. package/{src → leiamnash}/resolvePhotoUrl.js +17 -8
  45. package/{src → leiamnash}/searchForThread.js +21 -10
  46. package/{src → leiamnash}/sendTypingIndicator.js +47 -14
  47. package/{src → leiamnash}/setMessageReaction.js +26 -12
  48. package/{src → leiamnash}/setPostReaction.js +26 -13
  49. package/{src → leiamnash}/setTitle.js +29 -13
  50. package/leiamnash/threadColors.js +57 -0
  51. package/{src → leiamnash}/unfriend.js +19 -9
  52. package/{src → leiamnash}/unsendMessage.js +19 -9
  53. package/package.json +9 -14
  54. package/replit.nix +0 -1
  55. package/utils.js +1193 -1023
  56. package/src/addExternalModule.js +0 -15
  57. package/src/changeAdminStatus.js +0 -47
  58. package/src/changeArchivedStatus.js +0 -41
  59. package/src/changeNickname.js +0 -43
  60. package/src/changeThreadEmoji.js +0 -41
  61. package/src/chat.js +0 -315
  62. package/src/deleteMessage.js +0 -44
  63. package/src/deleteThread.js +0 -42
  64. package/src/forwardAttachment.js +0 -47
  65. package/src/forwardMessage.js +0 -0
  66. package/src/getThreadInfoDeprecated.js +0 -56
  67. package/src/getThreadListDeprecated.js +0 -46
  68. package/src/getThreadPictures.js +0 -59
  69. package/src/handleFriendRequest.js +0 -46
  70. package/src/handleMessageRequest.js +0 -47
  71. package/src/listen.js +0 -553
  72. package/src/listenMqtt-Test.js +0 -687
  73. package/src/listenMqtt.js +0 -677
  74. package/src/removeUserFromGroup.js +0 -45
  75. package/src/threadColors.js +0 -41
@@ -3,54 +3,73 @@
3
3
  var utils = require("../utils");
4
4
  var log = require("npmlog");
5
5
 
6
- module.exports = function (defaultFuncs, api, ctx) {
6
+ module.exports = function(defaultFuncs, api, ctx) {
7
7
  return function getThreadHistory(threadID, amount, timestamp, callback) {
8
- var resolveFunc = function () { };
9
- var rejectFunc = function () { };
8
+ var resolveFunc = function(){};
9
+ var rejectFunc = function(){};
10
10
  var returnPromise = new Promise(function (resolve, reject) {
11
11
  resolveFunc = resolve;
12
12
  rejectFunc = reject;
13
13
  });
14
14
 
15
15
  if (!callback) {
16
- callback = function (err, threadInfo) {
17
- if (err) return rejectFunc(err);
18
- resolveFunc(threadInfo);
16
+ callback = function (err, friendList) {
17
+ if (err) {
18
+ return rejectFunc(err);
19
+ }
20
+ resolveFunc(friendList);
19
21
  };
20
22
  }
21
23
 
22
- if (!callback) throw { error: "getThreadHistory: need callback" };
24
+ if (!callback) {
25
+ throw { error: "getThreadHistory: need callback" };
26
+ }
27
+
23
28
  var form = {
24
29
  client: "mercury"
25
30
  };
26
31
 
27
- api.getUserInfo(threadID, function (err, res) {
28
- if (err) return callback(err);
32
+ api.getUserInfo(threadID, function(err, res) {
33
+ if (err) {
34
+ return callback(err);
35
+ }
29
36
  var key = Object.keys(res).length > 0 ? "user_ids" : "thread_fbids";
30
37
  form["messages[" + key + "][" + threadID + "][offset]"] = 0;
31
38
  form["messages[" + key + "][" + threadID + "][timestamp]"] = timestamp;
32
39
  form["messages[" + key + "][" + threadID + "][limit]"] = amount;
33
40
 
34
- if (ctx.globalOptions.pageID) form.request_user_id = ctx.globalOptions.pageID;
41
+ if (ctx.globalOptions.pageID)
42
+ form.request_user_id = ctx.globalOptions.pageID;
35
43
 
36
44
  defaultFuncs
37
- .post("https://www.facebook.com/ajax/mercury/thread_info.php", ctx.jar, form)
45
+ .post(
46
+ "https://www.facebook.com/ajax/mercury/thread_info.php",
47
+ ctx.jar,
48
+ form
49
+ )
38
50
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
39
- .then(function (resData) {
40
- if (resData.error) throw resData;
41
- else if (!resData.payload) throw { error: "Could not retrieve thread history." };
51
+ .then(function(resData) {
52
+ if (resData.error) {
53
+ throw resData;
54
+ } else if (!resData.payload) {
55
+ throw { error: "Could not retrieve thread history." };
56
+ }
42
57
 
43
58
  // Asking for message history from a thread with no message history
44
59
  // will return undefined for actions here
45
- if (!resData.payload.actions) resData.payload.actions = [];
60
+ if (!resData.payload.actions) {
61
+ resData.payload.actions = [];
62
+ }
46
63
 
47
64
  var userIDs = {};
48
- resData.payload.actions.forEach(v => userIDs[v.author.split(":").pop()] = "");
65
+ resData.payload.actions.forEach(function(v) {
66
+ userIDs[v.author.split(":").pop()] = "";
67
+ });
49
68
 
50
- api.getUserInfo(Object.keys(userIDs), function (err, data) {
69
+ api.getUserInfo(Object.keys(userIDs), function(err, data) {
51
70
  if (err) return callback(err); //callback({error: "Could not retrieve user information in getThreadHistory."});
52
71
 
53
- resData.payload.actions.forEach(function (v) {
72
+ resData.payload.actions.forEach(function(v) {
54
73
  var sender = data[v.author.split(":").pop()];
55
74
  if (sender) v.sender_name = sender.name;
56
75
  else v.sender_name = "Facebook User";
@@ -58,10 +77,13 @@ module.exports = function (defaultFuncs, api, ctx) {
58
77
  delete v.author;
59
78
  });
60
79
 
61
- callback(null, resData.payload.actions.map(utils.formatHistoryMessage));
80
+ callback(
81
+ null,
82
+ resData.payload.actions.map(utils.formatHistoryMessage)
83
+ );
62
84
  });
63
85
  })
64
- .catch(function (err) {
86
+ .catch(function(err) {
65
87
  log.error("getThreadHistory", err);
66
88
  return callback(err);
67
89
  });
@@ -21,7 +21,7 @@ function formatEventReminders(reminder) {
21
21
  secondsToNotifyBefore: reminder.seconds_to_notify_before,
22
22
  allowsRsvp: reminder.allows_rsvp,
23
23
  relatedEvent: reminder.related_event,
24
- members: reminder.event_reminder_members.edges.map(function (member) {
24
+ members: reminder.event_reminder_members.edges.map(function(member) {
25
25
  return {
26
26
  memberID: member.node.id,
27
27
  state: member.guest_list_state.toLowerCase()
@@ -31,15 +31,33 @@ function formatEventReminders(reminder) {
31
31
  }
32
32
 
33
33
  function formatThreadGraphQLResponse(data) {
34
- var messageThread = data.o0.data.message_thread;
35
- var threadID = messageThread.thread_key.thread_fbid ? messageThread.thread_key.thread_fbid : messageThread.thread_key.other_user_id;
34
+ try{
35
+ var messageThread = data.o0.data.message_thread;
36
+ } catch (err){
37
+ console.error("GetThreadInfoGraphQL", "Can't get this thread info!");
38
+ return {err: err};
39
+ }
40
+ var threadID = messageThread.thread_key.thread_fbid
41
+ ? messageThread.thread_key.thread_fbid
42
+ : messageThread.thread_key.other_user_id;
36
43
 
37
44
  // Remove me
38
45
  var lastM = messageThread.last_message;
39
- var snippetID = lastM && lastM.nodes && lastM.nodes[0] && lastM.nodes[0].message_sender && lastM.nodes[0].message_sender.messaging_actor ? lastM.nodes[0].message_sender.messaging_actor.id : null;
40
- var snippetText = lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
46
+ var snippetID =
47
+ lastM &&
48
+ lastM.nodes &&
49
+ lastM.nodes[0] &&
50
+ lastM.nodes[0].message_sender &&
51
+ lastM.nodes[0].message_sender.messaging_actor
52
+ ? lastM.nodes[0].message_sender.messaging_actor.id
53
+ : null;
54
+ var snippetText =
55
+ lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
41
56
  var lastR = messageThread.last_read_receipt;
42
- var lastReadTimestamp = lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise ? lastR.nodes[0].timestamp_precise : null;
57
+ var lastReadTimestamp =
58
+ lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
59
+ ? lastR.nodes[0].timestamp_precise
60
+ : null;
43
61
 
44
62
  return {
45
63
  threadID: threadID,
@@ -66,16 +84,27 @@ function formatThreadGraphQLResponse(data) {
66
84
  isArchived: messageThread.has_viewer_archived,
67
85
  folder: messageThread.folder,
68
86
  cannotReplyReason: messageThread.cannot_reply_reason,
69
- eventReminders: messageThread.event_reminders ? messageThread.event_reminders.nodes.map(formatEventReminders) : null,
70
- emoji: messageThread.customization_info ? messageThread.customization_info.emoji : null,
71
- color: messageThread.customization_info && messageThread.customization_info.outgoing_bubble_color ? messageThread.customization_info.outgoing_bubble_color.slice(2) : null,
87
+ eventReminders: messageThread.event_reminders
88
+ ? messageThread.event_reminders.nodes.map(formatEventReminders)
89
+ : null,
90
+ emoji: messageThread.customization_info
91
+ ? messageThread.customization_info.emoji
92
+ : null,
93
+ color:
94
+ messageThread.customization_info &&
95
+ messageThread.customization_info.outgoing_bubble_color
96
+ ? messageThread.customization_info.outgoing_bubble_color.slice(2)
97
+ : null,
72
98
  nicknames:
73
99
  messageThread.customization_info &&
74
- messageThread.customization_info.participant_customizations
75
- ? messageThread.customization_info.participant_customizations.reduce(function (res, val) {
76
- if (val.nickname) res[val.participant_id] = val.nickname;
77
- return res;
78
- }, {})
100
+ messageThread.customization_info.participant_customizations
101
+ ? messageThread.customization_info.participant_customizations.reduce(
102
+ function(res, val) {
103
+ if (val.nickname) res[val.participant_id] = val.nickname;
104
+ return res;
105
+ },
106
+ {}
107
+ )
79
108
  : {},
80
109
  adminIDs: messageThread.thread_admins,
81
110
  approvalMode: Boolean(messageThread.approval_mode),
@@ -105,17 +134,19 @@ function formatThreadGraphQLResponse(data) {
105
134
  hasEmailParticipant: false,
106
135
  readOnly: false,
107
136
  canReply: messageThread.cannot_reply_reason == null,
108
- lastMessageTimestamp: messageThread.last_message ? messageThread.last_message.timestamp_precise : null,
137
+ lastMessageTimestamp: messageThread.last_message
138
+ ? messageThread.last_message.timestamp_precise
139
+ : null,
109
140
  lastMessageType: "message",
110
141
  lastReadTimestamp: lastReadTimestamp,
111
142
  threadType: messageThread.thread_type == "GROUP" ? 2 : 1
112
143
  };
113
144
  }
114
145
 
115
- module.exports = function (defaultFuncs, api, ctx) {
146
+ module.exports = function(defaultFuncs, api, ctx) {
116
147
  return function getThreadInfoGraphQL(threadID, callback) {
117
- var resolveFunc = function () { };
118
- var rejectFunc = function () { };
148
+ var resolveFunc = function(){};
149
+ var rejectFunc = function(){};
119
150
  var returnPromise = new Promise(function (resolve, reject) {
120
151
  resolveFunc = resolve;
121
152
  rejectFunc = reject;
@@ -123,7 +154,9 @@ module.exports = function (defaultFuncs, api, ctx) {
123
154
 
124
155
  if (utils.getType(callback) != "Function" && utils.getType(callback) != "AsyncFunction") {
125
156
  callback = function (err, data) {
126
- if (err) return rejectFunc(err);
157
+ if (err) {
158
+ return rejectFunc(err);
159
+ }
127
160
  resolveFunc(data);
128
161
  };
129
162
  }
@@ -150,19 +183,21 @@ module.exports = function (defaultFuncs, api, ctx) {
150
183
  defaultFuncs
151
184
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
152
185
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
153
- .then(function (resData) {
154
- if (resData.error) throw resData;
186
+ .then(function(resData) {
187
+ if (resData.error) {
188
+ throw resData;
189
+ }
155
190
  // This returns us an array of things. The last one is the success /
156
191
  // failure one.
157
192
  // @TODO What do we do in this case?
158
193
  if (resData[resData.length - 1].error_results !== 0) {
159
- console.log(resData); //Log more info
160
- throw new Error("well darn there was an error_result");
194
+ console.error("GetThreadInfo", "Well darn there was an error_result");
161
195
  }
196
+
162
197
  callback(null, formatThreadGraphQLResponse(resData[0]));
163
198
  })
164
- .catch(function (err) {
165
- log.error("getThreadInfoGraphQL", "Can't get thread info");
199
+ .catch(function(err) {
200
+ log.error("getThreadInfoGraphQL", err);
166
201
  return callback(err);
167
202
  });
168
203
 
@@ -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
+ return function getThreadInfo(threadID, callback) {
8
+ var resolveFunc = function(){};
9
+ var rejectFunc = function(){};
10
+ var returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ callback = function (err, friendList) {
17
+ if (err) {
18
+ return rejectFunc(err);
19
+ }
20
+ resolveFunc(friendList);
21
+ };
22
+ }
23
+
24
+ var form = {
25
+ client: "mercury"
26
+ };
27
+
28
+ api.getUserInfo(threadID, function(err, userRes) {
29
+ if (err) {
30
+ return callback(err);
31
+ }
32
+ var key = Object.keys(userRes).length > 0 ? "user_ids" : "thread_fbids";
33
+ form["threads[" + key + "][0]"] = threadID;
34
+
35
+ if (ctx.globalOptions.pageId)
36
+ form.request_user_id = ctx.globalOptions.pageId;
37
+
38
+ defaultFuncs
39
+ .post(
40
+ "https://www.facebook.com/ajax/mercury/thread_info.php",
41
+ ctx.jar,
42
+ form
43
+ )
44
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
45
+ .then(function(resData) {
46
+ if (resData.error) {
47
+ throw resData;
48
+ } else if (!resData.payload) {
49
+ throw {
50
+ error: "Could not retrieve thread Info."
51
+ };
52
+ }
53
+ var threadData = resData.payload.threads[0];
54
+ var userData = userRes[threadID];
55
+
56
+ if (threadData == null) {
57
+ throw {
58
+ error: "ThreadData is null"
59
+ };
60
+ }
61
+
62
+ threadData.name =
63
+ userData != null && userData.name != null
64
+ ? userData.name
65
+ : threadData.name;
66
+ threadData.image_src =
67
+ userData != null && userData.thumbSrc != null
68
+ ? userData.thumbSrc
69
+ : threadData.image_src;
70
+
71
+ callback(null, utils.formatThread(threadData));
72
+ })
73
+ .catch(function(err) {
74
+ log.error("getThreadInfo", err);
75
+ return callback(err);
76
+ });
77
+ });
78
+ return returnPromise;
79
+ };
80
+ };
@@ -9,7 +9,7 @@ function createProfileUrl(url, username, id) {
9
9
  }
10
10
 
11
11
  function formatParticipants(participants) {
12
- return participants.edges.map((p) => {
12
+ return participants.edges.map((p)=>{
13
13
  p = p.node.messaging_actor;
14
14
  switch (p["__typename"]) {
15
15
  case "User":
@@ -21,7 +21,7 @@ function formatParticipants(participants) {
21
21
  gender: p.gender,
22
22
  url: p.url, // how about making it profileURL
23
23
  profilePicture: p.big_image_src.uri,
24
- username: (p.username || null),
24
+ username: (p.username||null),
25
25
  // TODO: maybe better names for these?
26
26
  isViewerFriend: p.is_viewer_friend, // true/false
27
27
  isMessengerUser: p.is_messenger_user, // true/false
@@ -37,7 +37,7 @@ function formatParticipants(participants) {
37
37
  name: p.name,
38
38
  url: p.url,
39
39
  profilePicture: p.big_image_src.uri,
40
- username: (p.username || null),
40
+ username: (p.username||null),
41
41
  // uhm... better names maybe?
42
42
  acceptsMessengerUserFeedback: p.accepts_messenger_user_feedback, // true/false
43
43
  isMessengerUser: p.is_messenger_user, // true/false
@@ -46,18 +46,27 @@ function formatParticipants(participants) {
46
46
  isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
47
47
  };
48
48
  case "ReducedMessagingActor":
49
- case "UnavailableMessagingActor":
50
49
  return {
51
50
  accountType: p["__typename"],
52
51
  userID: utils.formatID(p.id.toString()),
53
52
  name: p.name,
54
53
  url: createProfileUrl(p.url, p.username, p.id), // in this case p.url is null all the time
55
54
  profilePicture: p.big_image_src.uri, // in this case it is default facebook photo, we could determine gender using it
56
- username: (p.username || null), // maybe we could use it to generate profile URL?
55
+ username: (p.username||null), // maybe we could use it to generate profile URL?
56
+ isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
57
+ };
58
+ case "UnavailableMessagingActor":
59
+ return {
60
+ accountType: p["__typename"],
61
+ userID: utils.formatID(p.id.toString()),
62
+ name: p.name, // "Facebook User" in user's language
63
+ url: createProfileUrl(p.url, p.username, p.id), // in this case p.url is null all the time
64
+ profilePicture: p.big_image_src.uri, // default male facebook photo
65
+ username: (p.username||null), // maybe we could use it to generate profile URL?
57
66
  isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
58
67
  };
59
68
  default:
60
- log.warn("getThreadList", "Found participant with unsupported typename. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues\n" + JSON.stringify(p, null, 2));
69
+ log.warn("getThreadList", "Found participant with unsupported typename. Please open an issue at https://github.com/Schmavery/fca-unofficial/issues\n" + JSON.stringify(p, null, 2));
61
70
  return {
62
71
  accountType: p["__typename"],
63
72
  userID: utils.formatID(p.id.toString()),
@@ -69,7 +78,9 @@ function formatParticipants(participants) {
69
78
 
70
79
  // "FF8C0077" -> "8C0077"
71
80
  function formatColor(color) {
72
- if (color && color.match(/^(?:[0-9a-fA-F]{8})$/g)) return color.slice(2);
81
+ if (color && color.match(/^(?:[0-9a-fA-F]{8})$/g)) {
82
+ return color.slice(2);
83
+ }
73
84
  return color;
74
85
  }
75
86
 
@@ -84,24 +95,24 @@ function getThreadName(t) {
84
95
 
85
96
  function mapNicknames(customizationInfo) {
86
97
  return (customizationInfo && customizationInfo.participant_customizations) ? customizationInfo.participant_customizations.map(u => {
87
- return {
88
- "userID": u.participant_id,
89
- "nickname": u.nickname
90
- };
91
- }) : [];
98
+ return {
99
+ "userID": u.participant_id,
100
+ "nickname": u.nickname
101
+ };
102
+ }):[];
92
103
  }
93
104
 
94
105
  function formatThreadList(data) {
95
106
  return data.map(t => {
96
- let lastMessageNode = (t.last_message && t.last_message.nodes && t.last_message.nodes.length > 0) ? t.last_message.nodes[0] : null;
107
+ let lastMessageNode = (t.last_message&&t.last_message.nodes&&t.last_message.nodes.length>0)?t.last_message.nodes[0]:null;
97
108
  return {
98
- threadID: t.thread_key ? utils.formatID(t.thread_key.thread_fbid || t.thread_key.other_user_id) : null, // shall never be null
109
+ threadID: t.thread_key?utils.formatID(t.thread_key.thread_fbid || t.thread_key.other_user_id):null, // shall never be null
99
110
  name: getThreadName(t),
100
111
  unreadCount: t.unread_count,
101
112
  messageCount: t.messages_count,
102
- imageSrc: t.image ? t.image.uri : null,
103
- emoji: t.customization_info ? t.customization_info.emoji : null,
104
- color: formatColor(t.customization_info ? t.customization_info.outgoing_bubble_color : null),
113
+ imageSrc: t.image?t.image.uri:null,
114
+ emoji: t.customization_info?t.customization_info.emoji:null,
115
+ color: formatColor(t.customization_info?t.customization_info.outgoing_bubble_color:null),
105
116
  nicknames: mapNicknames(t.customization_info),
106
117
  muteUntil: t.mute_until,
107
118
  participants: formatParticipants(t.all_participants),
@@ -112,7 +123,7 @@ function formatThreadList(data) {
112
123
  // isPinProtected: t.is_pin_protected, // feature from future? always false (2018-04-04)
113
124
  customizationEnabled: t.customization_enabled, // false for ONE_TO_ONE with Page or ReducedMessagingActor
114
125
  participantAddMode: t.participant_add_mode_as_string, // "ADD" if "GROUP" and null if "ONE_TO_ONE"
115
- montageThread: t.montage_thread ? Buffer.from(t.montage_thread.id, "base64").toString() : null, // base64 encoded string "message_thread:0000000000000000"
126
+ montageThread: t.montage_thread?Buffer.from(t.montage_thread.id,"base64").toString():null, // base64 encoded string "message_thread:0000000000000000"
116
127
  // it is not userID nor any other ID known to me...
117
128
  // can somebody inspect it? where is it used?
118
129
  // probably Messenger Day uses it
@@ -123,13 +134,13 @@ function formatThreadList(data) {
123
134
  timestamp: t.updated_time_precise, // in miliseconds
124
135
  // isCanonicalUser: t.is_canonical_neo_user, // is it always false?
125
136
  // TODO: how about putting snippet in another object? current implementation does not handle every possibile message type etc.
126
- snippet: lastMessageNode ? lastMessageNode.snippet : null,
127
- snippetAttachments: lastMessageNode ? lastMessageNode.extensible_attachment : null, // TODO: not sure if it works
128
- snippetSender: lastMessageNode ? utils.formatID((lastMessageNode.message_sender.messaging_actor.id || "").toString()) : null,
129
- lastMessageTimestamp: lastMessageNode ? lastMessageNode.timestamp_precise : null, // timestamp in miliseconds
130
- lastReadTimestamp: (t.last_read_receipt && t.last_read_receipt.nodes.length > 0)
131
- ? (t.last_read_receipt.nodes[0] ? t.last_read_receipt.nodes[0].timestamp_precise : null)
132
- : null, // timestamp in miliseconds
137
+ snippet: lastMessageNode?lastMessageNode.snippet:null,
138
+ snippetAttachments: lastMessageNode?lastMessageNode.extensible_attachment:null, // TODO: not sure if it works
139
+ snippetSender: lastMessageNode?utils.formatID((lastMessageNode.message_sender.messaging_actor.id || "").toString()):null,
140
+ lastMessageTimestamp: lastMessageNode?lastMessageNode.timestamp_precise:null, // timestamp in miliseconds
141
+ lastReadTimestamp: (t.last_read_receipt&&t.last_read_receipt.nodes.length>0)
142
+ ? (t.last_read_receipt.nodes[0]?t.last_read_receipt.nodes[0].timestamp_precise:null)
143
+ : null, // timestamp in miliseconds
133
144
  cannotReplyReason: t.cannot_reply_reason, // TODO: inspect possible values
134
145
  approvalMode: Boolean(t.approval_mode),
135
146
 
@@ -140,21 +151,28 @@ function formatThreadList(data) {
140
151
  });
141
152
  }
142
153
 
143
- module.exports = function (defaultFuncs, api, ctx) {
154
+ module.exports = function(defaultFuncs, api, ctx) {
144
155
  return function getThreadList(limit, timestamp, tags, callback) {
145
156
  if (!callback && (utils.getType(tags) === "Function" || utils.getType(tags) === "AsyncFunction")) {
146
157
  callback = tags;
147
158
  tags = [""];
148
159
  }
149
- if (utils.getType(limit) !== "Number" || !Number.isInteger(limit) || limit <= 0) throw { error: "getThreadList: limit must be a positive integer" };
150
-
151
- if (utils.getType(timestamp) !== "Null" && (utils.getType(timestamp) !== "Number" || !Number.isInteger(timestamp))) throw { error: "getThreadList: timestamp must be an integer or null" };
152
-
153
- if (utils.getType(tags) === "String") tags = [tags];
154
- if (utils.getType(tags) !== "Array") throw { error: "getThreadList: tags must be an array" };
160
+ if (utils.getType(limit) !== "Number" || !Number.isInteger(limit) || limit <= 0) {
161
+ throw {error: "getThreadList: limit must be a positive integer"};
162
+ }
163
+ if (utils.getType(timestamp) !== "Null" &&
164
+ (utils.getType(timestamp) !== "Number" || !Number.isInteger(timestamp))) {
165
+ throw {error: "getThreadList: timestamp must be an integer or null"};
166
+ }
167
+ if (utils.getType(tags) === "String") {
168
+ tags = [tags];
169
+ }
170
+ if (utils.getType(tags) !== "Array") {
171
+ throw {error: "getThreadList: tags must be an array"};
172
+ }
155
173
 
156
- var resolveFunc = function () { };
157
- var rejectFunc = function () { };
174
+ var resolveFunc = function(){};
175
+ var rejectFunc = function(){};
158
176
  var returnPromise = new Promise(function (resolve, reject) {
159
177
  resolveFunc = resolve;
160
178
  rejectFunc = reject;
@@ -162,7 +180,9 @@ module.exports = function (defaultFuncs, api, ctx) {
162
180
 
163
181
  if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
164
182
  callback = function (err, data) {
165
- if (err) return rejectFunc(err);
183
+ if (err) {
184
+ return rejectFunc(err);
185
+ }
166
186
  resolveFunc(data);
167
187
  };
168
188
  }
@@ -174,7 +194,7 @@ module.exports = function (defaultFuncs, api, ctx) {
174
194
  // This doc_id was valid on 2020-07-20
175
195
  "doc_id": "3336396659757871",
176
196
  "query_params": {
177
- "limit": limit + (timestamp ? 1 : 0),
197
+ "limit": limit+(timestamp?1:0),
178
198
  "before": timestamp,
179
199
  "tags": tags,
180
200
  "includeDeliveryReceipts": true,
@@ -189,9 +209,13 @@ module.exports = function (defaultFuncs, api, ctx) {
189
209
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
190
210
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
191
211
  .then((resData) => {
192
- if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
212
+ if (resData[resData.length - 1].error_results > 0) {
213
+ throw resData[0].o0.errors;
214
+ }
193
215
 
194
- if (resData[resData.length - 1].successful_results === 0) throw { error: "getThreadList: there was no successful_results", res: resData };
216
+ if (resData[resData.length - 1].successful_results === 0) {
217
+ throw {error: "getThreadList: there was no successful_results", res: resData};
218
+ }
195
219
 
196
220
  // When we ask for threads using timestamp from the previous request,
197
221
  // we are getting the last thread repeated as the first thread in this response.
@@ -199,12 +223,13 @@ module.exports = function (defaultFuncs, api, ctx) {
199
223
  // It is also the reason for increasing limit by 1 when timestamp is set
200
224
  // this way user asks for 10 threads, we are asking for 11,
201
225
  // but after removing the duplicated one, it is again 10
202
- if (timestamp) resData[0].o0.data.viewer.message_threads.nodes.shift();
203
-
226
+ if (timestamp) {
227
+ resData[0].o0.data.viewer.message_threads.nodes.shift();
228
+ }
204
229
  callback(null, formatThreadList(resData[0].o0.data.viewer.message_threads.nodes));
205
230
  })
206
231
  .catch((err) => {
207
- log.error("getThreadList", "ParseAndCheckLogin got status code: 404. Bailing out of trying to parse response.");
232
+ log.error("getThreadList", err);
208
233
  return callback(err);
209
234
  });
210
235
 
@@ -0,0 +1,75 @@
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 getThreadList(start, end, type, callback) {
8
+ if (utils.getType(callback) === "Undefined") {
9
+ if (utils.getType(end) !== "Number") {
10
+ throw {
11
+ error: "Please pass a number as a second argument."
12
+ };
13
+ } else if (
14
+ utils.getType(type) === "Function" ||
15
+ utils.getType(type) === "AsyncFunction"
16
+ ) {
17
+ callback = type;
18
+ type = "inbox"; //default to inbox
19
+ } else if (utils.getType(type) !== "String") {
20
+ throw {
21
+ error:
22
+ "Please pass a String as a third argument. Your options are: inbox, pending, and archived"
23
+ };
24
+ } else {
25
+ throw {
26
+ error: "getThreadList: need callback"
27
+ };
28
+ }
29
+ }
30
+
31
+ if (type === "archived") {
32
+ type = "action:archived";
33
+ } else if (type !== "inbox" && type !== "pending" && type !== "other") {
34
+ throw {
35
+ error:
36
+ "type can only be one of the following: inbox, pending, archived, other"
37
+ };
38
+ }
39
+
40
+ if (end <= start) end = start + 20;
41
+
42
+ var form = {
43
+ client: "mercury"
44
+ };
45
+
46
+ form[type + "[offset]"] = start;
47
+ form[type + "[limit]"] = end - start;
48
+
49
+ if (ctx.globalOptions.pageID) {
50
+ form.request_user_id = ctx.globalOptions.pageID;
51
+ }
52
+
53
+ defaultFuncs
54
+ .post(
55
+ "https://www.facebook.com/ajax/mercury/threadlist_info.php",
56
+ ctx.jar,
57
+ form
58
+ )
59
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
60
+ .then(function(resData) {
61
+ if (resData.error) {
62
+ throw resData;
63
+ }
64
+ log.verbose("getThreadList", JSON.stringify(resData.payload.threads));
65
+ return callback(
66
+ null,
67
+ (resData.payload.threads || []).map(utils.formatThread)
68
+ );
69
+ })
70
+ .catch(function(err) {
71
+ log.error("getThreadList", err);
72
+ return callback(err);
73
+ });
74
+ };
75
+ };