@cexy/hoonfca 1.0.1 → 1.0.3

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.
Files changed (170) hide show
  1. package/.travis.yml +6 -0
  2. package/LICENSE-MIT +21 -0
  3. package/index.d.ts +620 -0
  4. package/index.js +778 -1
  5. package/package.json +31 -84
  6. package/src/{apis/addExternalModule.js → addExternalModule.js} +4 -5
  7. package/src/addUserToGroup.js +113 -0
  8. package/src/changeAdminStatus.js +95 -0
  9. package/src/changeApprovalMode.js +79 -0
  10. package/src/changeArchivedStatus.js +55 -0
  11. package/src/changeBio.js +76 -0
  12. package/src/changeBlockedStatus.js +47 -0
  13. package/src/changeBlockedStatusMqtt.js +86 -0
  14. package/src/changeGroupImage.js +133 -0
  15. package/src/changeNickname.js +59 -0
  16. package/src/changeThreadColor.js +71 -0
  17. package/src/{apis/changeThreadEmoji.js → changeThreadEmoji.js} +8 -6
  18. package/src/createNewGroup.js +88 -0
  19. package/src/createPoll.js +130 -0
  20. package/src/deleteMessage.js +56 -0
  21. package/src/deleteThread.js +56 -0
  22. package/src/editMessage.js +63 -0
  23. package/src/forwardAttachment.js +60 -0
  24. package/src/forwardMessage.js +63 -0
  25. package/src/getCurrentUserID.js +7 -0
  26. package/src/getEmojiUrl.js +29 -0
  27. package/src/getFriendsList.js +84 -0
  28. package/src/getGroupsList.js +83 -0
  29. package/src/getMarketplace.js +84 -0
  30. package/src/getNotifications.js +86 -0
  31. package/src/getPagesList.js +83 -0
  32. package/src/getStories.js +88 -0
  33. package/src/getThreadHistory.js +647 -0
  34. package/src/getThreadInfo.js +222 -0
  35. package/src/getThreadList.js +292 -0
  36. package/src/getThreadPictures.js +79 -0
  37. package/src/getUserID.js +66 -0
  38. package/src/getUserInfo.js +128 -0
  39. package/src/handleFriendRequest.js +57 -0
  40. package/src/handleMessageRequest.js +65 -0
  41. package/src/{apis/httpGet.js → httpGet.js} +15 -20
  42. package/src/httpPost.js +58 -0
  43. package/src/listenMqtt.js +1018 -0
  44. package/src/logout.js +75 -0
  45. package/src/markAsDelivered.js +58 -0
  46. package/src/{apis/markAsRead.js → markAsRead.js} +19 -30
  47. package/src/markAsReadAll.js +50 -0
  48. package/src/markAsSeen.js +61 -0
  49. package/src/muteThread.js +52 -0
  50. package/src/pinMessage.js +61 -0
  51. package/src/removeUserFromGroup.js +79 -0
  52. package/src/resolvePhotoUrl.js +45 -0
  53. package/src/searchForThread.js +53 -0
  54. package/src/searchUsers.js +89 -0
  55. package/src/sendComment.js +161 -0
  56. package/src/sendMessage.js +457 -0
  57. package/src/sendTypingIndicator.js +179 -0
  58. package/src/setBio.js +86 -0
  59. package/src/setMessageReaction.js +186 -0
  60. package/src/setPostReaction.js +71 -0
  61. package/src/setTheme.js +313 -0
  62. package/src/setTitle.js +90 -0
  63. package/src/shareContact.js +53 -0
  64. package/src/shareLink.js +62 -0
  65. package/src/threadColors.js +57 -0
  66. package/src/unfriend.js +53 -0
  67. package/src/unsendMessage.js +104 -0
  68. package/utils.js +1447 -0
  69. package/LICENSE +0 -3
  70. package/README.md +0 -491
  71. package/examples/login-with-cookies.js +0 -102
  72. package/examples/verify.js +0 -70
  73. package/src/apis/addUserToGroup.js +0 -108
  74. package/src/apis/changeAdminStatus.js +0 -148
  75. package/src/apis/changeArchivedStatus.js +0 -61
  76. package/src/apis/changeAvatar.js +0 -103
  77. package/src/apis/changeBio.js +0 -69
  78. package/src/apis/changeBlockedStatus.js +0 -54
  79. package/src/apis/changeGroupImage.js +0 -136
  80. package/src/apis/changeThreadColor.js +0 -116
  81. package/src/apis/comment.js +0 -207
  82. package/src/apis/createAITheme.js +0 -129
  83. package/src/apis/createNewGroup.js +0 -79
  84. package/src/apis/createPoll.js +0 -73
  85. package/src/apis/deleteMessage.js +0 -44
  86. package/src/apis/deleteThread.js +0 -52
  87. package/src/apis/e2ee.js +0 -17
  88. package/src/apis/editMessage.js +0 -70
  89. package/src/apis/emoji.js +0 -124
  90. package/src/apis/fetchThemeData.js +0 -82
  91. package/src/apis/follow.js +0 -81
  92. package/src/apis/forwardMessage.js +0 -52
  93. package/src/apis/friend.js +0 -243
  94. package/src/apis/gcmember.js +0 -122
  95. package/src/apis/gcname.js +0 -123
  96. package/src/apis/gcrule.js +0 -119
  97. package/src/apis/getAccess.js +0 -111
  98. package/src/apis/getBotInfo.js +0 -88
  99. package/src/apis/getBotInitialData.js +0 -43
  100. package/src/apis/getFriendsList.js +0 -79
  101. package/src/apis/getMessage.js +0 -423
  102. package/src/apis/getTheme.js +0 -95
  103. package/src/apis/getThemeInfo.js +0 -116
  104. package/src/apis/getThreadHistory.js +0 -239
  105. package/src/apis/getThreadInfo.js +0 -267
  106. package/src/apis/getThreadList.js +0 -232
  107. package/src/apis/getThreadPictures.js +0 -58
  108. package/src/apis/getUserID.js +0 -117
  109. package/src/apis/getUserInfo.js +0 -513
  110. package/src/apis/getUserInfoV2.js +0 -146
  111. package/src/apis/handleMessageRequest.js +0 -50
  112. package/src/apis/httpPost.js +0 -89
  113. package/src/apis/httpPostFormData.js +0 -69
  114. package/src/apis/listenMqtt.js +0 -1236
  115. package/src/apis/listenSpeed.js +0 -179
  116. package/src/apis/logout.js +0 -87
  117. package/src/apis/markAsDelivered.js +0 -47
  118. package/src/apis/markAsReadAll.js +0 -40
  119. package/src/apis/markAsSeen.js +0 -70
  120. package/src/apis/mqttDeltaValue.js +0 -278
  121. package/src/apis/muteThread.js +0 -45
  122. package/src/apis/nickname.js +0 -132
  123. package/src/apis/notes.js +0 -163
  124. package/src/apis/pinMessage.js +0 -150
  125. package/src/apis/produceMetaTheme.js +0 -180
  126. package/src/apis/realtime.js +0 -182
  127. package/src/apis/removeUserFromGroup.js +0 -117
  128. package/src/apis/resolvePhotoUrl.js +0 -58
  129. package/src/apis/searchForThread.js +0 -154
  130. package/src/apis/sendMessage.js +0 -354
  131. package/src/apis/sendMessageMqtt.js +0 -249
  132. package/src/apis/sendTypingIndicator.js +0 -91
  133. package/src/apis/setMessageReaction.js +0 -27
  134. package/src/apis/setMessageReactionMqtt.js +0 -61
  135. package/src/apis/setThreadTheme.js +0 -260
  136. package/src/apis/setThreadThemeMqtt.js +0 -94
  137. package/src/apis/share.js +0 -107
  138. package/src/apis/shareContact.js +0 -66
  139. package/src/apis/stickers.js +0 -257
  140. package/src/apis/story.js +0 -181
  141. package/src/apis/theme.js +0 -233
  142. package/src/apis/unfriend.js +0 -47
  143. package/src/apis/unsendMessage.js +0 -17
  144. package/src/engine/client.js +0 -92
  145. package/src/engine/models/buildAPI.js +0 -152
  146. package/src/engine/models/loginHelper.js +0 -519
  147. package/src/engine/models/setOptions.js +0 -88
  148. package/src/security/e2ee.js +0 -109
  149. package/src/types/index.d.ts +0 -498
  150. package/src/utils/antiSuspension.js +0 -506
  151. package/src/utils/auth-helpers.js +0 -149
  152. package/src/utils/autoReLogin.js +0 -336
  153. package/src/utils/axios.js +0 -436
  154. package/src/utils/cache.js +0 -54
  155. package/src/utils/clients.js +0 -282
  156. package/src/utils/constants.js +0 -410
  157. package/src/utils/formatters/data/formatAttachment.js +0 -370
  158. package/src/utils/formatters/data/formatDelta.js +0 -109
  159. package/src/utils/formatters/index.js +0 -159
  160. package/src/utils/formatters/value/formatCookie.js +0 -91
  161. package/src/utils/formatters/value/formatDate.js +0 -36
  162. package/src/utils/formatters/value/formatID.js +0 -16
  163. package/src/utils/formatters.js +0 -1373
  164. package/src/utils/headers.js +0 -230
  165. package/src/utils/index.js +0 -153
  166. package/src/utils/monitoring.js +0 -333
  167. package/src/utils/rateLimiter.js +0 -319
  168. package/src/utils/tokenRefresh.js +0 -657
  169. package/src/utils/user-agents.js +0 -238
  170. package/src/utils/validation.js +0 -157
