bb-fca 2.0.3 → 2.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/dist/deltas/apis/users/getUserFriends.js +285 -0
- package/dist/deltas/apis/users/getUserFriends.js.map +1 -0
- package/dist/deltas/apis/users/searchCity.js +91 -0
- package/dist/deltas/apis/users/searchCity.js.map +1 -0
- package/dist/deltas/apis/users/searchCompany.js +86 -0
- package/dist/deltas/apis/users/searchCompany.js.map +1 -0
- package/dist/deltas/apis/users/searchJobTitle.js +85 -0
- package/dist/deltas/apis/users/searchJobTitle.js.map +1 -0
- package/dist/deltas/apis/users/updateCity.js +98 -0
- package/dist/deltas/apis/users/updateCity.js.map +1 -0
- package/dist/deltas/apis/users/updateHometown.js +97 -0
- package/dist/deltas/apis/users/updateHometown.js.map +1 -0
- package/dist/deltas/apis/users/updateWorkExperience.js +131 -0
- package/dist/deltas/apis/users/updateWorkExperience.js.map +1 -0
- package/dist/index.d.ts +115 -0
- package/dist/types/deltas/apis/users/getUserFriends.d.ts +30 -0
- package/dist/types/deltas/apis/users/searchCity.d.ts +10 -0
- package/dist/types/deltas/apis/users/searchCompany.d.ts +10 -0
- package/dist/types/deltas/apis/users/searchJobTitle.d.ts +10 -0
- package/dist/types/deltas/apis/users/updateCity.d.ts +10 -0
- package/dist/types/deltas/apis/users/updateHometown.d.ts +10 -0
- package/dist/types/deltas/apis/users/updateWorkExperience.d.ts +30 -0
- package/friend.html +534 -0
- package/package.json +1 -1
- package/proflie.html +527 -0
- package/src/deltas/apis/users/getUserFriends.ts +373 -0
- package/src/deltas/apis/users/searchCity.ts +106 -0
- package/src/deltas/apis/users/searchCompany.ts +100 -0
- package/src/deltas/apis/users/searchJobTitle.ts +99 -0
- package/src/deltas/apis/users/updateCity.ts +113 -0
- package/src/deltas/apis/users/updateHometown.ts +112 -0
- package/src/deltas/apis/users/updateWorkExperience.ts +160 -0
- package/src/types/index.d.ts +115 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = getUserFriendsModule;
|
|
4
|
+
const utils = require("../../../utils");
|
|
5
|
+
/**
|
|
6
|
+
* @ChoruOfficial
|
|
7
|
+
* @description A module for fetching a user's friend list via Facebook's GraphQL API.
|
|
8
|
+
* First resolves the user's friends page to extract the dynamic collection ID,
|
|
9
|
+
* then calls ProfileCometAppCollectionNonSelfFriendsListRendererPaginationQuery via /api/graphql/.
|
|
10
|
+
* Supports cursor-based pagination without re-fetching HTML on subsequent pages.
|
|
11
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
12
|
+
* @param {Object} api The full API object.
|
|
13
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
14
|
+
* @returns {Function} An async function that fetches a user's friend list.
|
|
15
|
+
*/
|
|
16
|
+
function getUserFriendsModule(defaultFuncs, api, ctx) {
|
|
17
|
+
/**
|
|
18
|
+
* Deep-searches an object/array tree for the first value matching a predicate.
|
|
19
|
+
*/
|
|
20
|
+
function deepFind(obj, predicate, visited = new WeakSet()) {
|
|
21
|
+
if (obj === null || obj === undefined)
|
|
22
|
+
return null;
|
|
23
|
+
if (typeof obj === 'object') {
|
|
24
|
+
if (visited.has(obj))
|
|
25
|
+
return null;
|
|
26
|
+
visited.add(obj);
|
|
27
|
+
}
|
|
28
|
+
if (typeof obj === 'object') {
|
|
29
|
+
for (const key in obj) {
|
|
30
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key))
|
|
31
|
+
continue;
|
|
32
|
+
const val = obj[key];
|
|
33
|
+
if (predicate(val, key))
|
|
34
|
+
return val;
|
|
35
|
+
const found = deepFind(val, predicate, visited);
|
|
36
|
+
if (found !== null)
|
|
37
|
+
return found;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Deep-searches for all values matching a predicate and collects them.
|
|
44
|
+
*/
|
|
45
|
+
function deepFindAll(obj, predicate, results = [], visited = new WeakSet()) {
|
|
46
|
+
if (obj === null || obj === undefined)
|
|
47
|
+
return results;
|
|
48
|
+
if (typeof obj === 'object') {
|
|
49
|
+
if (visited.has(obj))
|
|
50
|
+
return results;
|
|
51
|
+
visited.add(obj);
|
|
52
|
+
}
|
|
53
|
+
if (typeof obj === 'object') {
|
|
54
|
+
for (const key in obj) {
|
|
55
|
+
if (!Object.prototype.hasOwnProperty.call(obj, key))
|
|
56
|
+
continue;
|
|
57
|
+
const val = obj[key];
|
|
58
|
+
if (predicate(val, key))
|
|
59
|
+
results.push(val);
|
|
60
|
+
deepFindAll(val, predicate, results, visited);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return results;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Extracts the friends collection ID from the embedded JSON data on a user's friends page.
|
|
67
|
+
*
|
|
68
|
+
* The correct ID lives on the same node as `pageItems` (sibling), e.g.:
|
|
69
|
+
* { pageItems: { edges: [...], page_info: {...} }, id: "YXBwX2NvbGxlY3Rpb24..." }
|
|
70
|
+
* Decodes to `app_collection:...`.
|
|
71
|
+
*/
|
|
72
|
+
function extractCollectionId(allJsonData) {
|
|
73
|
+
// Strategy 1 (most reliable): find a node that has BOTH `pageItems.page_info`
|
|
74
|
+
// and a sibling `id` field. This is exactly the shape Facebook returns for
|
|
75
|
+
// the friends collection renderer.
|
|
76
|
+
const pageItemsParent = deepFind(allJsonData, (val, _key) => val &&
|
|
77
|
+
typeof val === 'object' &&
|
|
78
|
+
val.pageItems &&
|
|
79
|
+
val.pageItems.page_info &&
|
|
80
|
+
typeof val.id === 'string' &&
|
|
81
|
+
val.id.length > 40);
|
|
82
|
+
if (pageItemsParent?.id) {
|
|
83
|
+
try {
|
|
84
|
+
const decoded = Buffer.from(pageItemsParent.id, 'base64').toString('utf-8');
|
|
85
|
+
if (decoded.startsWith('app_collection:')) {
|
|
86
|
+
return pageItemsParent.id;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
/* not base64, fall through */
|
|
91
|
+
}
|
|
92
|
+
// Even if it doesn't decode to app_collection, it's still the
|
|
93
|
+
// best candidate because it sits next to pageItems.
|
|
94
|
+
return pageItemsParent.id;
|
|
95
|
+
}
|
|
96
|
+
// Strategy 2: all_collections → edges → node with tab_key "friends"
|
|
97
|
+
const allCollections = deepFindAll(allJsonData, (_val, key) => key === 'all_collections');
|
|
98
|
+
for (const collection of allCollections) {
|
|
99
|
+
const edges = collection?.edges;
|
|
100
|
+
if (!Array.isArray(edges))
|
|
101
|
+
continue;
|
|
102
|
+
for (const edge of edges) {
|
|
103
|
+
const node = edge?.node;
|
|
104
|
+
if (!node)
|
|
105
|
+
continue;
|
|
106
|
+
if (node.tab_key === 'friends') {
|
|
107
|
+
if (node.id)
|
|
108
|
+
return node.id;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Strategy 3: any base64 id that decodes to "app_collection:..."
|
|
113
|
+
const candidates = deepFindAll(allJsonData, (val, key) => key === 'id' && typeof val === 'string' && val.length > 40);
|
|
114
|
+
for (const candidate of candidates) {
|
|
115
|
+
try {
|
|
116
|
+
const decoded = Buffer.from(candidate, 'base64').toString('utf-8');
|
|
117
|
+
if (decoded.startsWith('app_collection:')) {
|
|
118
|
+
return candidate;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Not valid base64, skip
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Maps a raw pageItems edge node to a FriendEntry.
|
|
129
|
+
*/
|
|
130
|
+
function mapEdgeToFriend(edge) {
|
|
131
|
+
const item = edge.node;
|
|
132
|
+
const actionOwner = item?.actions_renderer?.action?.client_handler?.profile_action
|
|
133
|
+
?.restrictable_profile_owner || {};
|
|
134
|
+
return {
|
|
135
|
+
id: item?.node?.id || actionOwner?.id || '',
|
|
136
|
+
name: item?.title?.text || '',
|
|
137
|
+
avatarUri: item?.image_v2?.uri || '',
|
|
138
|
+
profileUrl: item?.url || item?.node?.url || '',
|
|
139
|
+
mutualFriendsText: item?.subtitle_text?.text || '',
|
|
140
|
+
friendshipStatus: item?.actions_renderer?.action?.profile_owner?.friendship_status || '',
|
|
141
|
+
gender: actionOwner?.gender || '',
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Extracts the initial friends list and page_info directly from the embedded
|
|
146
|
+
* HTML JSON data (the data Facebook ships with the first page load).
|
|
147
|
+
*
|
|
148
|
+
* The cursor pattern in the HTML:
|
|
149
|
+
* ],"page_info":{"end_cursor":"AQHS...","has_next_page":true}
|
|
150
|
+
*/
|
|
151
|
+
function extractInitialFriendsData(allJsonData) {
|
|
152
|
+
const pageItemsNode = deepFind(allJsonData, (val, key) => key === 'pageItems' &&
|
|
153
|
+
val &&
|
|
154
|
+
typeof val === 'object' &&
|
|
155
|
+
Array.isArray(val.edges) &&
|
|
156
|
+
val.page_info);
|
|
157
|
+
if (!pageItemsNode)
|
|
158
|
+
return null;
|
|
159
|
+
const edges = pageItemsNode.edges || [];
|
|
160
|
+
const pageInfo = pageItemsNode.page_info || {};
|
|
161
|
+
return {
|
|
162
|
+
friends: edges.map(mapEdgeToFriend),
|
|
163
|
+
endCursor: pageInfo.end_cursor || null,
|
|
164
|
+
hasNextPage: pageInfo.has_next_page || false,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Builds the GraphQL POST form matching the proven working pattern
|
|
169
|
+
* used by changeBio, uploadAvatar, and other GraphQL APIs.
|
|
170
|
+
* `defaultFuncs.post()` auto-injects `__req`, `__rev`, `__a`,
|
|
171
|
+
* `fb_dtsg`, `jazoest`, so we only add the query-specific fields.
|
|
172
|
+
*/
|
|
173
|
+
function buildGraphQLForm(variables, ctx) {
|
|
174
|
+
return {
|
|
175
|
+
av: ctx.userID,
|
|
176
|
+
__user: ctx.userID,
|
|
177
|
+
__a: '1',
|
|
178
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
179
|
+
jazoest: ctx.jazoest,
|
|
180
|
+
lsd: ctx.lsd,
|
|
181
|
+
fb_api_caller_class: 'RelayModern',
|
|
182
|
+
fb_api_req_friendly_name: 'ProfileCometAppCollectionNonSelfFriendsListRendererPaginationQuery',
|
|
183
|
+
variables: JSON.stringify(variables),
|
|
184
|
+
server_timestamps: 'true',
|
|
185
|
+
doc_id: '34081659828149039',
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Fetches the friend list of a given user with cursor-based pagination.
|
|
190
|
+
*
|
|
191
|
+
* @param {string} userID The Facebook user ID whose friends to fetch.
|
|
192
|
+
* @param {string|null} [cursor=null] Pagination cursor from the previous result's `endCursor`.
|
|
193
|
+
* Pass `null` (or omit) for the first page.
|
|
194
|
+
* @param {number} [count=8] Number of friends to fetch per page.
|
|
195
|
+
* @param {string} [collectionId] The collection ID from a previous result.
|
|
196
|
+
* Pass this to skip the HTML re-fetch on page 2 onward — avoids an extra network round-trip.
|
|
197
|
+
*
|
|
198
|
+
* @returns {Promise<FriendsResult>} Friends list, pagination info, and the `collectionId`
|
|
199
|
+
* to reuse on subsequent calls.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* // Page 1 — fetches HTML, reads friends + cursor from embedded data
|
|
203
|
+
* const page1 = await api.getUserFriends('100005706074199');
|
|
204
|
+
* console.log(page1.friends); // Array of FriendEntry
|
|
205
|
+
* console.log(page1.endCursor); // cursor string for next page
|
|
206
|
+
* console.log(page1.collectionId); // reuse this to skip HTML fetch on page 2+
|
|
207
|
+
*
|
|
208
|
+
* // Page 2+ — pass cursor AND collectionId to skip the HTML round-trip
|
|
209
|
+
* const page2 = await api.getUserFriends(
|
|
210
|
+
* '100005706074199',
|
|
211
|
+
* page1.endCursor,
|
|
212
|
+
* 8,
|
|
213
|
+
* page1.collectionId,
|
|
214
|
+
* );
|
|
215
|
+
*/
|
|
216
|
+
return async function getUserFriends(userID, cursor = null, collectionId, count = 8) {
|
|
217
|
+
if (!userID) {
|
|
218
|
+
throw new Error('userID is required.');
|
|
219
|
+
}
|
|
220
|
+
let resolvedCollectionId = collectionId || null;
|
|
221
|
+
// Step 1: Fetch the friends page HTML only when we don't have a collectionId.
|
|
222
|
+
// On page 2+ the caller should pass collectionId from the previous result
|
|
223
|
+
// to skip this round-trip (mirroring real browser behaviour).
|
|
224
|
+
if (!resolvedCollectionId) {
|
|
225
|
+
const friendsPageUrl = `https://www.facebook.com/profile.php?id=${userID}&sk=friends`;
|
|
226
|
+
const allJsonData = await utils.json(friendsPageUrl, ctx.jar, null, ctx.globalOptions, ctx);
|
|
227
|
+
if (!allJsonData || allJsonData.length === 0) {
|
|
228
|
+
throw new Error(`Could not fetch friends page data for user ${userID}.`);
|
|
229
|
+
}
|
|
230
|
+
resolvedCollectionId = extractCollectionId(allJsonData);
|
|
231
|
+
if (!resolvedCollectionId) {
|
|
232
|
+
throw new Error(`Could not extract friends collection ID for user ${userID}. ` +
|
|
233
|
+
`The user may have their friends list set to private.`);
|
|
234
|
+
}
|
|
235
|
+
// First page: try to read friends + page_info directly from the HTML data.
|
|
236
|
+
// The HTML ships with the initial batch and the cursor for the next page,
|
|
237
|
+
// matching: ],"page_info":{"end_cursor":"AQHS...","has_next_page":true}
|
|
238
|
+
if (cursor === null) {
|
|
239
|
+
const initialData = extractInitialFriendsData(allJsonData);
|
|
240
|
+
if (initialData) {
|
|
241
|
+
return { ...initialData, collectionId: resolvedCollectionId };
|
|
242
|
+
}
|
|
243
|
+
// Fallthrough: HTML extraction failed — use GraphQL with null cursor
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Step 2: GraphQL pagination request (page 2+ or first-page fallback).
|
|
247
|
+
// Variables match the real browser request exactly.
|
|
248
|
+
const variables = {
|
|
249
|
+
count,
|
|
250
|
+
cursor,
|
|
251
|
+
scale: 1,
|
|
252
|
+
search: null,
|
|
253
|
+
id: resolvedCollectionId,
|
|
254
|
+
__relay_internal__pv__FBProfile_enable_perf_improv_gkrelayprovider: true,
|
|
255
|
+
};
|
|
256
|
+
const form = buildGraphQLForm(variables, ctx);
|
|
257
|
+
const res = await utils.post('https://www.facebook.com/api/graphql/', ctx.jar, form, ctx.globalOptions, ctx);
|
|
258
|
+
let data;
|
|
259
|
+
if (typeof res.body === 'object' && res.body !== null) {
|
|
260
|
+
data = res.body;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const body = typeof res.body === 'string' ? res.body : String(res.body);
|
|
264
|
+
try {
|
|
265
|
+
data = JSON.parse(body);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
const lines = body.split('\n').filter(Boolean);
|
|
269
|
+
data = JSON.parse(lines[0]);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (data.errors)
|
|
273
|
+
throw new Error(JSON.stringify(data.errors));
|
|
274
|
+
const pageItems = data?.data?.node?.pageItems;
|
|
275
|
+
const edges = pageItems?.edges || [];
|
|
276
|
+
const pageInfo = pageItems?.page_info || {};
|
|
277
|
+
return {
|
|
278
|
+
friends: edges.map(mapEdgeToFriend),
|
|
279
|
+
endCursor: pageInfo.end_cursor || null,
|
|
280
|
+
hasNextPage: pageInfo.has_next_page || false,
|
|
281
|
+
collectionId: resolvedCollectionId,
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=getUserFriends.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getUserFriends.js","sourceRoot":"","sources":["../../../../src/deltas/apis/users/getUserFriends.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const utils = require("../../../utils");
|
|
5
|
+
/**
|
|
6
|
+
* @ChoruOfficial
|
|
7
|
+
* @description A module for searching cities via Facebook's Directory Typeahead API.
|
|
8
|
+
* Calls useProfileCometDirectoryTypeaheadDataSourceQuery via /api/graphql/.
|
|
9
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
10
|
+
* @param {Object} api The full API object.
|
|
11
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
12
|
+
* @returns {Function} An async function that searches for cities by name.
|
|
13
|
+
*/
|
|
14
|
+
function default_1(defaultFuncs, api, ctx) {
|
|
15
|
+
/**
|
|
16
|
+
* Searches for cities matching the given query string.
|
|
17
|
+
* Uses Facebook's Directory Typeahead data source to find city results.
|
|
18
|
+
* @async
|
|
19
|
+
* @param {string} query The search query (city name or partial name).
|
|
20
|
+
* @param {string} [searchCategory='CURRENT_CITY'] The category to search.
|
|
21
|
+
* Supported values: 'CURRENT_CITY', 'HOMETOWN', etc.
|
|
22
|
+
* @returns {Promise<Array<Object>>} A promise that resolves to an array of city objects.
|
|
23
|
+
* @throws {Error} If the query is missing or the API request fails.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const cities = await api.searchCity('vinh');
|
|
27
|
+
* const hometowns = await api.searchCity('ha noi', 'HOMETOWN');
|
|
28
|
+
*/
|
|
29
|
+
return async function searchCity(query, searchCategory = 'CURRENT_CITY') {
|
|
30
|
+
if (!query) {
|
|
31
|
+
throw new Error('query is required.');
|
|
32
|
+
}
|
|
33
|
+
const variables = {
|
|
34
|
+
search_category: searchCategory,
|
|
35
|
+
query: query,
|
|
36
|
+
};
|
|
37
|
+
const form = {
|
|
38
|
+
av: ctx.userID,
|
|
39
|
+
__user: ctx.userID,
|
|
40
|
+
__a: '1',
|
|
41
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
42
|
+
jazoest: ctx.jazoest,
|
|
43
|
+
lsd: ctx.lsd,
|
|
44
|
+
fb_api_caller_class: 'RelayModern',
|
|
45
|
+
fb_api_req_friendly_name: 'useProfileCometDirectoryTypeaheadDataSourceQuery',
|
|
46
|
+
variables: JSON.stringify(variables),
|
|
47
|
+
server_timestamps: 'true',
|
|
48
|
+
doc_id: '24825162803742896',
|
|
49
|
+
};
|
|
50
|
+
const customHeader = {
|
|
51
|
+
'x-fb-friendly-name': 'useProfileCometDirectoryTypeaheadDataSourceQuery',
|
|
52
|
+
'x-fb-lsd': ctx.lsd,
|
|
53
|
+
'x-asbd-id': '359341',
|
|
54
|
+
origin: 'https://www.facebook.com',
|
|
55
|
+
referer: `https://www.facebook.com/profile.php?id=${ctx.userID}&sk=directory_personal_details`,
|
|
56
|
+
};
|
|
57
|
+
const resData = await utils.post('https://www.facebook.com/api/graphql/', ctx.jar, form, ctx.globalOptions, ctx, customHeader);
|
|
58
|
+
// resData.body may already be a parsed object (axios auto-parses JSON)
|
|
59
|
+
// or it may be a string/Buffer — handle both cases
|
|
60
|
+
let data;
|
|
61
|
+
if (typeof resData.body === 'object' && resData.body !== null && !Buffer.isBuffer(resData.body)) {
|
|
62
|
+
data = resData.body;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const body = typeof resData.body === 'string' ? resData.body : resData.body.toString();
|
|
66
|
+
try {
|
|
67
|
+
data = JSON.parse(body);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Facebook sometimes returns multiple JSON lines
|
|
71
|
+
const lines = body.split('\n').filter(Boolean);
|
|
72
|
+
data = JSON.parse(lines[0]);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (data.errors)
|
|
76
|
+
throw new Error(JSON.stringify(data.errors));
|
|
77
|
+
// Extract city suggestions from: data.viewer.profile_directory_typeahead_suggestions
|
|
78
|
+
const suggestions = data?.data?.viewer?.profile_directory_typeahead_suggestions || [];
|
|
79
|
+
return suggestions
|
|
80
|
+
.filter((item) => item.fbid !== '-1')
|
|
81
|
+
.map((item) => ({
|
|
82
|
+
fbid: item.fbid,
|
|
83
|
+
title: item.title,
|
|
84
|
+
value: item.value,
|
|
85
|
+
photoUri: item.photo_uri,
|
|
86
|
+
subtitle: item.subtitle,
|
|
87
|
+
secondSubtitle: item.second_subtitle,
|
|
88
|
+
}));
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=searchCity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchCity.js","sourceRoot":"","sources":["../../../../src/deltas/apis/users/searchCity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = searchCompanyModule;
|
|
4
|
+
const utils = require("../../../utils");
|
|
5
|
+
/**
|
|
6
|
+
* @ChoruOfficial
|
|
7
|
+
* @description A module for searching companies/workplaces via Facebook's Directory Typeahead API.
|
|
8
|
+
* Calls useProfileCometDirectoryTypeaheadDataSourceQuery via /api/graphql/.
|
|
9
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
10
|
+
* @param {Object} api The full API object.
|
|
11
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
12
|
+
* @returns {Function} An async function that searches for companies by name.
|
|
13
|
+
*/
|
|
14
|
+
function searchCompanyModule(defaultFuncs, api, ctx) {
|
|
15
|
+
/**
|
|
16
|
+
* Searches for companies/workplaces matching the given query string.
|
|
17
|
+
* Uses Facebook's Directory Typeahead data source with WORKPLACE category.
|
|
18
|
+
* @async
|
|
19
|
+
* @param {string} query The search query (company name or partial name).
|
|
20
|
+
* @returns {Promise<Array<Object>>} A promise that resolves to an array of company objects.
|
|
21
|
+
* @throws {Error} If the query is missing or the API request fails.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* const companies = await api.searchCompany('google');
|
|
25
|
+
* // companies[0] = { fbid: '...', title: 'Google', photoUri: '...', subtitle: '...', ... }
|
|
26
|
+
*/
|
|
27
|
+
return async function searchCompany(query) {
|
|
28
|
+
if (!query) {
|
|
29
|
+
throw new Error('query is required.');
|
|
30
|
+
}
|
|
31
|
+
const variables = {
|
|
32
|
+
search_category: 'WORKPLACE',
|
|
33
|
+
query: query,
|
|
34
|
+
};
|
|
35
|
+
const form = {
|
|
36
|
+
av: ctx.userID,
|
|
37
|
+
__user: ctx.userID,
|
|
38
|
+
__a: '1',
|
|
39
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
40
|
+
jazoest: ctx.jazoest,
|
|
41
|
+
lsd: ctx.lsd,
|
|
42
|
+
fb_api_caller_class: 'RelayModern',
|
|
43
|
+
fb_api_req_friendly_name: 'useProfileCometDirectoryTypeaheadDataSourceQuery',
|
|
44
|
+
variables: JSON.stringify(variables),
|
|
45
|
+
server_timestamps: 'true',
|
|
46
|
+
doc_id: '24825162803742896',
|
|
47
|
+
};
|
|
48
|
+
const customHeader = {
|
|
49
|
+
'x-fb-friendly-name': 'useProfileCometDirectoryTypeaheadDataSourceQuery',
|
|
50
|
+
'x-fb-lsd': ctx.lsd,
|
|
51
|
+
'x-asbd-id': '359341',
|
|
52
|
+
origin: 'https://www.facebook.com',
|
|
53
|
+
referer: `https://www.facebook.com/profile.php?id=${ctx.userID}&sk=directory_work`,
|
|
54
|
+
};
|
|
55
|
+
const resData = await utils.post('https://www.facebook.com/api/graphql/', ctx.jar, form, ctx.globalOptions, ctx, customHeader);
|
|
56
|
+
// Handle both parsed object and string/Buffer response
|
|
57
|
+
let data;
|
|
58
|
+
if (typeof resData.body === 'object' && resData.body !== null && !Buffer.isBuffer(resData.body)) {
|
|
59
|
+
data = resData.body;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const body = typeof resData.body === 'string' ? resData.body : resData.body.toString();
|
|
63
|
+
try {
|
|
64
|
+
data = JSON.parse(body);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
const lines = body.split('\n').filter((l) => l);
|
|
68
|
+
data = JSON.parse(lines[0]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (data.errors)
|
|
72
|
+
throw new Error(JSON.stringify(data.errors));
|
|
73
|
+
const suggestions = data?.data?.viewer?.profile_directory_typeahead_suggestions || [];
|
|
74
|
+
return suggestions
|
|
75
|
+
.filter((item) => item.fbid !== '-1')
|
|
76
|
+
.map((item) => ({
|
|
77
|
+
fbid: item.fbid,
|
|
78
|
+
title: item.title,
|
|
79
|
+
value: item.value,
|
|
80
|
+
photoUri: item.photo_uri,
|
|
81
|
+
subtitle: item.subtitle,
|
|
82
|
+
secondSubtitle: item.second_subtitle,
|
|
83
|
+
}));
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=searchCompany.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchCompany.js","sourceRoot":"","sources":["../../../../src/deltas/apis/users/searchCompany.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = searchJobTitleModule;
|
|
4
|
+
const utils = require("../../../utils");
|
|
5
|
+
/**
|
|
6
|
+
* @ChoruOfficial
|
|
7
|
+
* @description A module for searching job titles via Facebook's Directory Typeahead API.
|
|
8
|
+
* Calls useProfileCometDirectoryTypeaheadDataSourceQuery via /api/graphql/.
|
|
9
|
+
* @param {Object} defaultFuncs The default functions provided by the API wrapper.
|
|
10
|
+
* @param {Object} api The full API object.
|
|
11
|
+
* @param {Object} ctx The context object containing the user's session state.
|
|
12
|
+
* @returns {Function} An async function that searches for job titles by name.
|
|
13
|
+
*/
|
|
14
|
+
function searchJobTitleModule(defaultFuncs, api, ctx) {
|
|
15
|
+
/**
|
|
16
|
+
* Searches for job titles/positions matching the given query string.
|
|
17
|
+
* Uses Facebook's Directory Typeahead data source with JOB_TITLE category.
|
|
18
|
+
* @async
|
|
19
|
+
* @param {string} query The search query (job title or partial name).
|
|
20
|
+
* @returns {Promise<Array<Object>>} A promise that resolves to an array of job title objects.
|
|
21
|
+
* @throws {Error} If the query is missing or the API request fails.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* const jobs = await api.searchJobTitle('developer');
|
|
25
|
+
* // jobs[0] = { fbid: '...', title: 'Software Developer', ... }
|
|
26
|
+
*/
|
|
27
|
+
return async function searchJobTitle(query) {
|
|
28
|
+
if (!query) {
|
|
29
|
+
throw new Error('query is required.');
|
|
30
|
+
}
|
|
31
|
+
const variables = {
|
|
32
|
+
search_category: 'JOB_TITLE',
|
|
33
|
+
query: query,
|
|
34
|
+
};
|
|
35
|
+
const form = {
|
|
36
|
+
av: ctx.userID,
|
|
37
|
+
__user: ctx.userID,
|
|
38
|
+
__a: '1',
|
|
39
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
40
|
+
jazoest: ctx.jazoest,
|
|
41
|
+
lsd: ctx.lsd,
|
|
42
|
+
fb_api_caller_class: 'RelayModern',
|
|
43
|
+
fb_api_req_friendly_name: 'useProfileCometDirectoryTypeaheadDataSourceQuery',
|
|
44
|
+
variables: JSON.stringify(variables),
|
|
45
|
+
server_timestamps: 'true',
|
|
46
|
+
doc_id: '24825162803742896',
|
|
47
|
+
};
|
|
48
|
+
const customHeader = {
|
|
49
|
+
'x-fb-friendly-name': 'useProfileCometDirectoryTypeaheadDataSourceQuery',
|
|
50
|
+
'x-fb-lsd': ctx.lsd,
|
|
51
|
+
'x-asbd-id': '359341',
|
|
52
|
+
origin: 'https://www.facebook.com',
|
|
53
|
+
referer: `https://www.facebook.com/profile.php?id=${ctx.userID}&sk=directory_work`,
|
|
54
|
+
};
|
|
55
|
+
const resData = await utils.post('https://www.facebook.com/api/graphql/', ctx.jar, form, ctx.globalOptions, ctx, customHeader);
|
|
56
|
+
let data;
|
|
57
|
+
if (typeof resData.body === 'object' && resData.body !== null && !Buffer.isBuffer(resData.body)) {
|
|
58
|
+
data = resData.body;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const body = typeof resData.body === 'string' ? resData.body : resData.body.toString();
|
|
62
|
+
try {
|
|
63
|
+
data = JSON.parse(body);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
const lines = body.split('\n').filter(Boolean);
|
|
67
|
+
data = JSON.parse(lines[0]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (data.errors)
|
|
71
|
+
throw new Error(JSON.stringify(data.errors));
|
|
72
|
+
const suggestions = data?.data?.viewer?.profile_directory_typeahead_suggestions || [];
|
|
73
|
+
return suggestions
|
|
74
|
+
.filter((item) => item.fbid !== '-1')
|
|
75
|
+
.map((item) => ({
|
|
76
|
+
fbid: item.fbid,
|
|
77
|
+
title: item.title,
|
|
78
|
+
value: item.value,
|
|
79
|
+
photoUri: item.photo_uri,
|
|
80
|
+
subtitle: item.subtitle,
|
|
81
|
+
secondSubtitle: item.second_subtitle,
|
|
82
|
+
}));
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=searchJobTitle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchJobTitle.js","sourceRoot":"","sources":["../../../../src/deltas/apis/users/searchJobTitle.ts"],"names":[],"mappings":"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"}
|