alicezetion 1.0.3 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -1
  2. package/.cache/replit/modules.stamp +1 -0
  3. package/.cache/replit/nix/env.json +1 -1
  4. package/index.js +536 -604
  5. package/package.json +78 -75
  6. package/replit.nix +6 -0
  7. package/src/addExternalModule.js +15 -0
  8. package/{alice → src}/addUserToGroup.js +77 -113
  9. package/src/changeAdminStatus.js +47 -0
  10. package/src/changeArchivedStatus.js +41 -0
  11. package/{alice → src}/changeBio.js +64 -77
  12. package/{alice → src}/changeBlockedStatus.js +36 -47
  13. package/{alice → src}/changeGroupImage.js +105 -129
  14. package/src/changeNickname.js +43 -0
  15. package/{alice → src}/changeThreadColor.js +61 -71
  16. package/src/changeThreadEmoji.js +41 -0
  17. package/src/chat.js +315 -0
  18. package/{alice → src}/createNewGroup.js +70 -86
  19. package/{alice → src}/createPoll.js +59 -71
  20. package/src/deleteMessage.js +44 -0
  21. package/src/deleteThread.js +42 -0
  22. package/src/forwardAttachment.js +47 -0
  23. package/src/forwardMessage.js +0 -0
  24. package/{alice → src}/getCurrentUserID.js +7 -7
  25. package/{alice → src}/getEmojiUrl.js +27 -29
  26. package/{alice → src}/getFriendsList.js +73 -84
  27. package/{alice → src}/getThreadHistory.js +537 -645
  28. package/src/getThreadHistoryDeprecated.js +71 -0
  29. package/{alice → src}/getThreadInfo.js +171 -206
  30. package/src/getThreadInfoDeprecated.js +56 -0
  31. package/{alice → src}/getThreadList.js +213 -238
  32. package/src/getThreadListDeprecated.js +46 -0
  33. package/src/getThreadPictures.js +59 -0
  34. package/{alice → src}/getUserID.js +61 -66
  35. package/{alice → src}/getUserInfo.js +66 -72
  36. package/src/handleFriendRequest.js +46 -0
  37. package/src/handleMessageRequest.js +47 -0
  38. package/{alice → src}/httpGet.js +47 -52
  39. package/{alice → src}/httpPost.js +47 -52
  40. package/src/listen.js +553 -0
  41. package/src/listenMqtt-Test.js +687 -0
  42. package/src/listenMqtt.js +677 -0
  43. package/{alice → src}/logout.js +68 -75
  44. package/{alice → src}/markAsDelivered.js +47 -58
  45. package/{alice → src}/markAsRead.js +70 -80
  46. package/{alice/seen.js → src/markAsReadAll.js} +39 -49
  47. package/{alice → src}/markAsSeen.js +48 -59
  48. package/{alice → src}/muteThread.js +45 -52
  49. package/src/removeUserFromGroup.js +45 -0
  50. package/{alice → src}/resolvePhotoUrl.js +36 -45
  51. package/src/searchForThread.js +42 -0
  52. package/{alice → src}/sendTypingIndicator.js +70 -103
  53. package/{alice/react.js → src/setMessageReaction.js} +103 -117
  54. package/{alice → src}/setPostReaction.js +63 -76
  55. package/{alice → src}/setTitle.js +70 -86
  56. package/src/threadColors.js +41 -0
  57. package/{alice → src}/unfriend.js +42 -52
  58. package/{alice → src}/unsendMessage.js +39 -49
  59. package/utils.js +1193 -1357
  60. package/alice/addExternalModule.js +0 -19
  61. package/alice/changeAdminStatus.js +0 -79
  62. package/alice/changeArchivedStatus.js +0 -55
  63. package/alice/changeNickname.js +0 -59
  64. package/alice/changeThreadEmoji.js +0 -55
  65. package/alice/chat.js +0 -459
  66. package/alice/deleteMessage.js +0 -56
  67. package/alice/deleteThread.js +0 -56
  68. package/alice/forwardAttachment.js +0 -60
  69. package/alice/getThreadHistoryDeprecated.js +0 -93
  70. package/alice/getThreadInfoDeprecated.js +0 -80
  71. package/alice/getThreadListDeprecated.js +0 -75
  72. package/alice/getThreadPictures.js +0 -79
  73. package/alice/handleFriendRequest.js +0 -61
  74. package/alice/handleMessageRequest.js +0 -65
  75. package/alice/listenMqtt.js +0 -789
  76. package/alice/removeUserFromGroup.js +0 -79
  77. package/alice/searchForThread.js +0 -53
  78. package/alice/threadColors.js +0 -57
  79. package/test/data/shareAttach.js +0 -146
  80. package/test/data/something.mov +0 -0
  81. package/test/data/test.png +0 -0
  82. package/test/data/test.txt +0 -7
  83. package/test/example-config.json +0 -18
  84. package/test/test-page.js +0 -140
  85. package/test/test.js +0 -385