@@ -1,513 +0,0 @@
1
- "use strict";
2
-
3
- const utils = require('../utils');
4
- const _ = require('lodash');
5
- const deepdash = require('deepdash');
6
- deepdash(_);
7
-
8
- const DOC_PRIMARY = "5009315269112105";
9
- const BATCH_PRIMARY = "MessengerParticipantsFetcher";
10
- const DOC_V2 = "24418640587785718";
11
- const FRIENDLY_V2 = "CometHovercardQueryRendererQuery";
12
- const CALLER_V2 = "RelayModern";
13
-
14
- function toJSONMaybe(s) {
15
- if (!s) return null;
16
- if (typeof s === "string") {
17
- const t = s.trim().replace(/^for\s*\(\s*;\s*;\s*\)\s*;/, "");
18
- try { return JSON.parse(t); } catch { return null; }
19
- }
20
- return s;
21
- }
22
-
23
- function usernameFromUrl(raw) {
24
- if (!raw) return null;
25
- try {
26
- const u = new URL(raw);
27
- if (/^www\.facebook\.com$/i.test(u.hostname)) {
28
- const seg = u.pathname.replace(/^\//, "").replace(/\/$/, "");
29
- if (seg && !/^profile\.php$/i.test(seg) && !seg.includes("/")) return seg;
30
- }
31
- } catch { }
32
- return null;
33
- }
34
-
35
- function pickMeta(u) {
36
- let friendshipStatus = null;
37
- let gender = null;
38
- let shortName = u?.short_name || null;
39
- const pa = Array.isArray(u?.primaryActions) ? u.primaryActions : [];
40
- const sa = Array.isArray(u?.secondaryActions) ? u.secondaryActions : [];
41
- const aFriend = pa.find(x => x?.profile_action_type === "FRIEND");
42
- if (aFriend?.client_handler?.profile_action?.restrictable_profile_owner) {
43
- const p = aFriend.client_handler.profile_action.restrictable_profile_owner;
44
- friendshipStatus = p?.friendship_status || null;
45
- gender = p?.gender || gender;
46
- shortName = p?.short_name || shortName;
47
- }
48
- if (!gender || !shortName) {
49
- const aBlock = sa.find(x => x?.profile_action_type === "BLOCK");
50
- const p2 = aBlock?.client_handler?.profile_action?.profile_owner;
51
- if (p2) {
52
- gender = p2.gender || gender;
53
- shortName = p2.short_name || shortName;
54
- }
55
- }
56
- return { friendshipStatus, gender, shortName };
57
- }
58
-
59
- function normalizePrimaryActor(a) {
60
- if (!a) return null;
61
- return {
62
- id: a.id || null,
63
- name: a.name || null,
64
- firstName: a.short_name || null,
65
- vanity: a.username || null,
66
- thumbSrc: a.big_image_src?.uri || null,
67
- profileUrl: a.url || null,
68
- gender: a.gender || null,
69
- type: a.__typename || null,
70
- isFriend: !!a.is_viewer_friend,
71
- isMessengerUser: !!a.is_messenger_user,
72
- isMessageBlockedByViewer: !!a.is_message_blocked_by_viewer,
73
- workInfo: a.work_info || null,
74
- messengerStatus: a.messenger_account_status_category || null
75
- };
76
- }
77
-
78
- function normalizeV2User(u) {
79
- if (!u) return null;
80
- const vanity = usernameFromUrl(u.profile_url || u.url);
81
- const meta = pickMeta(u);
82
- return {
83
- id: u.id || null,
84
- name: u.name || null,
85
- firstName: meta.shortName || null,
86
- vanity: vanity || u.username_for_profile || null,
87
- thumbSrc: u.profile_picture?.uri || null,
88
- profileUrl: u.profile_url || u.url || null,
89
- gender: meta.gender || null,
90
- type: "User",
91
- isFriend: meta.friendshipStatus === "ARE_FRIENDS",
92
- isMessengerUser: null,
93
- isMessageBlockedByViewer: false,
94
- workInfo: null,
95
- messengerStatus: null
96
- };
97
- }
98
-
99
- /**
100
- * @param {object} data
101
- * @param {string} userID
102
- * @returns {object|null}
103
- */
104
- function findMainUserObject(data, userID) {
105
- let mainUserObject = null;
106
- if (!Array.isArray(data)) return null;
107
- function deepFind(obj) {
108
- if (mainUserObject || typeof obj !== 'object' || obj === null) return;
109
- if (obj.id === userID && obj.__typename === 'User' && obj.profile_tabs) {
110
- mainUserObject = obj;
111
- return;
112
- }
113
- for (const k in obj) {
114
- if (obj.hasOwnProperty(k)) {
115
- deepFind(obj[k]);
116
- }
117
- }
118
- }
119
- deepFind({ all: data });
120
- return mainUserObject;
121
- }
122
-
123
- /**
124
- * @param {object} socialContext
125
- * @param {string} keyword
126
- * @returns {string|null}
127
- */
128
- function findSocialContextText(socialContext, keyword) {
129
- if (socialContext && Array.isArray(socialContext.content)) {
130
- for (const item of socialContext.content) {
131
- const text = item?.text?.text;
132
- if (text && text.toLowerCase().includes(keyword.toLowerCase())) {
133
- return text;
134
- }
135
- }
136
- }
137
- return null;
138
- }
139
-
140
- /**
141
- * @param {Array<Object>} dataArray
142
- * @param {string} key
143
- * @returns {any}
144
- */
145
- function findFirstValueByKey(dataArray, key) {
146
- if (!Array.isArray(dataArray)) return null;
147
- let found = null;
148
- function deepSearch(obj) {
149
- if (found !== null || typeof obj !== 'object' || obj === null) return;
150
- if (obj.hasOwnProperty(key)) {
151
- found = obj[key];
152
- return;
153
- }
154
- for (const k in obj) {
155
- if (obj.hasOwnProperty(k)) {
156
- deepSearch(obj[k]);
157
- }
158
- }
159
- }
160
- for (const obj of dataArray) {
161
- deepSearch(obj);
162
- }
163
- return found;
164
- }
165
-
166
- /**
167
- * @param {Array<Object>} allJsonData
168
- * @returns {string|null}
169
- */
170
- function findBioFromProfileTiles(allJsonData) {
171
- try {
172
- const bio = findFirstValueByKey(allJsonData, 'profile_status_text');
173
- return bio?.text || null;
174
- } catch {
175
- return null;
176
- }
177
- }
178
-
179
- /**
180
- * @param {Array<Object>} allJsonData
181
- * @returns {string|null}
182
- */
183
- function findLiveCityFromProfileTiles(allJsonData) {
184
- try {
185
- const result = _.findDeep(allJsonData, (value, key, parent) => {
186
- return key === 'text' &&
187
- typeof value === 'string' &&
188
- value.includes('Lives in') &&
189
- parent?.ranges?.[0]?.entity?.category_type === "CITY_WITH_ID";
190
- });
191
-
192
- if (result) {
193
- return result.value;
194
- }
195
-
196
- return null;
197
- } catch (err) {
198
- return null;
199
- }
200
- }
201
-
202
- module.exports = (defaultFuncs, api, ctx) => {
203
- function createDefaultUser(id) {
204
- return {
205
- id,
206
- name: "Facebook User",
207
- firstName: "Facebook",
208
- lastName: null,
209
- vanity: id,
210
- profilePicUrl: `https://graph.facebook.com/${id}/picture?width=720&height=720&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`,
211
- profileUrl: `https://www.facebook.com/profile.php?id=${id}`,
212
- gender: "no specific gender",
213
- type: "user",
214
- isFriend: false,
215
- isBirthday: false,
216
- isMessengerUser: null,
217
- isMessageBlockedByViewer: false,
218
- workInfo: null,
219
- messengerStatus: null
220
- };
221
- }
222
-
223
- async function fetchPrimaryBatch(ids) {
224
- try {
225
- const form = {
226
- queries: JSON.stringify({
227
- o0: {
228
- doc_id: DOC_PRIMARY,
229
- query_params: { ids }
230
- }
231
- }),
232
- batch_name: BATCH_PRIMARY
233
- };
234
- const resData = await defaultFuncs.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
235
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
236
- if (!resData || resData.length === 0) return {};
237
- const first = resData[0];
238
- if (!first || !first.o0) return {};
239
- if (first.o0.errors && first.o0.errors.length) return {};
240
- const result = first.o0.data;
241
- if (!result || !Array.isArray(result.messaging_actors)) return {};
242
- const out = {};
243
- for (const actor of result.messaging_actors) {
244
- const n = normalizePrimaryActor(actor);
245
- if (n?.id) out[n.id] = n;
246
- }
247
- return out;
248
- } catch (err) {
249
- utils.error("fetchPrimaryBatch", err);
250
- return {};
251
- }
252
- }
253
-
254
- async function fetchV2Single(uid) {
255
- try {
256
- const av = String(ctx?.userID || "");
257
- const variablesObj = {
258
- actionBarRenderLocation: "WWW_COMET_HOVERCARD",
259
- context: "DEFAULT",
260
- entityID: String(uid),
261
- scale: 1,
262
- __relay_internal__pv__WorkCometIsEmployeeGKProviderrelayprovider: false
263
- };
264
- const form = {
265
- av,
266
- fb_api_caller_class: CALLER_V2,
267
- fb_api_req_friendly_name: FRIENDLY_V2,
268
- server_timestamps: true,
269
- doc_id: DOC_V2,
270
- variables: JSON.stringify(variablesObj)
271
- };
272
- const raw = await defaultFuncs.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
273
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
274
- const parsed = toJSONMaybe(raw) ?? raw;
275
- const root = Array.isArray(parsed) ? parsed[0] : parsed;
276
- const user = root?.data?.node?.comet_hovercard_renderer?.user || null;
277
- const n = normalizeV2User(user);
278
- return n && n.id ? { [n.id]: n } : {};
279
- } catch (err) {
280
- utils.error(`fetchV2Single ${uid}`, err);
281
- return {};
282
- }
283
- }
284
-
285
- return function getUserInfo(id, usePayload, callback, groupFields = []) {
286
- let resolveFunc = () => {};
287
- let rejectFunc = () => {};
288
- const returnPromise = new Promise((resolve, reject) => {
289
- resolveFunc = resolve;
290
- rejectFunc = reject;
291
- });
292
-
293
- if (typeof usePayload === 'function') {
294
- callback = usePayload;
295
- usePayload = true;
296
- }
297
- if (usePayload === undefined) usePayload = true;
298
- if (!callback) {
299
- callback = (err, data) => {
300
- if (err) return rejectFunc(err);
301
- resolveFunc(data);
302
- };
303
- }
304
-
305
- const originalIdIsArray = Array.isArray(id);
306
- const ids = originalIdIsArray ? id : [id];
307
-
308
- // Validate user IDs
309
- if (!ctx.validator.validateIDArray(ids, ctx.validator.isValidUserID.bind(ctx.validator))) {
310
- return callback(new Error("Invalid user ID(s)"));
311
- }
312
-
313
- if (usePayload) {
314
- (async () => {
315
- try {
316
- const retObj = {};
317
- const graphqlData = await fetchPrimaryBatch(ids);
318
-
319
- const needFallback = [];
320
- for (const id of ids) {
321
- if (graphqlData[id]) {
322
- const gd = graphqlData[id];
323
- retObj[id] = {
324
- id: gd.id,
325
- name: gd.name,
326
- firstName: gd.firstName,
327
- lastName: gd.name ? (gd.name.split(' ').slice(1).join(' ') || null) : null,
328
- vanity: gd.vanity,
329
- profilePicUrl: gd.thumbSrc || `https://graph.facebook.com/${id}/picture?width=720&height=720&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`,
330
- profileUrl: gd.profileUrl,
331
- gender: gd.gender,
332
- type: gd.type,
333
- isFriend: gd.isFriend,
334
- isBirthday: false,
335
- isMessengerUser: gd.isMessengerUser,
336
- isMessageBlockedByViewer: gd.isMessageBlockedByViewer,
337
- workInfo: gd.workInfo,
338
- messengerStatus: gd.messengerStatus
339
- };
340
- } else {
341
- needFallback.push(id);
342
- }
343
- }
344
-
345
- let stillNeedFallback = needFallback;
346
- if (needFallback.length > 0) {
347
- const v2Results = await Promise.allSettled(needFallback.map(id => fetchV2Single(id)));
348
- stillNeedFallback = [];
349
- for (let i = 0; i < needFallback.length; i++) {
350
- const id = needFallback[i];
351
- const v2Data = v2Results[i].status === "fulfilled" ? v2Results[i].value : {};
352
- if (v2Data[id]) {
353
- const gd = v2Data[id];
354
- retObj[id] = {
355
- id: gd.id,
356
- name: gd.name,
357
- firstName: gd.firstName,
358
- lastName: gd.name ? (gd.name.split(' ').slice(1).join(' ') || null) : null,
359
- vanity: gd.vanity,
360
- profilePicUrl: gd.thumbSrc || `https://graph.facebook.com/${id}/picture?width=720&height=720&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`,
361
- profileUrl: gd.profileUrl,
362
- gender: gd.gender,
363
- type: gd.type,
364
- isFriend: gd.isFriend,
365
- isBirthday: false,
366
- isMessengerUser: gd.isMessengerUser,
367
- isMessageBlockedByViewer: gd.isMessageBlockedByViewer,
368
- workInfo: gd.workInfo,
369
- messengerStatus: gd.messengerStatus
370
- };
371
- } else {
372
- stillNeedFallback.push(id);
373
- }
374
- }
375
- }
376
-
377
- if (stillNeedFallback.length > 0) {
378
- const form = {};
379
- stillNeedFallback.forEach((v, i) => { form[`ids[${i}]`] = v; });
380
- const getGenderString = (code) => code === 1 ? "male" : code === 2 ? "female" : "no specific gender";
381
- const resData = await defaultFuncs.post("https://www.facebook.com/chat/user_info/", ctx.jar, form)
382
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
383
-
384
- if (resData?.error) {
385
- for (const prop of stillNeedFallback) {
386
- retObj[prop] = createDefaultUser(prop);
387
- }
388
- } else {
389
- const profiles = resData?.payload?.profiles;
390
- if (profiles) {
391
- for (const prop in profiles) {
392
- if (profiles.hasOwnProperty(prop)) {
393
- const inner = profiles[prop];
394
- const nameParts = inner.name ? inner.name.split(' ') : [];
395
- retObj[prop] = {
396
- id: prop,
397
- name: inner.name,
398
- firstName: inner.firstName,
399
- lastName: nameParts.length > 1 ? nameParts[nameParts.length - 1] : null,
400
- vanity: inner.vanity,
401
- profilePicUrl: `https://graph.facebook.com/${prop}/picture?width=720&height=720&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`,
402
- profileUrl: inner.uri,
403
- gender: getGenderString(inner.gender),
404
- type: inner.type,
405
- isFriend: inner.is_friend,
406
- isBirthday: !!inner.is_birthday,
407
- searchTokens: inner.searchTokens,
408
- alternateName: inner.alternateName,
409
- isMessengerUser: null,
410
- isMessageBlockedByViewer: false,
411
- workInfo: null,
412
- messengerStatus: null
413
- };
414
- }
415
- }
416
- } else {
417
- for (const prop of stillNeedFallback) {
418
- retObj[prop] = createDefaultUser(prop);
419
- }
420
- }
421
- }
422
- }
423
-
424
- // Ensure all requested IDs have entries in retObj
425
- for (const id of ids) {
426
- if (!retObj[id]) {
427
- retObj[id] = createDefaultUser(id);
428
- }
429
- }
430
-
431
- // Cache the results
432
- for (const id in retObj) {
433
- ctx.cache.set(`user_${id}`, retObj[id]);
434
- }
435
-
436
- // ALWAYS return retObj (map format) for consistency
437
- return callback(null, retObj);
438
- } catch (err) {
439
- utils.error("getUserInfo (payload)", err);
440
- // Instead of returning error, return default users
441
- const retObj = {};
442
- for (const id of ids) {
443
- retObj[id] = createDefaultUser(id);
444
- }
445
- // Cache the default results
446
- for (const id in retObj) {
447
- ctx.cache.set(`user_${id}`, retObj[id]);
448
- }
449
- // ALWAYS return retObj (map format) for consistency
450
- return callback(null, retObj);
451
- }
452
- })();
453
- } else {
454
- const fetchProfile = async (userID) => {
455
- try {
456
- const url = `https://www.facebook.com/${userID}`;
457
- const allJsonData = await utils.json(url, ctx.jar, null, ctx.globalOptions, ctx);
458
- if (!allJsonData || allJsonData.length === 0) throw new Error(`Could not find JSON data for ID: ${userID}`);
459
- const mainUserObject = findMainUserObject(allJsonData, userID);
460
- if (!mainUserObject) throw new Error(`Could not isolate main user object for ID: ${userID}`);
461
- const get = (obj, path) => {
462
- if (!obj || !path) return null;
463
- return path.split('.').reduce((prev, curr) => (prev ? prev[curr] : undefined), obj);
464
- };
465
- const name = mainUserObject.name;
466
- const nameParts = name ? name.split(' ') : [];
467
- const result = {
468
- id: mainUserObject.id,
469
- name: name,
470
- firstName: nameParts[0] || get(mainUserObject, 'short_name') || get(findFirstValueByKey(allJsonData, 'profile_owner'), 'short_name'),
471
- lastName: nameParts.length > 1 ? nameParts[nameParts.length - 1] : null,
472
- vanity: get(mainUserObject, 'vanity') || get(findFirstValueByKey(allJsonData, 'props'), 'userVanity') || null,
473
- profileUrl: mainUserObject.url,
474
- profilePicUrl: `https://graph.facebook.com/${userID}/picture?width=720&height=720&access_token=6628568379%7Cc1e620fa708a1d5696fb991c1bde5662`,
475
- gender: mainUserObject.gender,
476
- type: mainUserObject.__typename,
477
- isFriend: mainUserObject.is_viewer_friend,
478
- isBirthday: !!mainUserObject.is_birthday,
479
- isVerified: !!mainUserObject.show_verified_badge_on_profile,
480
- bio: findBioFromProfileTiles(allJsonData) || get(findFirstValueByKey(allJsonData, 'delegate_page'), 'best_description.text'),
481
- live_city: findLiveCityFromProfileTiles(allJsonData),
482
- headline: get(mainUserObject, 'contextual_headline.text') || get(findFirstValueByKey(allJsonData, 'meta_verified_section'), 'headline'),
483
- followers: findSocialContextText(mainUserObject.profile_social_context, "followers"),
484
- following: findSocialContextText(mainUserObject.profile_social_context, "following"),
485
- coverPhoto: get(mainUserObject, 'cover_photo.photo.image.uri'),
486
- isMessengerUser: null,
487
- isMessageBlockedByViewer: false,
488
- workInfo: null,
489
- messengerStatus: null
490
- };
491
- return result;
492
- } catch (err) {
493
- utils.error(`Failed to fetch profile for ${userID}: ${err.message}`, err);
494
- return createDefaultUser(userID);
495
- }
496
- };
497
-
498
- Promise.all(ids.map(fetchProfile))
499
- .then(results => {
500
- // Cache the results
501
- ids.forEach((id, index) => {
502
- ctx.cache.set(`user_${id}`, results[index]);
503
- });
504
- return originalIdIsArray ? callback(null, results) : callback(null, results[0] || null);
505
- })
506
- .catch(err => {
507
- utils.error("getUserInfo (fetch)", err);
508
- callback(err);
509
- });
510
- }
511
- return returnPromise;
512
- };
513
- };
@@ -1,146 +0,0 @@
1
- "use strict";
2
-
3
- const utils = require('../utils');
4
-
5
- const DOC_V2 = "24418640587785718";
6
- const FRIENDLY_V2 = "CometHovercardQueryRendererQuery";
7
- const CALLER_V2 = "RelayModern";
8
-
9
- function toJSONMaybe(s) {
10
- if (!s) return null;
11
- if (typeof s === "string") {
12
- const t = s.trim().replace(/^for\s*\(\s*;\s*;\s*\)\s*;/, "");
13
- try { return JSON.parse(t); } catch { return null; }
14
- }
15
- return s;
16
- }
17
-
18
- function usernameFromUrl(raw) {
19
- if (!raw) return null;
20
- try {
21
- const u = new URL(raw);
22
- if (/^www\.facebook\.com$/i.test(u.hostname)) {
23
- const seg = u.pathname.replace(/^\//, "").replace(/\/$/, "");
24
- if (seg && !/^profile\.php$/i.test(seg) && !seg.includes("/")) return seg;
25
- }
26
- } catch { }
27
- return null;
28
- }
29
-
30
- function pickMeta(u) {
31
- let friendshipStatus = null;
32
- let gender = null;
33
- let shortName = u?.short_name || null;
34
- const pa = Array.isArray(u?.primaryActions) ? u.primaryActions : [];
35
- const sa = Array.isArray(u?.secondaryActions) ? u.secondaryActions : [];
36
- const aFriend = pa.find(x => x?.profile_action_type === "FRIEND");
37
- if (aFriend?.client_handler?.profile_action?.restrictable_profile_owner) {
38
- const p = aFriend.client_handler.profile_action.restrictable_profile_owner;
39
- friendshipStatus = p?.friendship_status || null;
40
- gender = p?.gender || gender;
41
- shortName = p?.short_name || shortName;
42
- }
43
- if (!gender || !shortName) {
44
- const aBlock = sa.find(x => x?.profile_action_type === "BLOCK");
45
- const p2 = aBlock?.client_handler?.profile_action?.profile_owner;
46
- if (p2) {
47
- gender = p2.gender || gender;
48
- shortName = p2.short_name || shortName;
49
- }
50
- }
51
- return { friendshipStatus, gender, shortName };
52
- }
53
-
54
- function normalizeUser(u) {
55
- if (!u) return null;
56
- const vanity = usernameFromUrl(u.profile_url || u.url);
57
- const meta = pickMeta(u);
58
- return {
59
- id: u.id || null,
60
- name: u.name || null,
61
- username: vanity || u.username_for_profile || null,
62
- profileUrl: u.profile_url || u.url || null,
63
- url: u.url || null,
64
- isVerified: !!u.is_verified,
65
- isMemorialized: !!u.is_visibly_memorialized,
66
- avatar: u.profile_picture?.uri || null,
67
- shortName: meta.shortName || null,
68
- gender: meta.gender || null,
69
- friendshipStatus: meta.friendshipStatus || null
70
- };
71
- }
72
-
73
- function toRetObjEntry(nu) {
74
- return {
75
- name: nu?.name || null,
76
- firstName: nu?.shortName || null,
77
- vanity: nu?.username || null,
78
- thumbSrc: nu?.avatar || null,
79
- profileUrl: nu?.profileUrl || null,
80
- gender: nu?.gender || null,
81
- type: "User",
82
- isFriend: nu?.friendshipStatus === "ARE_FRIENDS",
83
- isMessengerUser: null,
84
- isMessageBlockedByViewer: false,
85
- workInfo: null,
86
- messengerStatus: null,
87
- isVerified: nu?.isVerified || false,
88
- isMemorialized: nu?.isMemorialized || false
89
- };
90
- }
91
-
92
- module.exports = (defaultFuncs, api, ctx) => {
93
- async function fetchOne(uid) {
94
- const av = String(ctx?.userID || "");
95
- const variablesObj = {
96
- actionBarRenderLocation: "WWW_COMET_HOVERCARD",
97
- context: "DEFAULT",
98
- entityID: String(uid),
99
- scale: 1,
100
- __relay_internal__pv__WorkCometIsEmployeeGKProviderrelayprovider: false
101
- };
102
- const form = {
103
- av,
104
- fb_api_caller_class: CALLER_V2,
105
- fb_api_req_friendly_name: FRIENDLY_V2,
106
- server_timestamps: true,
107
- doc_id: DOC_V2,
108
- variables: JSON.stringify(variablesObj)
109
- };
110
- const raw = await defaultFuncs.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
111
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
112
- const parsed = toJSONMaybe(raw) ?? raw;
113
- const root = Array.isArray(parsed) ? parsed[0] : parsed;
114
- const user = root?.data?.node?.comet_hovercard_renderer?.user || null;
115
- return normalizeUser(user);
116
- }
117
-
118
- return function getUserInfoV2(idOrList, callback) {
119
- let resolveFunc, rejectFunc;
120
- const returnPromise = new Promise((resolve, reject) => {
121
- resolveFunc = resolve;
122
- rejectFunc = reject;
123
- });
124
- if (typeof callback !== "function") {
125
- callback = (err, data) => {
126
- if (err) return rejectFunc(err);
127
- resolveFunc(data);
128
- };
129
- }
130
- const ids = Array.isArray(idOrList) ? idOrList.map(v => String(v)) : [String(idOrList)];
131
- Promise.allSettled(ids.map(fetchOne))
132
- .then(results => {
133
- const retObj = {};
134
- for (let i = 0; i < ids.length; i++) {
135
- const nu = results[i].status === "fulfilled" ? results[i].value : null;
136
- retObj[ids[i]] = toRetObjEntry(nu);
137
- }
138
- return callback(null, retObj);
139
- })
140
- .catch(err => {
141
- utils.error("getUserInfoV2", err);
142
- callback(err);
143
- });
144
- return returnPromise;
145
- };
146
- };
@@ -1,50 +0,0 @@
1
- "use strict";
2
-
3
- const utils = require('../utils');
4
-
5
- module.exports = (defaultFuncs, api, ctx) => {
6
- return async function handleMessageRequest(threadID, accept, callback) {
7
- let resolveFunc = () => {};
8
- let rejectFunc = () => {};
9
- const returnPromise = new Promise((resolve, reject) => {
10
- resolveFunc = resolve;
11
- rejectFunc = reject;
12
- });
13
-
14
- if (!callback) {
15
- callback = (err, result) => {
16
- if (err) return rejectFunc(err);
17
- resolveFunc(result);
18
- };
19
- }
20
-
21
- try {
22
- if (utils.getType(accept) === "Function") {
23
- callback = accept;
24
- accept = true;
25
- }
26
-
27
- const form = {
28
- ids: `ids[${threadID}]=${threadID}`,
29
- action: accept ? "accept" : "reject"
30
- };
31
-
32
- const res = await defaultFuncs.post(
33
- "https://www.facebook.com/ajax/mercury/handle_message_requests.php",
34
- ctx.jar,
35
- form
36
- ).then(utils.parseAndCheckLogin(ctx, defaultFuncs));
37
-
38
- if (res && res.error) {
39
- throw res;
40
- }
41
-
42
- return callback(null, { success: true, accepted: accept });
43
- } catch (err) {
44
- utils.error("handleMessageRequest", err);
45
- callback(err);
46
- }
47
-
48
- return returnPromise;
49
- };
50
- };