metacord 0.0.1-security → 1.1.8-Beta
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of metacord might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/MetaCord_Config.json +14 -0
- package/MetaCord_Database/Database.sqlite +0 -0
- package/MetaCord_Database/Do not delete this folder or any of the files in it +0 -0
- package/README.md +207 -5
- package/index.js +678 -0
- package/logger.js +16 -0
- package/package.json +38 -3
- package/src/addExternalModule.js +16 -0
- package/src/addUserToGroup.js +78 -0
- package/src/changeAdminStatus.js +78 -0
- package/src/changeArchivedStatus.js +41 -0
- package/src/changeBio.js +65 -0
- package/src/changeBlockedStatus.js +36 -0
- package/src/changeGroupImage.js +106 -0
- package/src/changeNickname.js +45 -0
- package/src/changeThreadColor.js +62 -0
- package/src/changeThreadEmoji.js +42 -0
- package/src/createNewGroup.js +70 -0
- package/src/createPoll.js +60 -0
- package/src/deleteMessage.js +45 -0
- package/src/deleteThread.js +43 -0
- package/src/forwardAttachment.js +48 -0
- package/src/getCurrentUserID.js +7 -0
- package/src/getEmojiUrl.js +27 -0
- package/src/getFriendsList.js +73 -0
- package/src/getOnlineTime.js +31 -0
- package/src/getThreadHistory.js +193 -0
- package/src/getThreadInfo.js +197 -0
- package/src/getThreadList.js +213 -0
- package/src/getThreadPictures.js +59 -0
- package/src/getUID.js +57 -0
- package/src/getUserID.js +62 -0
- package/src/getUserInfo.js +66 -0
- package/src/handleFriendRequest.js +49 -0
- package/src/handleMessageRequest.js +49 -0
- package/src/httpGet.js +49 -0
- package/src/httpPost.js +48 -0
- package/src/httpPostFormData.js +41 -0
- package/src/listenMqtt.js +634 -0
- package/src/logout.js +68 -0
- package/src/markAsDelivered.js +48 -0
- package/src/markAsRead.js +70 -0
- package/src/markAsReadAll.js +43 -0
- package/src/markAsSeen.js +51 -0
- package/src/muteThread.js +47 -0
- package/src/removeUserFromGroup.js +49 -0
- package/src/resolvePhotoUrl.js +37 -0
- package/src/searchForThread.js +43 -0
- package/src/sendMessage.js +334 -0
- package/src/sendTypingIndicator.js +80 -0
- package/src/setMessageReaction.js +109 -0
- package/src/setPostReaction.js +102 -0
- package/src/setTitle.js +74 -0
- package/src/threadColors.js +39 -0
- package/src/unfriend.js +43 -0
- package/src/unsendMessage.js +40 -0
- package/utils/Database.js +42 -0
- package/utils/Extension.js +138 -0
- package/utils/Html/MetaCord.png +0 -0
- package/utils/Html/index.html +200 -0
- package/utils/StateCrypt.js +53 -0
- package/utils.js +1249 -0
@@ -0,0 +1,70 @@
|
|
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 createNewGroup(participantIDs, groupTitle, callback) {
|
8
|
+
if (utils.getType(groupTitle) == "Function") {
|
9
|
+
callback = groupTitle;
|
10
|
+
groupTitle = null;
|
11
|
+
}
|
12
|
+
|
13
|
+
if (utils.getType(participantIDs) !== "Array") throw { error: "createNewGroup: participantIDs should be an array." };
|
14
|
+
|
15
|
+
if (participantIDs.length < 2) throw { error: "createNewGroup: participantIDs should have at least 2 IDs." };
|
16
|
+
|
17
|
+
var resolveFunc = function () { };
|
18
|
+
var rejectFunc = function () { };
|
19
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
20
|
+
resolveFunc = resolve;
|
21
|
+
rejectFunc = reject;
|
22
|
+
});
|
23
|
+
|
24
|
+
if (!callback) {
|
25
|
+
callback = function (err, threadID) {
|
26
|
+
if (err) return rejectFunc(err);
|
27
|
+
resolveFunc(threadID);
|
28
|
+
};
|
29
|
+
}
|
30
|
+
|
31
|
+
var pids = [];
|
32
|
+
for (var n in participantIDs) pids.push({ fbid: participantIDs[n] });
|
33
|
+
pids.push({ fbid: ctx.userID });
|
34
|
+
|
35
|
+
var form = {
|
36
|
+
fb_api_caller_class: "RelayModern",
|
37
|
+
fb_api_req_friendly_name: "MessengerGroupCreateMutation",
|
38
|
+
av: ctx.userID,
|
39
|
+
//This doc_id is valid as of January 11th, 2020
|
40
|
+
doc_id: "577041672419534",
|
41
|
+
variables: JSON.stringify({
|
42
|
+
input: {
|
43
|
+
entry_point: "jewel_new_group",
|
44
|
+
actor_id: ctx.userID,
|
45
|
+
participants: pids,
|
46
|
+
client_mutation_id: Math.round(Math.random() * 1024).toString(),
|
47
|
+
thread_settings: {
|
48
|
+
name: groupTitle,
|
49
|
+
joinable_mode: "PRIVATE",
|
50
|
+
thread_image_fbid: null
|
51
|
+
}
|
52
|
+
}
|
53
|
+
})
|
54
|
+
};
|
55
|
+
|
56
|
+
defaultFuncs
|
57
|
+
.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
|
58
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
59
|
+
.then(function (resData) {
|
60
|
+
if (resData.errors) throw resData;
|
61
|
+
return callback(null, resData.data.messenger_group_thread_create.thread.thread_key.thread_fbid);
|
62
|
+
})
|
63
|
+
.catch(function (err) {
|
64
|
+
log.error("createNewGroup", err);
|
65
|
+
return callback(err);
|
66
|
+
});
|
67
|
+
|
68
|
+
return returnPromise;
|
69
|
+
};
|
70
|
+
};
|
@@ -0,0 +1,60 @@
|
|
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 createPoll(title, threadID, options, 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
|
+
if (utils.getType(options) == "Function") {
|
17
|
+
callback = options;
|
18
|
+
options = null;
|
19
|
+
}
|
20
|
+
else {
|
21
|
+
callback = function (err) {
|
22
|
+
if (err) return rejectFunc(err);
|
23
|
+
resolveFunc();
|
24
|
+
};
|
25
|
+
}
|
26
|
+
}
|
27
|
+
if (!options) options = {}; // Initial poll options are optional
|
28
|
+
|
29
|
+
var form = {
|
30
|
+
target_id: threadID,
|
31
|
+
question_text: title
|
32
|
+
};
|
33
|
+
|
34
|
+
// Set fields for options (and whether they are selected initially by the posting user)
|
35
|
+
var ind = 0;
|
36
|
+
for (var opt in options) {
|
37
|
+
// eslint-disable-next-line no-prototype-builtins
|
38
|
+
if (options.hasOwnProperty(opt)) {
|
39
|
+
form["option_text_array[" + ind + "]"] = opt;
|
40
|
+
form["option_is_selected_array[" + ind + "]"] = options[opt] ? "1" : "0";
|
41
|
+
ind++;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
defaultFuncs
|
46
|
+
.post("https://www.facebook.com/messaging/group_polling/create_poll/?dpr=1", ctx.jar, form)
|
47
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
48
|
+
.then(function (resData) {
|
49
|
+
if (resData.payload.status != "success") throw resData;
|
50
|
+
|
51
|
+
return callback();
|
52
|
+
})
|
53
|
+
.catch(function (err) {
|
54
|
+
log.error("createPoll", err);
|
55
|
+
return callback(err);
|
56
|
+
});
|
57
|
+
|
58
|
+
return returnPromise;
|
59
|
+
};
|
60
|
+
};
|
@@ -0,0 +1,45 @@
|
|
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 deleteMessage(messageOrMessages, 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
|
+
if (!callback) {
|
15
|
+
callback = function (err) {
|
16
|
+
if (err) return rejectFunc(err);
|
17
|
+
|
18
|
+
resolveFunc();
|
19
|
+
};
|
20
|
+
}
|
21
|
+
|
22
|
+
var form = {
|
23
|
+
client: "mercury"
|
24
|
+
};
|
25
|
+
|
26
|
+
if (utils.getType(messageOrMessages) !== "Array") messageOrMessages = [messageOrMessages];
|
27
|
+
|
28
|
+
for (var i = 0; i < messageOrMessages.length; i++) form["message_ids[" + i + "]"] = messageOrMessages[i];
|
29
|
+
|
30
|
+
defaultFuncs
|
31
|
+
.post("https://www.facebook.com/ajax/mercury/delete_messages.php", ctx.jar, form)
|
32
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
33
|
+
.then(function (resData) {
|
34
|
+
if (resData.error) throw resData;
|
35
|
+
|
36
|
+
return callback();
|
37
|
+
})
|
38
|
+
.catch(function (err) {
|
39
|
+
log.error("deleteMessage", err);
|
40
|
+
return callback(err);
|
41
|
+
});
|
42
|
+
|
43
|
+
return returnPromise;
|
44
|
+
};
|
45
|
+
};
|
@@ -0,0 +1,43 @@
|
|
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 deleteThread(threadOrThreads, 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
|
+
if (!callback) {
|
15
|
+
callback = function (err) {
|
16
|
+
if (err) return rejectFunc(err);
|
17
|
+
resolveFunc();
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
var form = {
|
22
|
+
client: "mercury"
|
23
|
+
};
|
24
|
+
|
25
|
+
if (utils.getType(threadOrThreads) !== "Array") threadOrThreads = [threadOrThreads];
|
26
|
+
for (var i = 0; i < threadOrThreads.length; i++) form["ids[" + i + "]"] = threadOrThreads[i];
|
27
|
+
|
28
|
+
defaultFuncs
|
29
|
+
.post("https://www.facebook.com/ajax/mercury/delete_thread.php", ctx.jar, form)
|
30
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
31
|
+
.then(function (resData) {
|
32
|
+
if (resData.error) throw resData;
|
33
|
+
|
34
|
+
return callback();
|
35
|
+
})
|
36
|
+
.catch(function (err) {
|
37
|
+
log.error("deleteThread", err);
|
38
|
+
return callback(err);
|
39
|
+
});
|
40
|
+
|
41
|
+
return returnPromise;
|
42
|
+
};
|
43
|
+
};
|
@@ -0,0 +1,48 @@
|
|
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 forwardAttachment(attachmentID, userOrUsers, 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
|
+
if (!callback) {
|
15
|
+
callback = function (err) {
|
16
|
+
if (err) return rejectFunc(err);
|
17
|
+
resolveFunc();
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
var form = {
|
22
|
+
attachment_id: attachmentID
|
23
|
+
};
|
24
|
+
|
25
|
+
if (utils.getType(userOrUsers) !== "Array") userOrUsers = [userOrUsers];
|
26
|
+
|
27
|
+
var timestamp = Math.floor(Date.now() / 1000);
|
28
|
+
|
29
|
+
//That's good, the key of the array is really timestmap in seconds + index
|
30
|
+
//Probably time when the attachment will be sent?
|
31
|
+
for (var i = 0; i < userOrUsers.length; i++) form["recipient_map[" + (timestamp + i) + "]"] = userOrUsers[i];
|
32
|
+
|
33
|
+
defaultFuncs
|
34
|
+
.post("https://www.facebook.com/mercury/attachments/forward/", ctx.jar, form)
|
35
|
+
.then(utils.parseAndCheckLogin(ctx.jar, defaultFuncs))
|
36
|
+
.then(function (resData) {
|
37
|
+
if (resData.error) throw resData;
|
38
|
+
|
39
|
+
return callback();
|
40
|
+
})
|
41
|
+
.catch(function (err) {
|
42
|
+
log.error("forwardAttachment", err);
|
43
|
+
return callback(err);
|
44
|
+
});
|
45
|
+
|
46
|
+
return returnPromise;
|
47
|
+
};
|
48
|
+
};
|
@@ -0,0 +1,27 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
const util = require("util");
|
4
|
+
|
5
|
+
module.exports = function () {
|
6
|
+
return function getEmojiUrl(c, size, pixelRatio) {
|
7
|
+
/*
|
8
|
+
Resolves Facebook Messenger emoji image asset URL for an emoji character.
|
9
|
+
Supported sizes are 32, 64, and 128.
|
10
|
+
Supported pixel ratios are '1.0' and '1.5' (possibly more; haven't tested)
|
11
|
+
*/
|
12
|
+
const baseUrl = "https://static.xx.fbcdn.net/images/emoji.php/v8/z%s/%s";
|
13
|
+
pixelRatio = pixelRatio || "1.0";
|
14
|
+
|
15
|
+
let ending = util.format(
|
16
|
+
"%s/%s/%s.png",
|
17
|
+
pixelRatio,
|
18
|
+
size,
|
19
|
+
c.codePointAt(0).toString(16)
|
20
|
+
);
|
21
|
+
let base = 317426846;
|
22
|
+
for (let i = 0; i < ending.length; i++) base = (base << 5) - base + ending.charCodeAt(i);
|
23
|
+
|
24
|
+
let hashed = (base & 255).toString(16);
|
25
|
+
return util.format(baseUrl, hashed, ending);
|
26
|
+
};
|
27
|
+
};
|
@@ -0,0 +1,73 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
//var cheerio = require("cheerio");
|
4
|
+
var utils = require("../utils");
|
5
|
+
var log = require("npmlog");
|
6
|
+
|
7
|
+
// [almost] copy pasted from one of FB's minified file (GenderConst)
|
8
|
+
var GENDERS = {
|
9
|
+
0: "unknown",
|
10
|
+
1: "female_singular",
|
11
|
+
2: "male_singular",
|
12
|
+
3: "female_singular_guess",
|
13
|
+
4: "male_singular_guess",
|
14
|
+
5: "mixed",
|
15
|
+
6: "neuter_singular",
|
16
|
+
7: "unknown_singular",
|
17
|
+
8: "female_plural",
|
18
|
+
9: "male_plural",
|
19
|
+
10: "neuter_plural",
|
20
|
+
11: "unknown_plural"
|
21
|
+
};
|
22
|
+
|
23
|
+
function formatData(obj) {
|
24
|
+
return Object.keys(obj).map(function (key) {
|
25
|
+
var user = obj[key];
|
26
|
+
return {
|
27
|
+
alternateName: user.alternateName,
|
28
|
+
firstName: user.firstName,
|
29
|
+
gender: GENDERS[user.gender],
|
30
|
+
userID: utils.formatID(user.id.toString()),
|
31
|
+
isFriend: user.is_friend != null && user.is_friend ? true : false,
|
32
|
+
fullName: user.name,
|
33
|
+
profilePicture: user.thumbSrc,
|
34
|
+
type: user.type,
|
35
|
+
profileUrl: user.uri,
|
36
|
+
vanity: user.vanity,
|
37
|
+
isBirthday: !!user.is_birthday
|
38
|
+
};
|
39
|
+
});
|
40
|
+
}
|
41
|
+
|
42
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
43
|
+
return function getFriendsList(callback) {
|
44
|
+
var resolveFunc = function () { };
|
45
|
+
var rejectFunc = function () { };
|
46
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
47
|
+
resolveFunc = resolve;
|
48
|
+
rejectFunc = reject;
|
49
|
+
});
|
50
|
+
|
51
|
+
if (!callback) {
|
52
|
+
callback = function (err, friendList) {
|
53
|
+
if (err) return rejectFunc(err);
|
54
|
+
resolveFunc(friendList);
|
55
|
+
};
|
56
|
+
}
|
57
|
+
|
58
|
+
defaultFuncs
|
59
|
+
.postFormData("https://www.facebook.com/chat/user_info_all", ctx.jar, {}, { viewer: ctx.userID })
|
60
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
61
|
+
.then(function (resData) {
|
62
|
+
if (!resData) throw { error: "getFriendsList returned empty object." };
|
63
|
+
if (resData.error) throw resData;
|
64
|
+
callback(null, formatData(resData.payload));
|
65
|
+
})
|
66
|
+
.catch(function (err) {
|
67
|
+
log.error("getFriendsList", "Lỗi getFriendsList Có Thể Do Bạn Spam Quá Nhiều ! Hãy Hạn Chế !");
|
68
|
+
return callback(err);
|
69
|
+
});
|
70
|
+
|
71
|
+
return returnPromise;
|
72
|
+
};
|
73
|
+
};
|
@@ -0,0 +1,31 @@
|
|
1
|
+
/* eslint-disable linebreak-style */
|
2
|
+
"use strict";
|
3
|
+
|
4
|
+
module.exports = function (_defaultFuncs, _ctx) {
|
5
|
+
return function getUID(callback) {
|
6
|
+
var resolveFunc = function () { };
|
7
|
+
var rejectFunc = function () { };
|
8
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
9
|
+
resolveFunc = resolve;
|
10
|
+
rejectFunc = reject;
|
11
|
+
});
|
12
|
+
|
13
|
+
if (!callback) {
|
14
|
+
callback = function (err, data) {
|
15
|
+
if (err) return rejectFunc(err);
|
16
|
+
resolveFunc(data);
|
17
|
+
};
|
18
|
+
}
|
19
|
+
|
20
|
+
try {
|
21
|
+
if (!require(process.cwd() + "/MetaCord_Config.json").Count_Online_Time.Enable) return callback(null, "Not Enable Count Online Time");
|
22
|
+
const extension = require('../utils/Extension');
|
23
|
+
const { day, hour, minute } = extension.GetCountOnlineTime();
|
24
|
+
callback((require(process.cwd() + "/MetaCord_Config.json").Count_Online_Time.Format).replace("{day}", day).replace("{hour}", hour).replace("minute", minute), null);
|
25
|
+
}
|
26
|
+
catch (e) {
|
27
|
+
return callback(null, e);
|
28
|
+
}
|
29
|
+
return returnPromise;
|
30
|
+
};
|
31
|
+
};
|
@@ -0,0 +1,193 @@
|
|
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 path = require("path");
|
118
|
+
const { writeFileSync } = require('fs-extra');
|
119
|
+
var threadData = require('./data/getThreadInfo.json');
|
120
|
+
|
121
|
+
var threadJson = path.resolve(__dirname, 'data', 'getThreadInfo.json');
|
122
|
+
if(threadData.some(i => i.data.threadID == threadID)) {
|
123
|
+
var thread = threadData.find(i => i.data.threadID == threadID);
|
124
|
+
if(((Date.now() - thread.time)/1000).toFixed() >= 60 * 60 * 2) {
|
125
|
+
const index = threadData.findIndex(i => i.data.threadID == threadID);
|
126
|
+
threadData.splice(index, 1);
|
127
|
+
setTimeout(function() {
|
128
|
+
writeFileSync(threadJson, JSON.stringify(threadData, null, 4));
|
129
|
+
}, 2000);
|
130
|
+
}
|
131
|
+
return thread.data
|
132
|
+
}
|
133
|
+
else {
|
134
|
+
var resolveFunc = function () { };
|
135
|
+
var rejectFunc = function () { };
|
136
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
137
|
+
resolveFunc = resolve;
|
138
|
+
rejectFunc = reject;
|
139
|
+
});
|
140
|
+
|
141
|
+
if (utils.getType(callback) != "Function" && utils.getType(callback) != "AsyncFunction") {
|
142
|
+
callback = function (err, data) {
|
143
|
+
if (err) return rejectFunc(err);
|
144
|
+
resolveFunc(data);
|
145
|
+
};
|
146
|
+
}
|
147
|
+
|
148
|
+
// `queries` has to be a string. I couldn't tell from the dev console. This
|
149
|
+
// took me a really long time to figure out. I deserve a cookie for this.
|
150
|
+
var form = {
|
151
|
+
queries: JSON.stringify({
|
152
|
+
o0: {
|
153
|
+
// This doc_id is valid as of July 20th, 2020
|
154
|
+
doc_id: "3449967031715030",
|
155
|
+
query_params: {
|
156
|
+
id: threadID,
|
157
|
+
message_limit: 0,
|
158
|
+
load_messages: false,
|
159
|
+
load_read_receipts: false,
|
160
|
+
before: null
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}),
|
164
|
+
batch_name: "MessengerGraphQLThreadFetcher"
|
165
|
+
};
|
166
|
+
|
167
|
+
defaultFuncs
|
168
|
+
.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
|
169
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
170
|
+
.then(function (resData) {
|
171
|
+
if (resData.error) throw resData;
|
172
|
+
// This returns us an array of things. The last one is the success /
|
173
|
+
// failure one.
|
174
|
+
// @TODO What do we do in this case?
|
175
|
+
if (resData[resData.length - 1].error_results !== 0) {
|
176
|
+
console.log(resData); //Log more info
|
177
|
+
throw new Error("well darn there was an error_result");
|
178
|
+
}
|
179
|
+
threadData.push({
|
180
|
+
data: formatThreadGraphQLResponse(resData[0]),
|
181
|
+
time: Date.now()
|
182
|
+
})
|
183
|
+
writeFileSync(threadJson, JSON.stringify(threadData, null, 4));
|
184
|
+
callback(null, formatThreadGraphQLResponse(resData[0]));
|
185
|
+
})
|
186
|
+
.catch(function (err) {
|
187
|
+
log.error("getThreadInfoGraphQL", err);
|
188
|
+
return callback(err);
|
189
|
+
});
|
190
|
+
return returnPromise;
|
191
|
+
};
|
192
|
+
}
|
193
|
+
};
|