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