@@ -0,0 +1,71 @@
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 getThreadHistory(threadID, amount, timestamp, 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, threadInfo) {
17
+ if (err) return rejectFunc(err);
18
+ resolveFunc(threadInfo);
19
+ };
20
+ }
21
+
22
+ if (!callback) throw { error: "getThreadHistory: need callback" };
23
+ var form = {
24
+ client: "mercury"
25
+ };
26
+
27
+ api.getUserInfo(threadID, function (err, res) {
28
+ if (err) return callback(err);
29
+ var key = Object.keys(res).length > 0 ? "user_ids" : "thread_fbids";
30
+ form["messages[" + key + "][" + threadID + "][offset]"] = 0;
31
+ form["messages[" + key + "][" + threadID + "][timestamp]"] = timestamp;
32
+ form["messages[" + key + "][" + threadID + "][limit]"] = amount;
33
+
34
+ if (ctx.globalOptions.pageID) form.request_user_id = ctx.globalOptions.pageID;
35
+
36
+ defaultFuncs
37
+ .post("https://www.facebook.com/ajax/mercury/thread_info.php", ctx.jar, form)
38
+ .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." };
42
+
43
+ // Asking for message history from a thread with no message history
44
+ // will return undefined for actions here
45
+ if (!resData.payload.actions) resData.payload.actions = [];
46
+
47
+ var userIDs = {};
48
+ resData.payload.actions.forEach(v => userIDs[v.author.split(":").pop()] = "");
49
+
50
+ api.getUserInfo(Object.keys(userIDs), function (err, data) {
51
+ if (err) return callback(err); //callback({error: "Could not retrieve user information in getThreadHistory."});
52
+
53
+ resData.payload.actions.forEach(function (v) {
54
+ var sender = data[v.author.split(":").pop()];
55
+ if (sender) v.sender_name = sender.name;
56
+ else v.sender_name = "Facebook User";
57
+ v.sender_fbid = v.author;
58
+ delete v.author;
59
+ });
60
+
61
+ callback(null, resData.payload.actions.map(utils.formatHistoryMessage));
62
+ });
63
+ })
64
+ .catch(function (err) {
65
+ log.error("getThreadHistory", err);
66
+ return callback(err);
67
+ });
68
+ });
69
+ return returnPromise;
70
+ };
71
+ };
@@ -1,206 +1,171 @@
1
- "use strict";
2
-
3
- var utils = require("../utils");
4
- var 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(data) {
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;
43
-
44
- // Remove me
45
- var lastM = messageThread.last_message;
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;
56
- var lastR = messageThread.last_read_receipt;
57
- var lastReadTimestamp =
58
- lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
59
- ? lastR.nodes[0].timestamp_precise
60
- : null;
61
-
62
- return {
63
- threadID: threadID,
64
- threadName: messageThread.name,
65
- participantIDs: messageThread.all_participants.edges.map(d => d.node.messaging_actor.id),
66
- userInfo: messageThread.all_participants.edges.map(d => ({
67
- id: d.node.messaging_actor.id,
68
- name: d.node.messaging_actor.name,
69
- firstName: d.node.messaging_actor.short_name,
70
- vanity: d.node.messaging_actor.username,
71
- thumbSrc: d.node.messaging_actor.big_image_src.uri,
72
- profileUrl: d.node.messaging_actor.big_image_src.uri,
73
- gender: d.node.messaging_actor.gender,
74
- type: d.node.messaging_actor.__typename,
75
- isFriend: d.node.messaging_actor.is_viewer_friend,
76
- isBirthday: !!d.node.messaging_actor.is_birthday //not sure?
77
- })),
78
- unreadCount: messageThread.unread_count,
79
- messageCount: messageThread.messages_count,
80
- timestamp: messageThread.updated_time_precise,
81
- muteUntil: messageThread.mute_until,
82
- isGroup: messageThread.thread_type == "GROUP",
83
- isSubscribed: messageThread.is_viewer_subscribed,
84
- isArchived: messageThread.has_viewer_archived,
85
- folder: messageThread.folder,
86
- cannotReplyReason: messageThread.cannot_reply_reason,
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,
98
- nicknames:
99
- messageThread.customization_info &&
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
- )
108
- : {},
109
- adminIDs: messageThread.thread_admins,
110
- approvalMode: Boolean(messageThread.approval_mode),
111
- approvalQueue: messageThread.group_approval_queue.nodes.map(a => ({
112
- inviterID: a.inviter.id,
113
- requesterID: a.requester.id,
114
- timestamp: a.request_timestamp,
115
- request_source: a.request_source // @Undocumented
116
- })),
117
-
118
- // @Undocumented
119
- reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
120
- mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
121
- isPinProtected: messageThread.is_pin_protected,
122
- relatedPageThread: messageThread.related_page_thread,
123
-
124
- // @Legacy
125
- name: messageThread.name,
126
- snippet: snippetText,
127
- snippetSender: snippetID,
128
- snippetAttachments: [],
129
- serverTimestamp: messageThread.updated_time_precise,
130
- imageSrc: messageThread.image ? messageThread.image.uri : null,
131
- isCanonicalUser: messageThread.is_canonical_neo_user,
132
- isCanonical: messageThread.thread_type != "GROUP",
133
- recipientsLoadable: true,
134
- hasEmailParticipant: false,
135
- readOnly: false,
136
- canReply: messageThread.cannot_reply_reason == null,
137
- lastMessageTimestamp: messageThread.last_message
138
- ? messageThread.last_message.timestamp_precise
139
- : null,
140
- lastMessageType: "message",
141
- lastReadTimestamp: lastReadTimestamp,
142
- threadType: messageThread.thread_type == "GROUP" ? 2 : 1
143
- };
144
- }
145
-
146
- module.exports = function(defaultFuncs, api, ctx) {
147
- return function getThreadInfoGraphQL(threadID, callback) {
148
- var resolveFunc = function(){};
149
- var rejectFunc = function(){};
150
- var returnPromise = new Promise(function (resolve, reject) {
151
- resolveFunc = resolve;
152
- rejectFunc = reject;
153
- });
154
-
155
- if (utils.getType(callback) != "Function" && utils.getType(callback) != "AsyncFunction") {
156
- callback = function (err, data) {
157
- if (err) {
158
- return rejectFunc(err);
159
- }
160
- resolveFunc(data);
161
- };
162
- }
163
-
164
- // `queries` has to be a string. I couldn't tell from the dev console. This
165
- // took me a really long time to figure out. I deserve a cookie for this.
166
- var form = {
167
- queries: JSON.stringify({
168
- o0: {
169
- // This doc_id is valid as of July 20th, 2020
170
- doc_id: "3449967031715030",
171
- query_params: {
172
- id: threadID,
173
- message_limit: 0,
174
- load_messages: false,
175
- load_read_receipts: false,
176
- before: null
177
- }
178
- }
179
- }),
180
- batch_name: "MessengerGraphQLThreadFetcher"
181
- };
182
-
183
- defaultFuncs
184
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
185
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
186
- .then(function(resData) {
187
- if (resData.error) {
188
- throw resData;
189
- }
190
- // This returns us an array of things. The last one is the success /
191
- // failure one.
192
- // @TODO What do we do in this case?
193
- if (resData[resData.length - 1].error_results !== 0) {
194
- console.error("GetThreadInfo", "Well darn there was an error_result");
195
- }
196
-
197
- callback(null, formatThreadGraphQLResponse(resData[0]));
198
- })
199
- .catch(function(err) {
200
- log.error("getThreadInfoGraphQL", err);
201
- return callback(err);
202
- });
203
-
204
- return returnPromise;
205
- };
206
- };
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var 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(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;
36
+
37
+ // Remove me
38
+ 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;
41
+ 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;
43
+
44
+ return {
45
+ threadID: threadID,
46
+ threadName: messageThread.name,
47
+ participantIDs: messageThread.all_participants.edges.map(d => d.node.messaging_actor.id),
48
+ userInfo: messageThread.all_participants.edges.map(d => ({
49
+ id: d.node.messaging_actor.id,
50
+ name: d.node.messaging_actor.name,
51
+ firstName: d.node.messaging_actor.short_name,
52
+ vanity: d.node.messaging_actor.username,
53
+ thumbSrc: d.node.messaging_actor.big_image_src.uri,
54
+ profileUrl: d.node.messaging_actor.big_image_src.uri,
55
+ gender: d.node.messaging_actor.gender,
56
+ type: d.node.messaging_actor.__typename,
57
+ isFriend: d.node.messaging_actor.is_viewer_friend,
58
+ isBirthday: !!d.node.messaging_actor.is_birthday //not sure?
59
+ })),
60
+ unreadCount: messageThread.unread_count,
61
+ messageCount: messageThread.messages_count,
62
+ timestamp: messageThread.updated_time_precise,
63
+ muteUntil: messageThread.mute_until,
64
+ isGroup: messageThread.thread_type == "GROUP",
65
+ isSubscribed: messageThread.is_viewer_subscribed,
66
+ isArchived: messageThread.has_viewer_archived,
67
+ folder: messageThread.folder,
68
+ 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,
72
+ nicknames:
73
+ 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
+ }, {})
79
+ : {},
80
+ adminIDs: messageThread.thread_admins,
81
+ approvalMode: Boolean(messageThread.approval_mode),
82
+ approvalQueue: messageThread.group_approval_queue.nodes.map(a => ({
83
+ inviterID: a.inviter.id,
84
+ requesterID: a.requester.id,
85
+ timestamp: a.request_timestamp,
86
+ request_source: a.request_source // @Undocumented
87
+ })),
88
+
89
+ // @Undocumented
90
+ reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
91
+ mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
92
+ isPinProtected: messageThread.is_pin_protected,
93
+ relatedPageThread: messageThread.related_page_thread,
94
+
95
+ // @Legacy
96
+ name: messageThread.name,
97
+ snippet: snippetText,
98
+ snippetSender: snippetID,
99
+ snippetAttachments: [],
100
+ serverTimestamp: messageThread.updated_time_precise,
101
+ imageSrc: messageThread.image ? messageThread.image.uri : null,
102
+ isCanonicalUser: messageThread.is_canonical_neo_user,
103
+ isCanonical: messageThread.thread_type != "GROUP",
104
+ recipientsLoadable: true,
105
+ hasEmailParticipant: false,
106
+ readOnly: false,
107
+ canReply: messageThread.cannot_reply_reason == null,
108
+ lastMessageTimestamp: messageThread.last_message ? messageThread.last_message.timestamp_precise : null,
109
+ lastMessageType: "message",
110
+ lastReadTimestamp: lastReadTimestamp,
111
+ threadType: messageThread.thread_type == "GROUP" ? 2 : 1
112
+ };
113
+ }
114
+
115
+ 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
+ });
123
+
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
+
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
+ };
149
+
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
+ });
168
+
169
+ return returnPromise;
170
+ };
171
+ };
@@ -0,0 +1,56 @@
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, data) {
17
+ if (err) return rejectFunc(err);
18
+ resolveFunc(data);
19
+ };
20
+ }
21
+
22
+ var form = {
23
+ client: "mercury"
24
+ };
25
+
26
+ api.getUserInfo(threadID, function (err, userRes) {
27
+ if (err) return callback(err);
28
+ var key = Object.keys(userRes).length > 0 ? "user_ids" : "thread_fbids";
29
+ form["threads[" + key + "][0]"] = threadID;
30
+
31
+ if (ctx.globalOptions.pageId) form.request_user_id = ctx.globalOptions.pageId;
32
+
33
+ defaultFuncs
34
+ .post("https://www.facebook.com/ajax/mercury/thread_info.php", ctx.jar, form)
35
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
36
+ .then(function (resData) {
37
+ if (resData.error) throw resData;
38
+ else if (!resData.payload) throw { error: "Could not retrieve thread Info." };
39
+
40
+ var threadData = resData.payload.threads[0];
41
+ var userData = userRes[threadID];
42
+
43
+ if (threadData == null) throw { error: "ThreadData is null" };
44
+
45
+ threadData.name = userData != null && userData.name != null ? userData.name : threadData.name;
46
+ threadData.image_src = userData != null && userData.thumbSrc != null ? userData.thumbSrc : threadData.image_src;
47
+ callback(null, utils.formatThread(threadData));
48
+ })
49
+ .catch(function (err) {
50
+ log.error("getThreadInfo", err);
51
+ return callback(err);
52
+ });
53
+ });
54
+ return returnPromise;
55
+ };
56
+ };