@cexy/hoonfca 1.0.0 → 1.0.2
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.
- package/.travis.yml +6 -0
- package/LICENSE-MIT +21 -0
- package/index.d.ts +620 -0
- package/index.js +745 -433
- package/package.json +45 -6
- package/src/addExternalModule.js +14 -16
- package/src/addUserToGroup.js +45 -30
- package/src/changeAdminStatus.js +39 -42
- package/src/changeApprovalMode.js +79 -0
- package/src/changeArchivedStatus.js +19 -15
- package/src/changeBio.js +18 -16
- package/src/changeBlockedStatus.js +14 -12
- package/src/changeBlockedStatusMqtt.js +38 -17
- package/src/changeGroupImage.js +100 -77
- package/src/changeNickname.js +12 -11
- package/src/changeThreadColor.js +25 -16
- package/src/changeThreadEmoji.js +11 -10
- package/src/createNewGroup.js +21 -14
- package/src/createPoll.js +87 -21
- package/src/deleteMessage.js +18 -17
- package/src/deleteThread.js +18 -17
- package/src/editMessage.js +28 -31
- package/src/forwardAttachment.js +22 -19
- package/src/forwardMessage.js +63 -0
- package/src/getCurrentUserID.js +4 -2
- package/src/getEmojiUrl.js +20 -9
- package/src/getFriendsList.js +21 -18
- package/src/getGroupsList.js +83 -0
- package/src/getMarketplace.js +84 -0
- package/src/getNotifications.js +86 -0
- package/src/getPagesList.js +83 -0
- package/src/getStories.js +88 -0
- package/src/getThreadHistory.js +277 -126
- package/src/getThreadInfo.js +143 -115
- package/src/getThreadList.js +216 -143
- package/src/getThreadPictures.js +26 -32
- package/src/getUserID.js +13 -14
- package/src/getUserInfo.js +107 -68
- package/src/handleFriendRequest.js +16 -15
- package/src/handleMessageRequest.js +15 -15
- package/src/httpGet.js +36 -31
- package/src/httpPost.js +36 -31
- package/src/listenMqtt.js +705 -370
- package/src/logout.js +26 -28
- package/src/markAsDelivered.js +22 -17
- package/src/markAsRead.js +63 -49
- package/src/markAsReadAll.js +17 -13
- package/src/markAsSeen.js +23 -19
- package/src/muteThread.js +17 -14
- package/src/pinMessage.js +23 -22
- package/src/removeUserFromGroup.js +42 -22
- package/src/resolvePhotoUrl.js +15 -17
- package/src/searchForThread.js +18 -20
- package/src/searchUsers.js +89 -0
- package/src/sendComment.js +161 -0
- package/src/sendMessage.js +65 -52
- package/src/sendTypingIndicator.js +173 -48
- package/src/setBio.js +86 -0
- package/src/setMessageReaction.js +76 -16
- package/src/setPostReaction.js +29 -61
- package/src/setTheme.js +313 -0
- package/src/setTitle.js +27 -37
- package/src/shareContact.js +34 -82
- package/src/shareLink.js +56 -99
- package/src/threadColors.js +35 -97
- package/src/unfriend.js +15 -20
- package/src/unsendMessage.js +71 -18
- package/utils.js +1000 -472
- package/README.md +0 -83
- package/replit.nix +0 -3
- package/src/changeAvatar.js +0 -89
- package/src/changeCover.js +0 -92
- package/src/changeName.js +0 -106
- package/src/changeUsername.js +0 -80
- package/src/createCommentPost.js +0 -196
- package/src/createPost.js +0 -285
- package/src/data/getThreadInfo.json +0 -1
- package/src/follow.js +0 -71
- package/src/getAccess.js +0 -130
- package/src/getAvatarUser.js +0 -88
- package/src/getBotInitialData.js +0 -59
- package/src/getCtx.js +0 -5
- package/src/getMessage.js +0 -827
- package/src/getOptions.js +0 -5
- package/src/getRegion.js +0 -7
- package/src/getThreadHistoryDeprecated.js +0 -95
- package/src/getThreadInfoDeprecated.js +0 -77
- package/src/getThreadListDeprecated.js +0 -86
- package/src/httpPostFormData.js +0 -58
- package/src/listenNotification.js +0 -96
- package/src/refreshFb_dtsg.js +0 -75
- package/src/searchStickers.js +0 -59
- package/src/sendMessageMqtt.js +0 -326
- package/src/setMessageReactionMqtt.js +0 -74
- package/src/setProfileGuard.js +0 -66
- package/src/setStoryReaction.js +0 -97
- package/src/stopListenMqtt.js +0 -47
- package/src/uploadAttachment.js +0 -98
package/src/getThreadList.js
CHANGED
|
@@ -1,168 +1,233 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const utils = require("../utils");
|
|
4
|
+
const log = require("npmlog");
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
time: reminder.time,
|
|
11
|
-
eventType: reminder.lightweight_event_type?.toLowerCase(),
|
|
12
|
-
locationName: reminder.location_name,
|
|
13
|
-
locationCoordinates: reminder.location_coordinates,
|
|
14
|
-
locationPage: reminder.location_page,
|
|
15
|
-
eventStatus: reminder.lightweight_event_status?.toLowerCase(),
|
|
16
|
-
note: reminder.note,
|
|
17
|
-
repeatMode: reminder.repeat_mode?.toLowerCase(),
|
|
18
|
-
eventTitle: reminder.event_title,
|
|
19
|
-
triggerMessage: reminder.trigger_message,
|
|
20
|
-
secondsToNotifyBefore: reminder.seconds_to_notify_before,
|
|
21
|
-
allowsRsvp: reminder.allows_rsvp,
|
|
22
|
-
relatedEvent: reminder.related_event,
|
|
23
|
-
members: (reminder.event_reminder_members?.edges || []).map(member => ({
|
|
24
|
-
memberID: member.node?.id,
|
|
25
|
-
state: member.guest_list_state?.toLowerCase(),
|
|
26
|
-
})),
|
|
27
|
-
};
|
|
6
|
+
function createProfileUrl(url, username, id) {
|
|
7
|
+
if (url) return url;
|
|
8
|
+
return (
|
|
9
|
+
"https://www.facebook.com/" + (username || utils.formatID(id.toString()))
|
|
10
|
+
);
|
|
28
11
|
}
|
|
29
12
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
13
|
+
function formatParticipants(participants) {
|
|
14
|
+
return participants.edges.map((p) => {
|
|
15
|
+
p = p.node.messaging_actor;
|
|
16
|
+
switch (p["__typename"]) {
|
|
17
|
+
case "User":
|
|
18
|
+
return {
|
|
19
|
+
accountType: p["__typename"],
|
|
20
|
+
userID: utils.formatID(p.id.toString()), // do we need .toString()? when it is not a string?
|
|
21
|
+
name: p.name,
|
|
22
|
+
shortName: p.short_name,
|
|
23
|
+
gender: p.gender,
|
|
24
|
+
url: p.url, // how about making it profileURL
|
|
25
|
+
profilePicture: p.big_image_src.uri,
|
|
26
|
+
username: p.username || null,
|
|
27
|
+
// TODO: maybe better names for these?
|
|
28
|
+
isViewerFriend: p.is_viewer_friend, // true/false
|
|
29
|
+
isMessengerUser: p.is_messenger_user, // true/false
|
|
30
|
+
isVerified: p.is_verified, // true/false
|
|
31
|
+
isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
|
|
32
|
+
isViewerCoworker: p.is_viewer_coworker, // true/false
|
|
33
|
+
isEmployee: p.is_employee, // null? when it is something other? can someone check?
|
|
34
|
+
};
|
|
35
|
+
case "Page":
|
|
36
|
+
return {
|
|
37
|
+
accountType: p["__typename"],
|
|
38
|
+
userID: utils.formatID(p.id.toString()), // or maybe... pageID?
|
|
39
|
+
name: p.name,
|
|
40
|
+
url: p.url,
|
|
41
|
+
profilePicture: p.big_image_src.uri,
|
|
42
|
+
username: p.username || null,
|
|
43
|
+
// uhm... better names maybe?
|
|
44
|
+
acceptsMessengerUserFeedback: p.accepts_messenger_user_feedback, // true/false
|
|
45
|
+
isMessengerUser: p.is_messenger_user, // true/false
|
|
46
|
+
isVerified: p.is_verified, // true/false
|
|
47
|
+
isMessengerPlatformBot: p.is_messenger_platform_bot, // true/false
|
|
48
|
+
isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
|
|
49
|
+
};
|
|
50
|
+
case "ReducedMessagingActor":
|
|
51
|
+
return {
|
|
52
|
+
accountType: p["__typename"],
|
|
53
|
+
userID: utils.formatID(p.id.toString()),
|
|
54
|
+
name: p.name,
|
|
55
|
+
url: createProfileUrl(p.url, p.username, p.id), // in this case p.url is null all the time
|
|
56
|
+
profilePicture: p.big_image_src.uri, // in this case it is default facebook photo, we could determine gender using it
|
|
57
|
+
username: p.username || null, // maybe we could use it to generate profile URL?
|
|
58
|
+
isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
|
|
59
|
+
};
|
|
60
|
+
case "UnavailableMessagingActor":
|
|
61
|
+
return {
|
|
62
|
+
accountType: p["__typename"],
|
|
63
|
+
userID: utils.formatID(p.id.toString()),
|
|
64
|
+
name: p.name, // "Facebook User" in user's language
|
|
65
|
+
url: createProfileUrl(p.url, p.username, p.id), // in this case p.url is null all the time
|
|
66
|
+
profilePicture: p.big_image_src.uri, // default male facebook photo
|
|
67
|
+
username: p.username || null, // maybe we could use it to generate profile URL?
|
|
68
|
+
isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
|
|
69
|
+
};
|
|
70
|
+
default:
|
|
71
|
+
log.warn(
|
|
72
|
+
"getThreadList",
|
|
73
|
+
"Found participant with unsupported typename. Please open an issue at https://github.com/Schmavery/fca-unofficial/issues\n" +
|
|
74
|
+
JSON.stringify(p, null, 2),
|
|
75
|
+
);
|
|
76
|
+
return {
|
|
77
|
+
accountType: p["__typename"],
|
|
78
|
+
userID: utils.formatID(p.id.toString()),
|
|
79
|
+
name: p.name || `[unknown ${p["__typename"]}]`, // probably it will always be something... but fallback to [unknown], just in case
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// "FF8C0077" -> "8C0077"
|
|
86
|
+
function formatColor(color) {
|
|
87
|
+
if (color && color.match(/^(?:[0-9a-fA-F]{8})$/g)) {
|
|
88
|
+
return color.slice(2);
|
|
89
|
+
}
|
|
90
|
+
return color;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function getThreadName(t) {
|
|
94
|
+
if (t.name || t.thread_key.thread_fbid) return t.name;
|
|
95
|
+
|
|
96
|
+
for (let po of t.all_participants.edges) {
|
|
97
|
+
let p = po.node;
|
|
98
|
+
if (p.messaging_actor.id === t.thread_key.other_user_id)
|
|
99
|
+
return p.messaging_actor.name;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function mapNicknames(customizationInfo) {
|
|
104
|
+
return customizationInfo && customizationInfo.participant_customizations
|
|
105
|
+
? customizationInfo.participant_customizations.map((u) => {
|
|
106
|
+
return {
|
|
107
|
+
userID: u.participant_id,
|
|
108
|
+
nickname: u.nickname,
|
|
109
|
+
};
|
|
110
|
+
})
|
|
111
|
+
: [];
|
|
115
112
|
}
|
|
116
113
|
|
|
117
114
|
function formatThreadList(data) {
|
|
118
|
-
return data.map(t =>
|
|
115
|
+
return data.map((t) => {
|
|
116
|
+
let lastMessageNode =
|
|
117
|
+
t.last_message && t.last_message.nodes && t.last_message.nodes.length > 0
|
|
118
|
+
? t.last_message.nodes[0]
|
|
119
|
+
: null;
|
|
120
|
+
return {
|
|
121
|
+
threadID: t.thread_key
|
|
122
|
+
? utils.formatID(t.thread_key.thread_fbid || t.thread_key.other_user_id)
|
|
123
|
+
: null, // shall never be null
|
|
124
|
+
name: getThreadName(t),
|
|
125
|
+
unreadCount: t.unread_count,
|
|
126
|
+
messageCount: t.messages_count,
|
|
127
|
+
imageSrc: t.image ? t.image.uri : null,
|
|
128
|
+
emoji: t.customization_info ? t.customization_info.emoji : null,
|
|
129
|
+
color: formatColor(
|
|
130
|
+
t.customization_info
|
|
131
|
+
? t.customization_info.outgoing_bubble_color
|
|
132
|
+
: null,
|
|
133
|
+
),
|
|
134
|
+
nicknames: mapNicknames(t.customization_info),
|
|
135
|
+
muteUntil: t.mute_until,
|
|
136
|
+
participants: formatParticipants(t.all_participants),
|
|
137
|
+
adminIDs: t.thread_admins.map((a) => a.id),
|
|
138
|
+
folder: t.folder,
|
|
139
|
+
isGroup: t.thread_type === "GROUP",
|
|
140
|
+
// rtc_call_data: t.rtc_call_data, // TODO: format and document this
|
|
141
|
+
// isPinProtected: t.is_pin_protected, // feature from future? always false (2018-04-04)
|
|
142
|
+
customizationEnabled: t.customization_enabled, // false for ONE_TO_ONE with Page or ReducedMessagingActor
|
|
143
|
+
participantAddMode: t.participant_add_mode_as_string, // "ADD" if "GROUP" and null if "ONE_TO_ONE"
|
|
144
|
+
montageThread: t.montage_thread
|
|
145
|
+
? Buffer.from(t.montage_thread.id, "base64").toString()
|
|
146
|
+
: null, // base64 encoded string "message_thread:0000000000000000"
|
|
147
|
+
// it is not userID nor any other ID known to me...
|
|
148
|
+
// can somebody inspect it? where is it used?
|
|
149
|
+
// probably Messenger Day uses it
|
|
150
|
+
reactionsMuteMode: t.reactions_mute_mode,
|
|
151
|
+
mentionsMuteMode: t.mentions_mute_mode,
|
|
152
|
+
isArchived: t.has_viewer_archived,
|
|
153
|
+
isSubscribed: t.is_viewer_subscribed,
|
|
154
|
+
timestamp: t.updated_time_precise, // in miliseconds
|
|
155
|
+
// isCanonicalUser: t.is_canonical_neo_user, // is it always false?
|
|
156
|
+
// TODO: how about putting snippet in another object? current implementation does not handle every possibile message type etc.
|
|
157
|
+
snippet: lastMessageNode ? lastMessageNode.snippet : null,
|
|
158
|
+
snippetAttachments: lastMessageNode
|
|
159
|
+
? lastMessageNode.extensible_attachment
|
|
160
|
+
: null, // TODO: not sure if it works
|
|
161
|
+
snippetSender: lastMessageNode
|
|
162
|
+
? utils.formatID(
|
|
163
|
+
(
|
|
164
|
+
lastMessageNode.message_sender.messaging_actor.id || ""
|
|
165
|
+
).toString(),
|
|
166
|
+
)
|
|
167
|
+
: null,
|
|
168
|
+
lastMessageTimestamp: lastMessageNode
|
|
169
|
+
? lastMessageNode.timestamp_precise
|
|
170
|
+
: null, // timestamp in miliseconds
|
|
171
|
+
lastReadTimestamp:
|
|
172
|
+
t.last_read_receipt && t.last_read_receipt.nodes.length > 0
|
|
173
|
+
? t.last_read_receipt.nodes[0]
|
|
174
|
+
? t.last_read_receipt.nodes[0].timestamp_precise
|
|
175
|
+
: null
|
|
176
|
+
: null, // timestamp in miliseconds
|
|
177
|
+
cannotReplyReason: t.cannot_reply_reason, // TODO: inspect possible values
|
|
178
|
+
approvalMode: Boolean(t.approval_mode),
|
|
179
|
+
|
|
180
|
+
// @Legacy
|
|
181
|
+
participantIDs: formatParticipants(t.all_participants).map(
|
|
182
|
+
(participant) => participant.userID,
|
|
183
|
+
),
|
|
184
|
+
threadType: t.thread_type === "GROUP" ? 2 : 1, // "GROUP" or "ONE_TO_ONE"
|
|
185
|
+
};
|
|
186
|
+
});
|
|
119
187
|
}
|
|
120
188
|
|
|
121
189
|
module.exports = function (defaultFuncs, api, ctx) {
|
|
122
190
|
return function getThreadList(limit, timestamp, tags, callback) {
|
|
123
191
|
if (
|
|
124
192
|
!callback &&
|
|
125
|
-
(utils.getType(tags) === "Function" ||
|
|
193
|
+
(utils.getType(tags) === "Function" ||
|
|
194
|
+
utils.getType(tags) === "AsyncFunction")
|
|
126
195
|
) {
|
|
127
196
|
callback = tags;
|
|
128
197
|
tags = [""];
|
|
129
198
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
199
|
+
if (
|
|
200
|
+
utils.getType(limit) !== "Number" ||
|
|
201
|
+
!Number.isInteger(limit) ||
|
|
202
|
+
limit <= 0
|
|
203
|
+
) {
|
|
204
|
+
throw { error: "getThreadList: limit must be a positive integer" };
|
|
135
205
|
}
|
|
136
|
-
|
|
137
206
|
if (
|
|
138
207
|
utils.getType(timestamp) !== "Null" &&
|
|
139
208
|
(utils.getType(timestamp) !== "Number" || !Number.isInteger(timestamp))
|
|
140
209
|
) {
|
|
141
|
-
throw
|
|
142
|
-
error: "getThreadList: timestamp must be an integer or null",
|
|
143
|
-
});
|
|
210
|
+
throw { error: "getThreadList: timestamp must be an integer or null" };
|
|
144
211
|
}
|
|
145
|
-
|
|
146
212
|
if (utils.getType(tags) === "String") {
|
|
147
213
|
tags = [tags];
|
|
148
214
|
}
|
|
149
|
-
|
|
150
215
|
if (utils.getType(tags) !== "Array") {
|
|
151
|
-
throw
|
|
152
|
-
error: "getThreadList: tags must be an array",
|
|
153
|
-
message: "getThreadList: tags must be an array",
|
|
154
|
-
});
|
|
216
|
+
throw { error: "getThreadList: tags must be an array" };
|
|
155
217
|
}
|
|
156
218
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
219
|
+
var resolveFunc = function () {};
|
|
220
|
+
var rejectFunc = function () {};
|
|
221
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
|
160
222
|
resolveFunc = resolve;
|
|
161
223
|
rejectFunc = reject;
|
|
162
224
|
});
|
|
163
225
|
|
|
164
|
-
if (
|
|
165
|
-
callback
|
|
226
|
+
if (
|
|
227
|
+
utils.getType(callback) !== "Function" &&
|
|
228
|
+
utils.getType(callback) !== "AsyncFunction"
|
|
229
|
+
) {
|
|
230
|
+
callback = function (err, data) {
|
|
166
231
|
if (err) {
|
|
167
232
|
return rejectFunc(err);
|
|
168
233
|
}
|
|
@@ -171,10 +236,11 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
171
236
|
}
|
|
172
237
|
|
|
173
238
|
const form = {
|
|
174
|
-
av: ctx.
|
|
239
|
+
av: ctx.globalOptions.pageID,
|
|
175
240
|
queries: JSON.stringify({
|
|
176
241
|
o0: {
|
|
177
|
-
doc_id
|
|
242
|
+
// This doc_id was valid on 2020-07-20
|
|
243
|
+
doc_id: "3336396659757871",
|
|
178
244
|
query_params: {
|
|
179
245
|
limit: limit + (timestamp ? 1 : 0),
|
|
180
246
|
before: timestamp,
|
|
@@ -190,27 +256,34 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
190
256
|
defaultFuncs
|
|
191
257
|
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
|
|
192
258
|
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
193
|
-
.then(resData => {
|
|
259
|
+
.then((resData) => {
|
|
194
260
|
if (resData[resData.length - 1].error_results > 0) {
|
|
195
|
-
throw
|
|
261
|
+
throw resData[0].o0.errors;
|
|
196
262
|
}
|
|
197
263
|
|
|
198
264
|
if (resData[resData.length - 1].successful_results === 0) {
|
|
199
|
-
throw
|
|
265
|
+
throw {
|
|
200
266
|
error: "getThreadList: there was no successful_results",
|
|
201
267
|
res: resData,
|
|
202
|
-
}
|
|
268
|
+
};
|
|
203
269
|
}
|
|
204
270
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
271
|
+
// When we ask for threads using timestamp from the previous request,
|
|
272
|
+
// we are getting the last thread repeated as the first thread in this response.
|
|
273
|
+
// .shift() gets rid of it
|
|
274
|
+
// It is also the reason for increasing limit by 1 when timestamp is set
|
|
275
|
+
// this way user asks for 10 threads, we are asking for 11,
|
|
276
|
+
// but after removing the duplicated one, it is again 10
|
|
277
|
+
if (timestamp) {
|
|
278
|
+
resData[0].o0.data.viewer.message_threads.nodes.shift();
|
|
208
279
|
}
|
|
209
|
-
|
|
210
|
-
|
|
280
|
+
callback(
|
|
281
|
+
null,
|
|
282
|
+
formatThreadList(resData[0].o0.data.viewer.message_threads.nodes),
|
|
283
|
+
);
|
|
211
284
|
})
|
|
212
|
-
.catch(err => {
|
|
213
|
-
|
|
285
|
+
.catch((err) => {
|
|
286
|
+
log.error("getThreadList", err);
|
|
214
287
|
return callback(err);
|
|
215
288
|
});
|
|
216
289
|
|
package/src/getThreadPictures.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
var utils = require("../utils");
|
|
4
|
+
var log = require("npmlog");
|
|
4
5
|
|
|
5
6
|
module.exports = function (defaultFuncs, api, ctx) {
|
|
6
7
|
return function getThreadPictures(threadID, offset, limit, callback) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
var resolveFunc = function () {};
|
|
9
|
+
var rejectFunc = function () {};
|
|
10
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
|
10
11
|
resolveFunc = resolve;
|
|
11
12
|
rejectFunc = reject;
|
|
12
13
|
});
|
|
13
14
|
|
|
14
15
|
if (!callback) {
|
|
15
|
-
callback = (err, friendList)
|
|
16
|
+
callback = function (err, friendList) {
|
|
16
17
|
if (err) {
|
|
17
18
|
return rejectFunc(err);
|
|
18
19
|
}
|
|
@@ -20,7 +21,7 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
20
21
|
};
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
var form = {
|
|
24
25
|
thread_id: threadID,
|
|
25
26
|
offset: offset,
|
|
26
27
|
limit: limit,
|
|
@@ -30,56 +31,49 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
30
31
|
.post(
|
|
31
32
|
"https://www.facebook.com/ajax/messaging/attachments/sharedphotos.php",
|
|
32
33
|
ctx.jar,
|
|
33
|
-
|
|
34
|
+
form,
|
|
34
35
|
)
|
|
35
36
|
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
36
|
-
.then(resData
|
|
37
|
+
.then(function (resData) {
|
|
37
38
|
if (resData.error) {
|
|
38
39
|
throw resData;
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
// প্রতিটি ইমেজের জন্য আলাদা আলাদা রিকোয়েস্ট পাঠানো হচ্ছে
|
|
42
41
|
return Promise.all(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const innerForm = {
|
|
42
|
+
resData.payload.imagesData.map(function (image) {
|
|
43
|
+
form = {
|
|
46
44
|
thread_id: threadID,
|
|
47
45
|
image_id: image.fbid,
|
|
48
46
|
};
|
|
49
|
-
|
|
50
47
|
return defaultFuncs
|
|
51
48
|
.post(
|
|
52
49
|
"https://www.facebook.com/ajax/messaging/attachments/sharedphotos.php",
|
|
53
50
|
ctx.jar,
|
|
54
|
-
|
|
51
|
+
form,
|
|
55
52
|
)
|
|
56
53
|
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
57
|
-
.then(
|
|
58
|
-
if (
|
|
59
|
-
throw
|
|
54
|
+
.then(function (resData) {
|
|
55
|
+
if (resData.error) {
|
|
56
|
+
throw resData;
|
|
60
57
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
58
|
+
// the response is pretty messy
|
|
59
|
+
var queryThreadID =
|
|
60
|
+
resData.jsmods.require[0][3][1].query_metadata.query_path[0]
|
|
61
|
+
.message_thread;
|
|
62
|
+
var imageData =
|
|
63
|
+
resData.jsmods.require[0][3][1].query_results[queryThreadID]
|
|
64
|
+
.message_images.edges[0].node.image2;
|
|
69
65
|
return imageData;
|
|
70
66
|
});
|
|
71
67
|
}),
|
|
72
68
|
);
|
|
73
69
|
})
|
|
74
|
-
.then(resData
|
|
75
|
-
|
|
76
|
-
callback(null, resData.filter(img => img !== null));
|
|
70
|
+
.then(function (resData) {
|
|
71
|
+
callback(null, resData);
|
|
77
72
|
})
|
|
78
|
-
.catch(err
|
|
79
|
-
|
|
73
|
+
.catch(function (err) {
|
|
74
|
+
log.error("Error in getThreadPictures", err);
|
|
80
75
|
callback(err);
|
|
81
76
|
});
|
|
82
|
-
|
|
83
77
|
return returnPromise;
|
|
84
78
|
};
|
|
85
79
|
};
|
package/src/getUserID.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
var utils = require("../utils");
|
|
4
|
+
var log = require("npmlog");
|
|
4
5
|
|
|
5
|
-
// সার্চ রেজাল্টের ডাটা ফরম্যাট করার হেল্পার ফাংশন
|
|
6
6
|
function formatData(data) {
|
|
7
7
|
return {
|
|
8
|
-
userID:
|
|
8
|
+
userID: utils.formatID(data.uid.toString()),
|
|
9
9
|
photoUrl: data.photo,
|
|
10
10
|
indexRank: data.index_rank,
|
|
11
11
|
name: data.text,
|
|
@@ -19,15 +19,15 @@ function formatData(data) {
|
|
|
19
19
|
|
|
20
20
|
module.exports = function (defaultFuncs, api, ctx) {
|
|
21
21
|
return function getUserID(name, callback) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
var resolveFunc = function () {};
|
|
23
|
+
var rejectFunc = function () {};
|
|
24
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
|
25
25
|
resolveFunc = resolve;
|
|
26
26
|
rejectFunc = reject;
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
if (!callback) {
|
|
30
|
-
callback = (err, friendList)
|
|
30
|
+
callback = function (err, friendList) {
|
|
31
31
|
if (err) {
|
|
32
32
|
return rejectFunc(err);
|
|
33
33
|
}
|
|
@@ -35,7 +35,7 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
var form = {
|
|
39
39
|
value: name.toLowerCase(),
|
|
40
40
|
viewer: ctx.userID,
|
|
41
41
|
rsp: "search",
|
|
@@ -47,18 +47,17 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
47
47
|
defaultFuncs
|
|
48
48
|
.get("https://www.facebook.com/ajax/typeahead/search.php", ctx.jar, form)
|
|
49
49
|
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
50
|
-
.then(resData
|
|
50
|
+
.then(function (resData) {
|
|
51
51
|
if (resData.error) {
|
|
52
52
|
throw resData;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
const entries = resData.payload?.entries || [];
|
|
55
|
+
var data = resData.payload.entries;
|
|
57
56
|
|
|
58
|
-
callback(null,
|
|
57
|
+
callback(null, data.map(formatData));
|
|
59
58
|
})
|
|
60
|
-
.catch(err
|
|
61
|
-
|
|
59
|
+
.catch(function (err) {
|
|
60
|
+
log.error("getUserID", err);
|
|
62
61
|
return callback(err);
|
|
63
62
|
});
|
|
64
63
|
|