alicezetion 1.8.3 → 1.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) 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 +210 -375
  4. package/package.json +6 -3
  5. package/replit.nix +4 -4
  6. package/src/addExternalModule.js +17 -0
  7. package/src/addUserToGroup.js +113 -0
  8. package/src/changeAdminStatus.js +79 -0
  9. package/src/changeArchivedStatus.js +55 -0
  10. package/src/changeAvatar.js +93 -0
  11. package/src/changeBio.js +77 -0
  12. package/src/changeBlockedStatus.js +47 -0
  13. package/src/changeCover.js +73 -0
  14. package/src/changeGroupImage.js +132 -0
  15. package/src/changeName.js +79 -0
  16. package/src/changeNickname.js +59 -0
  17. package/src/changeThreadColor.js +65 -0
  18. package/src/changeThreadEmoji.js +55 -0
  19. package/{leiamnash → src}/chat.js +28 -3
  20. package/src/createNewGroup.js +86 -0
  21. package/src/createPoll.js +71 -0
  22. package/src/data/getThreadInfo.json +1 -0
  23. package/src/deleteMessage.js +56 -0
  24. package/src/deleteThread.js +56 -0
  25. package/src/forwardAttachment.js +60 -0
  26. package/src/getAccess.js +112 -0
  27. package/src/getAvatarUser.js +78 -0
  28. package/src/getCurrentUserID.js +7 -0
  29. package/src/getEmojiUrl.js +29 -0
  30. package/src/getFriendsList.js +83 -0
  31. package/src/getThreadHistory.js +666 -0
  32. package/{leiamnash → src}/getThreadInfo.js +70 -54
  33. package/src/getThreadList.js +237 -0
  34. package/src/getThreadPictures.js +79 -0
  35. package/src/getUserID.js +66 -0
  36. package/src/getUserInfo.js +163 -0
  37. package/src/handleFriendRequest.js +61 -0
  38. package/src/handleMessageRequest.js +65 -0
  39. package/src/httpGet.js +57 -0
  40. package/src/httpPost.js +57 -0
  41. package/src/httpPostFormData.js +63 -0
  42. package/{leiamnash → src}/listenMqtt.js +16 -6
  43. package/src/listenNotification.js +88 -0
  44. package/src/logout.js +275 -0
  45. package/src/markAsDelivered.js +58 -0
  46. package/src/markAsRead.js +80 -0
  47. package/src/markAsReadAll.js +50 -0
  48. package/src/markAsSeen.js +59 -0
  49. package/src/muteThread.js +52 -0
  50. package/src/react.js +117 -0
  51. package/{leiamnash → src}/refreshFb_dtsg.js +1 -1
  52. package/src/removeUserFromGroup.js +79 -0
  53. package/src/resolvePhotoUrl.js +45 -0
  54. package/src/searchForThread.js +53 -0
  55. package/src/searchStickers.js +52 -0
  56. package/src/seen.js +50 -0
  57. package/src/sendMessage.js +477 -0
  58. package/src/sendMessageMqtt.js +316 -0
  59. package/src/sendTypingIndicator.js +103 -0
  60. package/src/setMessageReaction.js +117 -0
  61. package/src/setPostReaction.js +109 -0
  62. package/src/setTitle.js +86 -0
  63. package/src/threadColors.js +131 -0
  64. package/src/unfriend.js +52 -0
  65. package/src/unsendMessage.js +49 -0
  66. package/utils.js +135 -176
  67. package/.cache/replit/modules.stamp +0 -1
  68. package/leiamnash/addExternalModule.js +0 -15
  69. package/leiamnash/addUserToGroup.js +0 -77
  70. package/leiamnash/changeAdminStatus.js +0 -47
  71. package/leiamnash/changeArchivedStatus.js +0 -41
  72. package/leiamnash/changeAvatar.js +0 -127
  73. package/leiamnash/changeBio.js +0 -64
  74. package/leiamnash/changeBlockedStatus.js +0 -36
  75. package/leiamnash/changeGroupImage.js +0 -105
  76. package/leiamnash/changeNickname.js +0 -43
  77. package/leiamnash/changeThreadColor.js +0 -61
  78. package/leiamnash/changeThreadEmoji.js +0 -41
  79. package/leiamnash/createNewGroup.js +0 -70
  80. package/leiamnash/createPoll.js +0 -59
  81. package/leiamnash/deleteMessage.js +0 -44
  82. package/leiamnash/deleteThread.js +0 -42
  83. package/leiamnash/forwardAttachment.js +0 -47
  84. package/leiamnash/forwardMessage.js +0 -0
  85. package/leiamnash/getCurrentUserID.js +0 -7
  86. package/leiamnash/getEmojiUrl.js +0 -27
  87. package/leiamnash/getFriendsList.js +0 -73
  88. package/leiamnash/getInfoVideo.js +0 -134
  89. package/leiamnash/getThreadHistory.js +0 -537
  90. package/leiamnash/getThreadHistoryDeprecated.js +0 -71
  91. package/leiamnash/getThreadInfoDeprecated.js +0 -56
  92. package/leiamnash/getThreadList.js +0 -213
  93. package/leiamnash/getThreadListDeprecated.js +0 -46
  94. package/leiamnash/getThreadPictures.js +0 -59
  95. package/leiamnash/getUserID.js +0 -61
  96. package/leiamnash/getUserInfo.js +0 -66
  97. package/leiamnash/handleFriendRequest.js +0 -46
  98. package/leiamnash/handleMessageRequest.js +0 -47
  99. package/leiamnash/httpGet.js +0 -47
  100. package/leiamnash/httpPost.js +0 -47
  101. package/leiamnash/httpPostFormData.js +0 -42
  102. package/leiamnash/logout.js +0 -68
  103. package/leiamnash/markAsDelivered.js +0 -47
  104. package/leiamnash/markAsRead.js +0 -70
  105. package/leiamnash/markAsReadAll.js +0 -40
  106. package/leiamnash/markAsSeen.js +0 -48
  107. package/leiamnash/muteThread.js +0 -45
  108. package/leiamnash/react.js +0 -109
  109. package/leiamnash/removeUserFromGroup.js +0 -45
  110. package/leiamnash/resolvePhotoUrl.js +0 -36
  111. package/leiamnash/searchForThread.js +0 -42
  112. package/leiamnash/seen.js +0 -40
  113. package/leiamnash/sendMessage.js +0 -315
  114. package/leiamnash/sendTypingIndicator.js +0 -70
  115. package/leiamnash/setMessageReaction.js +0 -103
  116. package/leiamnash/setPostReaction.js +0 -63
  117. package/leiamnash/setTitle.js +0 -70
  118. package/leiamnash/threadColors.js +0 -41
  119. package/leiamnash/unfriend.js +0 -42
  120. package/leiamnash/unsendMessage.js +0 -39
  121. package/leiamnash/uploadAttachment.js +0 -96
  122. /package/{leiamnash → src}/getMessage.js +0 -0
