stfca 1.0.11 → 1.0.12
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/package.json +1 -1
- package/src/getThreadTheme.js +82 -0
- package/src/searchFriends.js +139 -0
- package/src/sendFriendRequest.js +113 -0
package/package.json
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ===========================================================
|
|
3
|
+
* 🧑💻 Author: Sheikh Tamim (ST | Sheikh Tamim)
|
|
4
|
+
* 🔰 Owner & Developer
|
|
5
|
+
* 🌐 GitHub: https://github.com/sheikhtamimlover
|
|
6
|
+
* 📸 Instagram: https://instagram.com/sheikh.tamim_lover
|
|
7
|
+
* -----------------------------------------------------------
|
|
8
|
+
* 🕊️ Respect the creator & give proper credits if reused.
|
|
9
|
+
* ===========================================================
|
|
10
|
+
*/
|
|
11
|
+
"use strict";
|
|
12
|
+
|
|
13
|
+
const utils = require("../utils");
|
|
14
|
+
const log = require("npmlog");
|
|
15
|
+
|
|
16
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
17
|
+
/** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Instagram: @sheikh.tamim_lover */
|
|
18
|
+
return function getThreadTheme(themeID, callback) {
|
|
19
|
+
let resolveFunc, rejectFunc;
|
|
20
|
+
const returnPromise = new Promise((resolve, reject) => {
|
|
21
|
+
resolveFunc = resolve;
|
|
22
|
+
rejectFunc = reject;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (!callback) {
|
|
26
|
+
callback = function (err, data) {
|
|
27
|
+
if (err) return rejectFunc(err);
|
|
28
|
+
resolveFunc(data);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!themeID) {
|
|
33
|
+
return callback({ error: "themeID is required" });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const form = {
|
|
37
|
+
av: ctx.userID,
|
|
38
|
+
__user: ctx.userID,
|
|
39
|
+
__a: 1,
|
|
40
|
+
__req: utils.getSignatureID(),
|
|
41
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
42
|
+
jazoest: ctx.ttstamp,
|
|
43
|
+
lsd: ctx.fb_dtsg,
|
|
44
|
+
fb_api_caller_class: "RelayModern",
|
|
45
|
+
fb_api_req_friendly_name: "MWPThreadThemeProviderQuery",
|
|
46
|
+
variables: JSON.stringify({
|
|
47
|
+
id: themeID.toString() // <-- THEME ID instead of threadID
|
|
48
|
+
}),
|
|
49
|
+
server_timestamps: true,
|
|
50
|
+
doc_id: "9734829906576883"
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
defaultFuncs
|
|
54
|
+
.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
|
|
55
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
56
|
+
.then(function (resData) {
|
|
57
|
+
if (resData.errors) throw resData.errors;
|
|
58
|
+
|
|
59
|
+
if (resData.data && resData.data.messenger_thread_theme) {
|
|
60
|
+
const themeData = resData.data.messenger_thread_theme;
|
|
61
|
+
return callback(null, {
|
|
62
|
+
id: themeData.id,
|
|
63
|
+
name: themeData.accessibility_label,
|
|
64
|
+
description: themeData.description,
|
|
65
|
+
colors: themeData.gradient_colors || [themeData.fallback_color],
|
|
66
|
+
backgroundImage: themeData.background_asset
|
|
67
|
+
? themeData.background_asset.image.uri
|
|
68
|
+
: null
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
throw new Error("No theme data found");
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
.catch(function (err) {
|
|
75
|
+
log.error("getThreadTheme", err);
|
|
76
|
+
return callback(err);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return returnPromise;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
/** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Please give credits if reused. */
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ===========================================================
|
|
3
|
+
* 🧑💻 Author: Sheikh Tamim (ST | Sheikh Tamim)
|
|
4
|
+
* 🔰 Owner & Developer
|
|
5
|
+
* 🌐 GitHub: https://github.com/sheikhtamimlover
|
|
6
|
+
* 📸 Instagram: https://instagram.com/sheikh.tamim_lover
|
|
7
|
+
* -----------------------------------------------------------
|
|
8
|
+
* 🕊️ Respect the creator & give proper credits if reused.
|
|
9
|
+
* ===========================================================
|
|
10
|
+
*/
|
|
11
|
+
"use strict";
|
|
12
|
+
|
|
13
|
+
const utils = require("../utils");
|
|
14
|
+
|
|
15
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
16
|
+
/** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Instagram: @sheikh.tamim_lover */
|
|
17
|
+
return function searchFriends(searchQuery, callback) {
|
|
18
|
+
let resolveFunc = function () {};
|
|
19
|
+
let rejectFunc = function () {};
|
|
20
|
+
const returnPromise = new Promise(function (resolve, reject) {
|
|
21
|
+
resolveFunc = resolve;
|
|
22
|
+
rejectFunc = reject;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
if (!callback) {
|
|
26
|
+
callback = function (err, result) {
|
|
27
|
+
if (err) {
|
|
28
|
+
return rejectFunc(err);
|
|
29
|
+
}
|
|
30
|
+
resolveFunc(result);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!searchQuery || searchQuery.trim().length === 0) {
|
|
35
|
+
return callback(new Error("Search query cannot be empty"));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Enhanced form data based on captured API
|
|
39
|
+
const form = {
|
|
40
|
+
av: ctx.userID,
|
|
41
|
+
__aaid: 0,
|
|
42
|
+
__user: ctx.userID,
|
|
43
|
+
__a: 1,
|
|
44
|
+
__req: utils.getSignatureID(),
|
|
45
|
+
__hs: "20358.HYP:comet_pkg.2.1...0",
|
|
46
|
+
dpr: 1,
|
|
47
|
+
__ccg: "EXCELLENT",
|
|
48
|
+
__rev: "1027694919",
|
|
49
|
+
__s: utils.getSignatureID(),
|
|
50
|
+
__hsi: "7554748243252799467",
|
|
51
|
+
__comet_req: 15,
|
|
52
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
53
|
+
jazoest: ctx.ttstamp,
|
|
54
|
+
lsd: ctx.fb_dtsg,
|
|
55
|
+
__spin_r: "1027694919",
|
|
56
|
+
__spin_b: "trunk",
|
|
57
|
+
__spin_t: Date.now(),
|
|
58
|
+
fb_api_caller_class: "RelayModern",
|
|
59
|
+
fb_api_req_friendly_name: "ProfileCometAppCollectionSelfFriendsListRendererPaginationQuery",
|
|
60
|
+
variables: JSON.stringify({
|
|
61
|
+
count: 20, // Increased count for better results
|
|
62
|
+
cursor: null,
|
|
63
|
+
scale: 1,
|
|
64
|
+
search: searchQuery.trim(),
|
|
65
|
+
id: "YXBwX2NvbGxlY3Rpb246cGZiaWQwMkJSM3NDeXRjNkJIeVVXem9OeUxNcjNoYnVDclRFZkdCcVlEaXZuSlZYOUNLR2pXVmRyYTQ4U29FalJTVzduMm03NlhDa0xEQXAybVVUenF6RXZraGc3ZHkyaGw="
|
|
66
|
+
}),
|
|
67
|
+
server_timestamps: true,
|
|
68
|
+
doc_id: "31767020089578751"
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
defaultFuncs
|
|
72
|
+
.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
|
|
73
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
74
|
+
.then(function (resData) {
|
|
75
|
+
if (!resData || !resData.data) {
|
|
76
|
+
throw { error: "searchFriends returned empty object." };
|
|
77
|
+
}
|
|
78
|
+
if (resData.error) {
|
|
79
|
+
throw resData;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const friendsData = resData.data.node?.pageItems?.edges || [];
|
|
83
|
+
const formattedFriends = friendsData.map(edge => {
|
|
84
|
+
const friend = edge.node;
|
|
85
|
+
const friendUser = friend.node || friend;
|
|
86
|
+
|
|
87
|
+
// Extract mutual friends count from subtitle
|
|
88
|
+
let mutualFriends = 0;
|
|
89
|
+
if (friend.subtitle_text?.text) {
|
|
90
|
+
const mutualMatch = friend.subtitle_text.text.match(/(\d+)\s+mutual\s+friend/i);
|
|
91
|
+
if (mutualMatch) {
|
|
92
|
+
mutualFriends = parseInt(mutualMatch[1]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
userID: friendUser.id || friend.id,
|
|
98
|
+
name: friend.title?.text || friendUser.name || friend.name,
|
|
99
|
+
profilePicture: friend.image?.uri || null,
|
|
100
|
+
profileUrl: friend.url || friendUser.url,
|
|
101
|
+
subtitle: friend.subtitle_text?.text || "",
|
|
102
|
+
mutualFriends: mutualFriends,
|
|
103
|
+
// Additional fields from the captured API
|
|
104
|
+
cursor: edge.cursor,
|
|
105
|
+
friendshipStatus: friendUser.friendship_status || "UNKNOWN",
|
|
106
|
+
gender: friendUser.gender || null,
|
|
107
|
+
shortName: friendUser.short_name || null
|
|
108
|
+
};
|
|
109
|
+
}).filter(friend => friend.userID && friend.name);
|
|
110
|
+
|
|
111
|
+
// Sort by relevance (exact matches first, then by mutual friends)
|
|
112
|
+
formattedFriends.sort((a, b) => {
|
|
113
|
+
const queryLower = searchQuery.toLowerCase();
|
|
114
|
+
const aNameLower = a.name.toLowerCase();
|
|
115
|
+
const bNameLower = b.name.toLowerCase();
|
|
116
|
+
|
|
117
|
+
// Exact matches first
|
|
118
|
+
if (aNameLower === queryLower && bNameLower !== queryLower) return -1;
|
|
119
|
+
if (bNameLower === queryLower && aNameLower !== queryLower) return 1;
|
|
120
|
+
|
|
121
|
+
// Then by starts with
|
|
122
|
+
if (aNameLower.startsWith(queryLower) && !bNameLower.startsWith(queryLower)) return -1;
|
|
123
|
+
if (bNameLower.startsWith(queryLower) && !aNameLower.startsWith(queryLower)) return 1;
|
|
124
|
+
|
|
125
|
+
// Then by mutual friends count
|
|
126
|
+
return b.mutualFriends - a.mutualFriends;
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
callback(null, formattedFriends);
|
|
130
|
+
})
|
|
131
|
+
.catch(function (err) {
|
|
132
|
+
console.error("searchFriends error:", err);
|
|
133
|
+
return callback(err);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return returnPromise;
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
/** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Please give credits if reused. */
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ===========================================================
|
|
3
|
+
* 🧑💻 Author: Sheikh Tamim (ST | Sheikh Tamim)
|
|
4
|
+
* 🔰 Owner & Developer
|
|
5
|
+
* 🌐 GitHub: https://github.com/sheikhtamimlover
|
|
6
|
+
* 📸 Instagram: https://instagram.com/sheikh.tamim_lover
|
|
7
|
+
* -----------------------------------------------------------
|
|
8
|
+
* 🕊️ Respect the creator & give proper credits if reused.
|
|
9
|
+
* ===========================================================
|
|
10
|
+
*/
|
|
11
|
+
"use strict";
|
|
12
|
+
|
|
13
|
+
var utils = require("../utils");
|
|
14
|
+
var log = require("npmlog");
|
|
15
|
+
|
|
16
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
17
|
+
/** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Instagram: @sheikh.tamim_lover */
|
|
18
|
+
return function sendFriendRequest(userID, callback) {
|
|
19
|
+
var resolveFunc = function () { };
|
|
20
|
+
var rejectFunc = function () { };
|
|
21
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
|
22
|
+
resolveFunc = resolve;
|
|
23
|
+
rejectFunc = reject;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (!callback) {
|
|
27
|
+
callback = function (err, data) {
|
|
28
|
+
if (err) return rejectFunc(err);
|
|
29
|
+
resolveFunc(data);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!userID) {
|
|
34
|
+
return callback({ error: "User ID is required" });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
var form = {
|
|
38
|
+
av: ctx.userID,
|
|
39
|
+
__aaid: 0,
|
|
40
|
+
__user: ctx.userID,
|
|
41
|
+
__a: 1,
|
|
42
|
+
__req: utils.getSignatureID(),
|
|
43
|
+
__hs: "20353.HYP:comet_pkg.2.1...0",
|
|
44
|
+
dpr: 1,
|
|
45
|
+
__ccg: "EXCELLENT",
|
|
46
|
+
__rev: "1027405870",
|
|
47
|
+
__s: utils.getSignatureID(),
|
|
48
|
+
__hsi: "7552782279085106329",
|
|
49
|
+
__comet_req: 15,
|
|
50
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
51
|
+
jazoest: ctx.ttstamp,
|
|
52
|
+
lsd: ctx.fb_dtsg,
|
|
53
|
+
__spin_r: "1027405870",
|
|
54
|
+
__spin_b: "trunk",
|
|
55
|
+
__spin_t: Date.now(),
|
|
56
|
+
__crn: "comet.fbweb.CometFriendingRoute",
|
|
57
|
+
fb_api_caller_class: "RelayModern",
|
|
58
|
+
fb_api_req_friendly_name: "FriendingCometFriendRequestSendMutation",
|
|
59
|
+
variables: JSON.stringify({
|
|
60
|
+
input: {
|
|
61
|
+
click_correlation_id: Date.now().toString(),
|
|
62
|
+
click_proof_validation_result: '{"validated":true}',
|
|
63
|
+
friend_requestee_ids: [userID.toString()],
|
|
64
|
+
friending_channel: "FRIENDS_HOME_MAIN",
|
|
65
|
+
warn_ack_for_ids: [],
|
|
66
|
+
actor_id: ctx.userID,
|
|
67
|
+
client_mutation_id: Math.floor(Math.random() * 10).toString()
|
|
68
|
+
},
|
|
69
|
+
scale: 1
|
|
70
|
+
}),
|
|
71
|
+
server_timestamps: true,
|
|
72
|
+
doc_id: "24614631718227645"
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
defaultFuncs
|
|
76
|
+
.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
|
|
77
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
78
|
+
.then(function (resData) {
|
|
79
|
+
if (resData.error) {
|
|
80
|
+
throw resData;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (resData.data && resData.data.friend_request_send) {
|
|
84
|
+
var responseData = resData.data.friend_request_send;
|
|
85
|
+
if (responseData.friend_requestees && responseData.friend_requestees.length > 0) {
|
|
86
|
+
var requestee = responseData.friend_requestees[0];
|
|
87
|
+
var result = {
|
|
88
|
+
userID: requestee.id,
|
|
89
|
+
friendshipStatus: requestee.friendship_status,
|
|
90
|
+
success: requestee.friendship_status === "OUTGOING_REQUEST"
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if (requestee.profile_action) {
|
|
94
|
+
result.actionTitle = requestee.profile_action.title ? requestee.profile_action.title.text : "";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return callback(null, result);
|
|
98
|
+
} else {
|
|
99
|
+
return callback({ error: "No friend request data received" });
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
return callback({ error: "Invalid response format" });
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
.catch(function (err) {
|
|
106
|
+
log.error("sendFriendRequest", err);
|
|
107
|
+
return callback(err);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return returnPromise;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
/** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Please give credits if reused. */
|