@@ -31,8 +31,10 @@ 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
+ var messageThread = data.message_thread;
35
+ if (!messageThread) return {};
36
+
37
+ var threadID = messageThread.thread_key.thread_fbid || messageThread.thread_key.other_user_id;
36
38
 
37
39
  // Remove me
38
40
  var lastM = messageThread.last_message;
@@ -108,64 +110,78 @@ function formatThreadGraphQLResponse(data) {
108
110
  lastMessageTimestamp: messageThread.last_message ? messageThread.last_message.timestamp_precise : null,
109
111
  lastMessageType: "message",
110
112
  lastReadTimestamp: lastReadTimestamp,
111
- threadType: messageThread.thread_type == "GROUP" ? 2 : 1
113
+ threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
114
+ inviteLink: {
115
+ enable: messageThread.joinable_mode ? messageThread.joinable_mode.mode == 1 : false,
116
+ link: messageThread.joinable_mode ? messageThread.joinable_mode.link : null
117
+ }
112
118
  };
113
119
  }
114
120
 
115
121
  module.exports = function (defaultFuncs, api, ctx) {
116
- return function getThreadInfoGraphQL(threadID, callback) {
117
- var resolveFunc = function () { };
118
- var rejectFunc = function () { };
119
- var returnPromise = new Promise(function (resolve, reject) {
120
- resolveFunc = resolve;
121
- rejectFunc = reject;
122
+ return function getThreadInfoGraphQL(threadIDs, callback) {
123
+ var cb;
124
+ var rtPromise = new Promise(function (resolve, reject) {
125
+ cb = function (error, data) {
126
+ data ? resolve(data) : reject(error);
127
+ }
122
128
  });
123
129
 
124
- if (utils.getType(callback) != "Function" && utils.getType(callback) != "AsyncFunction") {
125
- callback = function (err, data) {
126
- if (err) return rejectFunc(err);
127
- resolveFunc(data);
128
- };
129
- }
130
+ if (typeof callback == 'function') cb = callback;
131
+ if (Array.isArray(threadIDs) == false) threadIDs = [threadIDs];
130
132
 
131
- // `queries` has to be a string. I couldn't tell from the dev console. This
132
- // took me a really long time to figure out. I deserve a cookie for this.
133
- var form = {
134
- queries: JSON.stringify({
135
- o0: {
136
- // This doc_id is valid as of July 20th, 2020
137
- doc_id: "3449967031715030",
138
- query_params: {
139
- id: threadID,
140
- message_limit: 0,
141
- load_messages: false,
142
- load_read_receipts: false,
143
- before: null
144
- }
145
- }
146
- }),
147
- batch_name: "MessengerGraphQLThreadFetcher"
148
- };
133
+ var form = {};
134
+ // `queries` has to be a string. I couldn't tell from the dev console. This
135
+ // took me a really long time to figure out. I deserve a cookie for this.
136
+ threadIDs.map(function (t, i) {
137
+ form["o" + i] = {
138
+ doc_id: "3449967031715030",
139
+ query_params: {
140
+ id: t,
141
+ message_limit: 0,
142
+ load_messages: false,
143
+ load_read_receipts: false,
144
+ before: null
145
+ }
146
+ };
147
+ });
149
148
 
150
- defaultFuncs
151
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
152
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
153
- .then(function (resData) {
154
- if (resData.error) throw resData;
155
- // This returns us an array of things. The last one is the success /
156
- // failure one.
157
- // @TODO What do we do in this case?
158
- 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");
161
- }
162
- callback(null, formatThreadGraphQLResponse(resData[0]));
163
- })
164
- .catch(function (err) {
165
- log.error("getThreadInfoGraphQL", "Can't get thread info");
166
- return callback(err);
167
- });
149
+ form = {
150
+ queries: JSON.stringify(form),
151
+ batch_name: "MessengerGraphQLThreadFetcher"
152
+ };
168
153
 
169
- return returnPromise;
170
- };
171
- };
154
+ defaultFuncs
155
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
156
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
157
+ .then(function (resData) {
158
+ if (resData.error) throw resData;
159
+ // This returns us an array of things. The last one is the success /
160
+ // failure one.
161
+ // @TODO What do we do in this case?
162
+ // if (resData[resData.length - 1].error_results !== 0) {
163
+ // throw resData[0].o0.errors[0];
164
+ // }
165
+ // if (!resData[0].o0.data.message_thread) {
166
+ // throw new Error("can't find this thread");
167
+ // }
168
+ const threadInfos = {};
169
+ for (let i = resData.length - 2; i >= 0; i--) {
170
+ const threadInfo = formatThreadGraphQLResponse(resData[i][Object.keys(resData[i])[0]].data);
171
+ threadInfos[threadInfo?.threadID || threadID[threadID.length - 1 - i]] = threadInfo;
172
+ }
173
+ if (Object.values(threadInfos).length == 1) {
174
+ cb(null, Object.values(threadInfos)[0]);
175
+ }
176
+ else {
177
+ cb(null, threadInfos);
178
+ }
179
+ })
180
+ .catch(function (err) {
181
+ log.error("getThreadInfoGraphQL", err);
182
+ return cb(err);
183
+ });
184
+
185
+ return rtPromise;
186
+ };
187
+ };
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ function formatEventReminders(reminder) {
7
+ return {
8
+ reminderID: reminder.id,
9
+ eventCreatorID: reminder.lightweight_event_creator.id,
10
+ time: reminder.time,
11
+ eventType: reminder.lightweight_event_type.toLowerCase(),
12
+ locationName: reminder.location_name,
13
+ // @TODO verify this
14
+ locationCoordinates: reminder.location_coordinates,
15
+ locationPage: reminder.location_page,
16
+ eventStatus: reminder.lightweight_event_status.toLowerCase(),
17
+ note: reminder.note,
18
+ repeatMode: reminder.repeat_mode.toLowerCase(),
19
+ eventTitle: reminder.event_title,
20
+ triggerMessage: reminder.trigger_message,
21
+ secondsToNotifyBefore: reminder.seconds_to_notify_before,
22
+ allowsRsvp: reminder.allows_rsvp,
23
+ relatedEvent: reminder.related_event,
24
+ members: reminder.event_reminder_members.edges.map(function (member) {
25
+ return {
26
+ memberID: member.node.id,
27
+ state: member.guest_list_state.toLowerCase()
28
+ };
29
+ })
30
+ };
31
+ }
32
+
33
+ function formatThreadGraphQLResponse(messageThread) {
34
+ var threadID = messageThread.thread_key.thread_fbid
35
+ ? messageThread.thread_key.thread_fbid
36
+ : messageThread.thread_key.other_user_id;
37
+
38
+ // Remove me
39
+ var lastM = messageThread.last_message;
40
+ var snippetID =
41
+ lastM &&
42
+ lastM.nodes &&
43
+ lastM.nodes[0] &&
44
+ lastM.nodes[0].message_sender &&
45
+ lastM.nodes[0].message_sender.messaging_actor
46
+ ? lastM.nodes[0].message_sender.messaging_actor.id
47
+ : null;
48
+ var snippetText =
49
+ lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
50
+ var lastR = messageThread.last_read_receipt;
51
+ var lastReadTimestamp =
52
+ lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
53
+ ? lastR.nodes[0].timestamp_precise
54
+ : null;
55
+
56
+ return {
57
+ threadID: threadID,
58
+ threadName: messageThread.name,
59
+ participantIDs: messageThread.all_participants.edges.map(d => d.node.messaging_actor.id),
60
+ userInfo: messageThread.all_participants.edges.map(d => ({
61
+ id: d.node.messaging_actor.id,
62
+ name: d.node.messaging_actor.name,
63
+ firstName: d.node.messaging_actor.short_name,
64
+ vanity: d.node.messaging_actor.username,
65
+ url: d.node.messaging_actor.url,
66
+ thumbSrc: d.node.messaging_actor.big_image_src.uri,
67
+ profileUrl: d.node.messaging_actor.big_image_src.uri,
68
+ gender: d.node.messaging_actor.gender,
69
+ type: d.node.messaging_actor.__typename,
70
+ isFriend: d.node.messaging_actor.is_viewer_friend,
71
+ isBirthday: !!d.node.messaging_actor.is_birthday //not sure?
72
+ })),
73
+ unreadCount: messageThread.unread_count,
74
+ messageCount: messageThread.messages_count,
75
+ timestamp: messageThread.updated_time_precise,
76
+ muteUntil: messageThread.mute_until,
77
+ isGroup: messageThread.thread_type == "GROUP",
78
+ isSubscribed: messageThread.is_viewer_subscribed,
79
+ isArchived: messageThread.has_viewer_archived,
80
+ folder: messageThread.folder,
81
+ cannotReplyReason: messageThread.cannot_reply_reason,
82
+ eventReminders: messageThread.event_reminders
83
+ ? messageThread.event_reminders.nodes.map(formatEventReminders)
84
+ : null,
85
+ emoji: messageThread.customization_info
86
+ ? messageThread.customization_info.emoji
87
+ : null,
88
+ color:
89
+ messageThread.customization_info &&
90
+ messageThread.customization_info.outgoing_bubble_color
91
+ ? messageThread.customization_info.outgoing_bubble_color.slice(2)
92
+ : null,
93
+ threadTheme: messageThread.thread_theme,
94
+ nicknames:
95
+ messageThread.customization_info &&
96
+ messageThread.customization_info.participant_customizations
97
+ ? messageThread.customization_info.participant_customizations.reduce(
98
+ function (res, val) {
99
+ if (val.nickname) res[val.participant_id] = val.nickname;
100
+ return res;
101
+ },
102
+ {}
103
+ )
104
+ : {},
105
+ adminIDs: messageThread.thread_admins,
106
+ approvalMode: Boolean(messageThread.approval_mode),
107
+ approvalQueue: messageThread.group_approval_queue.nodes.map(a => ({
108
+ inviterID: a.inviter.id,
109
+ requesterID: a.requester.id,
110
+ timestamp: a.request_timestamp,
111
+ request_source: a.request_source // @Undocumented
112
+ })),
113
+
114
+ // @Undocumented
115
+ reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
116
+ mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
117
+ isPinProtected: messageThread.is_pin_protected,
118
+ relatedPageThread: messageThread.related_page_thread,
119
+
120
+ // @Legacy
121
+ name: messageThread.name,
122
+ snippet: snippetText,
123
+ snippetSender: snippetID,
124
+ snippetAttachments: [],
125
+ serverTimestamp: messageThread.updated_time_precise,
126
+ imageSrc: messageThread.image ? messageThread.image.uri : null,
127
+ isCanonicalUser: messageThread.is_canonical_neo_user,
128
+ isCanonical: messageThread.thread_type != "GROUP",
129
+ recipientsLoadable: true,
130
+ hasEmailParticipant: false,
131
+ readOnly: false,
132
+ canReply: messageThread.cannot_reply_reason == null,
133
+ lastMessageTimestamp: messageThread.last_message
134
+ ? messageThread.last_message.timestamp_precise
135
+ : null,
136
+ lastMessageType: "message",
137
+ lastReadTimestamp: lastReadTimestamp,
138
+ threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
139
+
140
+ // update in Wed, 13 Jul 2022 19:41:12 +0700
141
+ inviteLink: {
142
+ enable: messageThread.joinable_mode ? messageThread.joinable_mode.mode == 1 : false,
143
+ link: messageThread.joinable_mode ? messageThread.joinable_mode.link : null
144
+ }
145
+ };
146
+ }
147
+
148
+ function formatThreadList(data) {
149
+ // console.log(JSON.stringify(data.find(t => t.thread_key.thread_fbid === "5095817367161431"), null, 2));
150
+ return data.map(t => formatThreadGraphQLResponse(t));
151
+ }
152
+
153
+ module.exports = function (defaultFuncs, api, ctx) {
154
+ return function getThreadList(limit, timestamp, tags, callback) {
155
+ if (!callback && (utils.getType(tags) === "Function" || utils.getType(tags) === "AsyncFunction")) {
156
+ callback = tags;
157
+ tags = [""];
158
+ }
159
+ if (utils.getType(limit) !== "Number" || !Number.isInteger(limit) || limit <= 0) {
160
+ throw { error: "getThreadList: limit must be a positive integer" };
161
+ }
162
+ if (utils.getType(timestamp) !== "Null" &&
163
+ (utils.getType(timestamp) !== "Number" || !Number.isInteger(timestamp))) {
164
+ throw { error: "getThreadList: timestamp must be an integer or null" };
165
+ }
166
+ if (utils.getType(tags) === "String") {
167
+ tags = [tags];
168
+ }
169
+ if (utils.getType(tags) !== "Array") {
170
+ throw { error: "getThreadList: tags must be an array" };
171
+ }
172
+
173
+ var resolveFunc = function () { };
174
+ var rejectFunc = function () { };
175
+ var returnPromise = new Promise(function (resolve, reject) {
176
+ resolveFunc = resolve;
177
+ rejectFunc = reject;
178
+ });
179
+
180
+ if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
181
+ callback = function (err, data) {
182
+ if (err) {
183
+ return rejectFunc(err);
184
+ }
185
+ resolveFunc(data);
186
+ };
187
+ }
188
+
189
+ const form = {
190
+ "av": ctx.globalOptions.pageID,
191
+ "queries": JSON.stringify({
192
+ "o0": {
193
+ // This doc_id was valid on 2020-07-20
194
+ "doc_id": "3336396659757871",
195
+ "query_params": {
196
+ "limit": limit + (timestamp ? 1 : 0),
197
+ "before": timestamp,
198
+ "tags": tags,
199
+ "includeDeliveryReceipts": true,
200
+ "includeSeqID": false
201
+ }
202
+ }
203
+ }),
204
+ "batch_name": "MessengerGraphQLThreadlistFetcher"
205
+ };
206
+
207
+ defaultFuncs
208
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
209
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
210
+ .then((resData) => {
211
+ if (resData[resData.length - 1].error_results > 0) {
212
+ throw resData[0].o0.errors;
213
+ }
214
+
215
+ if (resData[resData.length - 1].successful_results === 0) {
216
+ throw { error: "getThreadList: there was no successful_results", res: resData };
217
+ }
218
+
219
+ // When we ask for threads using timestamp from the previous request,
220
+ // we are getting the last thread repeated as the first thread in this response.
221
+ // .shift() gets rid of it
222
+ // It is also the reason for increasing limit by 1 when timestamp is set
223
+ // this way user asks for 10 threads, we are asking for 11,
224
+ // but after removing the duplicated one, it is again 10
225
+ if (timestamp) {
226
+ resData[0].o0.data.viewer.message_threads.nodes.shift();
227
+ }
228
+ callback(null, formatThreadList(resData[0].o0.data.viewer.message_threads.nodes));
229
+ })
230
+ .catch((err) => {
231
+ log.error("getThreadList", err);
232
+ return callback(err);
233
+ });
234
+
235
+ return returnPromise;
236
+ };
237
+ };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function getThreadPictures(threadID, offset, limit, callback) {
8
+ let resolveFunc = function () { };
9
+ let rejectFunc = function () { };
10
+ const 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
+ let form = {
25
+ thread_id: threadID,
26
+ offset: offset,
27
+ limit: limit
28
+ };
29
+
30
+ defaultFuncs
31
+ .post(
32
+ "https://www.facebook.com/ajax/messaging/attachments/sharedphotos.php",
33
+ ctx.jar,
34
+ form
35
+ )
36
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
37
+ .then(function (resData) {
38
+ if (resData.error) {
39
+ throw resData;
40
+ }
41
+ return Promise.all(
42
+ resData.payload.imagesData.map(function (image) {
43
+ form = {
44
+ thread_id: threadID,
45
+ image_id: image.fbid
46
+ };
47
+ return defaultFuncs
48
+ .post(
49
+ "https://www.facebook.com/ajax/messaging/attachments/sharedphotos.php",
50
+ ctx.jar,
51
+ form
52
+ )
53
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
54
+ .then(function (resData) {
55
+ if (resData.error) {
56
+ throw resData;
57
+ }
58
+ // the response is pretty messy
59
+ const queryThreadID =
60
+ resData.jsmods.require[0][3][1].query_metadata.query_path[0]
61
+ .message_thread;
62
+ const imageData =
63
+ resData.jsmods.require[0][3][1].query_results[queryThreadID]
64
+ .message_images.edges[0].node.image2;
65
+ return imageData;
66
+ });
67
+ })
68
+ );
69
+ })
70
+ .then(function (resData) {
71
+ callback(null, resData);
72
+ })
73
+ .catch(function (err) {
74
+ log.error("Error in getThreadPictures", err);
75
+ callback(err);
76
+ });
77
+ return returnPromise;
78
+ };
79
+ };
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ function formatData(data) {
7
+ return {
8
+ userID: utils.formatID(data.uid.toString()),
9
+ photoUrl: data.photo,
10
+ indexRank: data.index_rank,
11
+ name: data.text,
12
+ isVerified: data.is_verified,
13
+ profileUrl: data.path,
14
+ category: data.category,
15
+ score: data.score,
16
+ type: data.type
17
+ };
18
+ }
19
+
20
+ module.exports = function (defaultFuncs, api, ctx) {
21
+ return function getUserID(name, callback) {
22
+ let resolveFunc = function () { };
23
+ let rejectFunc = function () { };
24
+ const returnPromise = new Promise(function (resolve, reject) {
25
+ resolveFunc = resolve;
26
+ rejectFunc = reject;
27
+ });
28
+
29
+ if (!callback) {
30
+ callback = function (err, friendList) {
31
+ if (err) {
32
+ return rejectFunc(err);
33
+ }
34
+ resolveFunc(friendList);
35
+ };
36
+ }
37
+
38
+ const form = {
39
+ value: name.toLowerCase(),
40
+ viewer: ctx.i_userID || ctx.userID,
41
+ rsp: "search",
42
+ context: "search",
43
+ path: "/home.php",
44
+ request_id: utils.getGUID()
45
+ };
46
+
47
+ defaultFuncs
48
+ .get("https://www.facebook.com/ajax/typeahead/search.php", ctx.jar, form)
49
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
50
+ .then(function (resData) {
51
+ if (resData.error) {
52
+ throw resData;
53
+ }
54
+
55
+ const data = resData.payload.entries;
56
+
57
+ callback(null, data.map(formatData));
58
+ })
59
+ .catch(function (err) {
60
+ log.error("getUserID", err);
61
+ return callback(err);
62
+ });
63
+
64
+ return returnPromise;
65
+ };
66
+ };
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ function formatData(data) {
7
+ var retObj = {};
8
+
9
+ for (var prop in data) {
10
+ // eslint-disable-next-line no-prototype-builtins
11
+ if (data.hasOwnProperty(prop)) {
12
+ var innerObj = data[prop];
13
+ retObj[prop] = {
14
+ name: innerObj.name,
15
+ firstName: innerObj.firstName,
16
+ vanity: innerObj.vanity,
17
+ thumbSrc: innerObj.thumbSrc,
18
+ profileUrl: innerObj.uri,
19
+ gender: innerObj.gender,
20
+ type: innerObj.type,
21
+ isFriend: innerObj.is_friend,
22
+ isBirthday: !!innerObj.is_birthday,
23
+ searchTokens: innerObj.searchTokens,
24
+ alternateName: innerObj.alternateName,
25
+ isBlocked: innerObj.is_blocked
26
+ };
27
+ }
28
+ }
29
+
30
+ return retObj;
31
+ }
32
+
33
+ function formatDataGraph(userData, userIDs) {
34
+ var Obj = {};
35
+
36
+ userIDs.map(function (c, i) {
37
+ var res = userData[i];
38
+ return !res.data ? Obj[c] = {
39
+ id: c,
40
+ name: res.name,
41
+ shortName: res.short_name || null,
42
+ verified: res.is_verified,
43
+ email: res.email || null,
44
+ website: res.website || null,
45
+ follower: !!res.subscribers ? res.subscribers.summary.total_count : null,
46
+ lover: res.significant_other || null,
47
+ cover: !!res.cover ? res.cover.source : null,
48
+ first_name: res.first_name || null,
49
+ middle_name: res.middle_name || null,
50
+ last_name: res.last_name || null,
51
+ about: res.about || null,
52
+ birthday: res.birthday || null,
53
+ locale: res.locale,
54
+ languages: res.languages || [],
55
+ gender: res.gender || null,
56
+ hometown: !!res.hometown ? res.hometown.name : null,
57
+ profileUrl: res.link || null,
58
+ location: !!res.location ? res.location.name : null,
59
+ username: res.username || null,
60
+ avatar: !!res.picture ? res.picture.data.url : null,
61
+ relationship_status: !!res.relationship_status ? res.relationship_status : null,
62
+ subscribers: !!res.subscribers ? res.subscribers.data : null,
63
+ favorite_athletes: !!res.favorite_athletes ? res.favorite_athletes.map(function (v) {
64
+ return {
65
+ name: v.name
66
+ }
67
+ }) : [],
68
+ education: !!res.education ? res.education.map(function(v) {
69
+ return {
70
+ type: v.type,
71
+ school: v.school.name
72
+ }
73
+ }) : [],
74
+ work: !!res.work ? res.work : []
75
+ } : null;
76
+ });
77
+
78
+ return Obj;
79
+ }
80
+
81
+ module.exports = function (http, api, ctx) {
82
+ function handleGetData(userIDs) {
83
+ var cb;
84
+ var uploads = [];
85
+ var rtPromise = new Promise(function (resolve, reject) {
86
+ cb = (error, data) => data ? resolve(data) : reject(error);
87
+ });
88
+
89
+ // Getting User Data From GraphAPI In The Loop
90
+ userIDs.map(function (c) {
91
+ var mainPromise = utils
92
+ .get('https://graph.facebook.com/' + c, ctx.jar, {
93
+ fields: 'name,is_verified,cover,first_name,email,about,birthday,gender,website,hometown,link,location,quotes,relationship_status,significant_other,username,subscribers.limite(0),short_name,last_name,middle_name,education,picture,work,languages,favorite_athletes,locale',
94
+ access_token: ctx.access_token
95
+ }, ctx.globalOptions)
96
+ .then(function (res) {
97
+ return res.body.indexOf('<') < 0 ? JSON.parse(res.body) : { data: 404 };
98
+ })
99
+ .catch(cb);
100
+ return uploads.push(mainPromise);
101
+ });
102
+
103
+ // resolve all promise
104
+ Promise
105
+ .all(uploads)
106
+ .then(function (userData) {
107
+ return cb(null, formatDataGraph(userData, userIDs));
108
+ })
109
+ .catch(function (err) {
110
+ return cb(err);
111
+ });
112
+
113
+ return rtPromise;
114
+ }
115
+
116
+ return function getUserInfo(userIDs, useGraph, callback) {
117
+ var cb;
118
+ var rtPromise = new Promise(function (resolve, reject) {
119
+ cb = (error, data) => data ? resolve(data) : reject(error);
120
+ });
121
+
122
+ if (typeof useGraph == 'function') {
123
+ callback = useGraph;
124
+ useGraph = false;
125
+ }
126
+ if (typeof callback == 'function') cb = callback;
127
+ if (Array.isArray(userIDs) == false) userIDs = [userIDs];
128
+
129
+ if (useGraph) {
130
+ if (!ctx.access_token) {
131
+ var err = 'Cant get access_token, please let the "useGraph" feature is false';
132
+ log.error('getUserInfo', err);
133
+ return cb(err);
134
+ }
135
+ handleGetData(userIDs)
136
+ .then(function (res) {
137
+ return cb(null, res);
138
+ })
139
+ .catch(function (err) {
140
+ log.error('getUserInfo', err);
141
+ return cb(err);
142
+ });
143
+ } else {
144
+ var form = {};
145
+ userIDs.map(function(v, i) {
146
+ form["ids[" + i + "]"] = v;
147
+ });
148
+ http
149
+ .post("https://www.facebook.com/chat/user_info/", ctx.jar, form)
150
+ .then(utils.parseAndCheckLogin(ctx, http))
151
+ .then(function(res) {
152
+ if (res.error || res.errors) throw res;
153
+ return cb(null, formatData(res.payload.profiles));
154
+ })
155
+ .catch(function(err) {
156
+ log.error("getUserInfo", err);
157
+ return cb(err);
158
+ });
159
+ }
160
+
161
+ return rtPromise;
162
+ }
163
+ }