@dongdev/fca-unofficial 1.0.19 → 2.0.0

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 (128) hide show
  1. package/.gitattributes +1 -0
  2. package/CHANGELOG.md +30 -27
  3. package/DOCS.md +727 -592
  4. package/README.md +94 -97
  5. package/func/logger.js +112 -0
  6. package/html.html +474 -0
  7. package/index.js +1 -379
  8. package/module/config.js +26 -0
  9. package/module/login.js +45 -0
  10. package/module/loginHelper.js +634 -0
  11. package/module/options.js +49 -0
  12. package/package.json +6 -39
  13. package/src/api/action/addExternalModule.js +25 -0
  14. package/src/api/action/changeAvatar.js +136 -0
  15. package/src/api/action/changeBio.js +76 -0
  16. package/src/api/action/getCurrentUserID.js +7 -0
  17. package/src/api/action/handleFriendRequest.js +57 -0
  18. package/src/api/action/logout.js +75 -0
  19. package/src/{refreshFb_dtsg.js → api/action/refreshFb_dtsg.js} +8 -8
  20. package/src/api/action/setPostReaction.js +107 -0
  21. package/src/api/action/unfriend.js +55 -0
  22. package/src/api/http/httpGet.js +65 -0
  23. package/src/api/http/httpPost.js +65 -0
  24. package/src/{postFormData.js → api/http/postFormData.js} +10 -10
  25. package/src/api/messaging/addUserToGroup.js +69 -0
  26. package/src/api/messaging/changeAdminStatus.js +103 -0
  27. package/src/api/messaging/changeArchivedStatus.js +55 -0
  28. package/src/api/messaging/changeBlockedStatus.js +49 -0
  29. package/src/api/messaging/changeGroupImage.js +135 -0
  30. package/src/api/messaging/changeNickname.js +59 -0
  31. package/src/api/messaging/changeThreadColor.js +65 -0
  32. package/src/api/messaging/createNewGroup.js +88 -0
  33. package/src/api/messaging/createPoll.js +70 -0
  34. package/src/api/messaging/deleteMessage.js +56 -0
  35. package/src/api/messaging/deleteThread.js +56 -0
  36. package/src/api/messaging/forwardAttachment.js +60 -0
  37. package/src/api/messaging/getEmojiUrl.js +29 -0
  38. package/src/api/messaging/getFriendsList.js +83 -0
  39. package/src/api/messaging/getMessage.js +834 -0
  40. package/src/api/messaging/getThreadHistory.js +681 -0
  41. package/src/api/messaging/handleMessageRequest.js +65 -0
  42. package/src/api/messaging/markAsDelivered.js +57 -0
  43. package/src/api/messaging/markAsRead.js +88 -0
  44. package/src/api/messaging/markAsReadAll.js +50 -0
  45. package/src/api/messaging/markAsSeen.js +61 -0
  46. package/src/api/messaging/muteThread.js +51 -0
  47. package/src/api/messaging/removeUserFromGroup.js +79 -0
  48. package/src/api/messaging/resolvePhotoUrl.js +44 -0
  49. package/src/api/messaging/searchForThread.js +53 -0
  50. package/src/api/messaging/sendMessage.js +306 -0
  51. package/src/api/messaging/sendMessageMqtt.js +321 -0
  52. package/src/api/messaging/sendTypingIndicator.js +110 -0
  53. package/src/{setMessageReaction.js → api/messaging/setMessageReaction.js} +20 -20
  54. package/src/api/messaging/setTitle.js +90 -0
  55. package/src/api/messaging/shareContact.js +51 -0
  56. package/src/api/messaging/threadColors.js +131 -0
  57. package/src/api/messaging/unsendMessage.js +44 -0
  58. package/src/api/messaging/uploadAttachment.js +93 -0
  59. package/src/api/socket/detail/buildStream.js +100 -0
  60. package/src/{listenMqtt.js → api/socket/listenMqtt.js} +172 -256
  61. package/src/api/threads/changeThreadEmoji.js +55 -0
  62. package/src/api/threads/getThreadInfo.js +572 -0
  63. package/src/{getThreadList.js → api/threads/getThreadList.js} +110 -54
  64. package/src/api/threads/getThreadPictures.js +79 -0
  65. package/src/api/users/getUserID.js +66 -0
  66. package/src/api/users/getUserInfo.js +88 -0
  67. package/src/core/sendReqMqtt.js +63 -0
  68. package/{lib → src}/database/models/index.js +12 -10
  69. package/{lib → src}/database/models/thread.js +5 -5
  70. package/{lib → src}/database/threadData.js +19 -14
  71. package/src/utils/client.js +159 -0
  72. package/src/utils/constants.js +13 -0
  73. package/src/utils/format.js +60 -0
  74. package/src/utils/headers.js +41 -0
  75. package/src/utils/index.js +1497 -0
  76. package/src/utils/request.js +147 -0
  77. package/lib/logger.js +0 -96
  78. package/src/addExternalModule.js +0 -19
  79. package/src/addUserToGroup.js +0 -113
  80. package/src/changeAdminStatus.js +0 -79
  81. package/src/changeArchivedStatus.js +0 -55
  82. package/src/changeAvatar.js +0 -126
  83. package/src/changeBio.js +0 -77
  84. package/src/changeBlockedStatus.js +0 -47
  85. package/src/changeGroupImage.js +0 -132
  86. package/src/changeNickname.js +0 -59
  87. package/src/changeThreadColor.js +0 -65
  88. package/src/changeThreadEmoji.js +0 -55
  89. package/src/createNewGroup.js +0 -86
  90. package/src/createPoll.js +0 -71
  91. package/src/deleteMessage.js +0 -56
  92. package/src/deleteThread.js +0 -56
  93. package/src/forwardAttachment.js +0 -60
  94. package/src/getCurrentUserID.js +0 -7
  95. package/src/getEmojiUrl.js +0 -29
  96. package/src/getFriendsList.js +0 -83
  97. package/src/getMessage.js +0 -796
  98. package/src/getThreadHistory.js +0 -666
  99. package/src/getThreadInfo.js +0 -535
  100. package/src/getThreadPictures.js +0 -79
  101. package/src/getUserID.js +0 -66
  102. package/src/getUserInfo.js +0 -80
  103. package/src/handleFriendRequest.js +0 -61
  104. package/src/handleMessageRequest.js +0 -65
  105. package/src/httpGet.js +0 -57
  106. package/src/httpPost.js +0 -57
  107. package/src/httpPostFormData.js +0 -63
  108. package/src/logout.js +0 -75
  109. package/src/markAsDelivered.js +0 -58
  110. package/src/markAsRead.js +0 -80
  111. package/src/markAsReadAll.js +0 -50
  112. package/src/markAsSeen.js +0 -59
  113. package/src/muteThread.js +0 -52
  114. package/src/removeUserFromGroup.js +0 -79
  115. package/src/resolvePhotoUrl.js +0 -45
  116. package/src/searchForThread.js +0 -53
  117. package/src/sendMessage.js +0 -328
  118. package/src/sendMessageMqtt.js +0 -316
  119. package/src/sendTypingIndicator.js +0 -103
  120. package/src/setPostReaction.js +0 -109
  121. package/src/setTitle.js +0 -86
  122. package/src/shareContact.js +0 -49
  123. package/src/threadColors.js +0 -131
  124. package/src/unfriend.js +0 -52
  125. package/src/unsendMessage.js +0 -49
  126. package/src/uploadAttachment.js +0 -95
  127. package/utils.js +0 -1387
  128. /package/{lib → func}/login.js +0 -0
@@ -1,535 +0,0 @@
1
- "use strict";
2
- /*
3
- const utils = require("../utils");
4
- const log = require("npmlog");
5
- const fs = require("fs");
6
- const path = require("path");
7
- const logger = require("../lib/logger");
8
- function formatEventReminders(reminder) {
9
- return {
10
- reminderID: reminder.id,
11
- eventCreatorID: reminder.lightweight_event_creator.id,
12
- time: reminder.time,
13
- eventType: reminder.lightweight_event_type.toLowerCase(),
14
- locationName: reminder.location_name,
15
- locationCoordinates: reminder.location_coordinates,
16
- locationPage: reminder.location_page,
17
- eventStatus: reminder.lightweight_event_status.toLowerCase(),
18
- note: reminder.note,
19
- repeatMode: reminder.repeat_mode.toLowerCase(),
20
- eventTitle: reminder.event_title,
21
- triggerMessage: reminder.trigger_message,
22
- secondsToNotifyBefore: reminder.seconds_to_notify_before,
23
- allowsRsvp: reminder.allows_rsvp,
24
- relatedEvent: reminder.related_event,
25
- members: reminder.event_reminder_members.edges.map(function(member) {
26
- return {
27
- memberID: member.node.id,
28
- state: member.guest_list_state.toLowerCase(),
29
- };
30
- }),
31
- };
32
- }
33
- function formatThreadGraphQLResponse(data) {
34
- if (!data) return;
35
- if (data?.errors) return data.errors;
36
- const messageThread = data.message_thread;
37
- if (!messageThread) return null;
38
- const threadID = messageThread.thread_key.thread_fbid
39
- ? messageThread.thread_key.thread_fbid
40
- : messageThread.thread_key.other_user_id;
41
- const lastM = messageThread.last_message;
42
- const snippetID =
43
- lastM &&
44
- lastM.nodes &&
45
- lastM.nodes[0] &&
46
- lastM.nodes[0].message_sender &&
47
- lastM.nodes[0].message_sender.messaging_actor
48
- ? lastM.nodes[0].message_sender.messaging_actor.id
49
- : null;
50
- const snippetText =
51
- lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
52
- const lastR = messageThread.last_read_receipt;
53
- const lastReadTimestamp =
54
- lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
55
- ? lastR.nodes[0].timestamp_precise
56
- : null;
57
-
58
- return {
59
- threadID: threadID,
60
- threadName: messageThread.name,
61
- participantIDs: messageThread.all_participants.edges.map(
62
- (d) => d.node.messaging_actor.id
63
- ),
64
- userInfo: messageThread.all_participants.edges.map((d) => ({
65
- id: d.node.messaging_actor.id,
66
- name: d.node.messaging_actor.name,
67
- firstName: d.node.messaging_actor.short_name,
68
- vanity: d.node.messaging_actor.username,
69
- url: d.node.messaging_actor.url,
70
- thumbSrc: d.node.messaging_actor.big_image_src.uri,
71
- profileUrl: d.node.messaging_actor.big_image_src.uri,
72
- gender: d.node.messaging_actor.gender,
73
- type: d.node.messaging_actor.__typename,
74
- isFriend: d.node.messaging_actor.is_viewer_friend,
75
- isBirthday: !!d.node.messaging_actor.is_birthday,
76
- })),
77
- unreadCount: messageThread.unread_count,
78
- messageCount: messageThread.messages_count,
79
- timestamp: messageThread.updated_time_precise,
80
- muteUntil: messageThread.mute_until,
81
- isGroup: messageThread.thread_type == "GROUP",
82
- isSubscribed: messageThread.is_viewer_subscribed,
83
- isArchived: messageThread.has_viewer_archived,
84
- folder: messageThread.folder,
85
- cannotReplyReason: messageThread.cannot_reply_reason,
86
- eventReminders: messageThread.event_reminders
87
- ? messageThread.event_reminders.nodes.map(formatEventReminders)
88
- : null,
89
- emoji: messageThread.customization_info
90
- ? messageThread.customization_info.emoji
91
- : null,
92
- color:
93
- messageThread.customization_info &&
94
- messageThread.customization_info.outgoing_bubble_color
95
- ? messageThread.customization_info.outgoing_bubble_color.slice(2)
96
- : null,
97
- threadTheme: messageThread.thread_theme,
98
- nicknames:
99
- messageThread.customization_info &&
100
- messageThread.customization_info.participant_customizations
101
- ? messageThread.customization_info.participant_customizations.reduce(
102
- function(res, val) {
103
- if (val.nickname) res[val.participant_id] = val.nickname;
104
- return res;
105
- },
106
- {}
107
- )
108
- : {},
109
- adminIDs: messageThread.thread_admins,
110
- approvalMode: Boolean(messageThread.approval_mode),
111
- approvalQueue: messageThread.group_approval_queue.nodes.map((a) => ({
112
- inviterID: a.inviter.id,
113
- requesterID: a.requester.id,
114
- timestamp: a.request_timestamp,
115
- request_source: a.request_source,
116
- })),
117
- reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
118
- mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
119
- isPinProtected: messageThread.is_pin_protected,
120
- relatedPageThread: messageThread.related_page_thread,
121
- name: messageThread.name,
122
- snippet: snippetText,
123
- snippetSender: snippetID,
124
- snippetAttachments: [],
125
- serverTimestamp: messageThread.updated_time_precise,
126
- imageSrc: messageThread.image ? messageThread.image.uri : null,
127
- isCanonicalUser: messageThread.is_canonical_neo_user,
128
- isCanonical: messageThread.thread_type != "GROUP",
129
- recipientsLoadable: true,
130
- hasEmailParticipant: false,
131
- readOnly: false,
132
- canReply: messageThread.cannot_reply_reason == null,
133
- lastMessageTimestamp: messageThread.last_message
134
- ? messageThread.last_message.timestamp_precise
135
- : null,
136
- lastMessageType: "message",
137
- lastReadTimestamp: lastReadTimestamp,
138
- threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
139
- inviteLink: {
140
- enable: messageThread.joinable_mode
141
- ? messageThread.joinable_mode.mode == 1
142
- : false,
143
- link: messageThread.joinable_mode
144
- ? messageThread.joinable_mode.link
145
- : null,
146
- },
147
- };
148
- }
149
- const queue = [];
150
- let isProcessingQueue = false;
151
- const processingThreads = new Set();
152
- const queuedThreads = new Set();
153
- module.exports = function(defaultFuncs, api, ctx) {
154
- const getMultiInfo = async function(threadIDs) {
155
- let form = {};
156
- let tempThreadInf = [];
157
- threadIDs.forEach((x, y) => {
158
- form["o" + y] = {
159
- doc_id: "3449967031715030",
160
- query_params: {
161
- id: x,
162
- message_limit: 0,
163
- load_messages: false,
164
- load_read_receipts: false,
165
- before: null,
166
- },
167
- };
168
- });
169
- let Submit = {
170
- queries: JSON.stringify(form),
171
- batch_name: "MessengerGraphQLThreadFetcher",
172
- };
173
- try {
174
- const resData = await defaultFuncs
175
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, Submit)
176
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
177
- if (resData.error || resData[resData.length - 1].error_results !== 0)
178
- throw new Error(
179
- "Error: getThreadInfoGraphQL - You may be rate limited"
180
- );
181
- resData
182
- .slice(0, -1)
183
- .sort((a, b) => Object.keys(a)[0].localeCompare(Object.keys(b)[0]))
184
- .forEach((x, y) =>
185
- tempThreadInf.push(formatThreadGraphQLResponse(x["o" + y].data))
186
- );
187
- return { Success: true, Data: tempThreadInf };
188
- } catch (err) {
189
- return { Success: false, Data: "" };
190
- }
191
- };
192
- const dbFiles = fs
193
- .readdirSync(path.join(__dirname, "../lib/database"))
194
- .filter((f) => path.extname(f) === ".js")
195
- .reduce((acc, file) => {
196
- acc[path.basename(file, ".js")] = require(path.join(
197
- __dirname,
198
- "../lib/database",
199
- file
200
- ))(api);
201
- return acc;
202
- }, {});
203
- const { threadData } = dbFiles;
204
- const { create, get, update, getAll } = threadData;
205
- async function fetchThreadInfo(tID, isNew) {
206
- try {
207
- const response = await getMultiInfo([tID]);
208
- if (!response.Success) throw new Error("Failed to fetch thread info");
209
- const threadInfo = response.Data[0];
210
- if (isNew) {
211
- await create(tID, { data: threadInfo });
212
- logger(`Success create data thread: ${tID}`, 'info');
213
- } else {
214
- await update(tID, { data: threadInfo });
215
- logger(`Success update data thread: ${tID}`, 'info');
216
- }
217
- } catch (err) {
218
- console.error("fetchThreadInfo", err);
219
- } finally {
220
- queuedThreads.delete(tID);
221
- }
222
- }
223
- async function checkAndUpdateThreads() {
224
- try {
225
- const allThreads = await getAll("threadID");
226
- const existingThreadIDs = new Set(allThreads.map((t) => t.threadID));
227
- for (const t of existingThreadIDs) {
228
- const result = await get(t);
229
- if (!result) continue;
230
- const now = Date.now();
231
- const lastUpdated = new Date(result.updatedAt).getTime();
232
- if ((now - lastUpdated) / (1000 * 60) > 10 && !queuedThreads.has(t)) {
233
- queuedThreads.add(t);
234
- logger(`ThreadID ${t} aready update data`, 'info');
235
- queue.push(() => fetchThreadInfo(t, false));
236
- }
237
- }
238
- } catch (err) {
239
- console.error("checkAndUpdateThreads", err);
240
- }
241
- }
242
- async function processQueue() {
243
- if (isProcessingQueue) return;
244
- isProcessingQueue = true;
245
- while (queue.length > 0) {
246
- const task = queue.shift();
247
- try {
248
- await task();
249
- } catch (err) {
250
- console.error("Queue processing error", err);
251
- }
252
- }
253
- isProcessingQueue = false;
254
- }
255
- setInterval(() => {
256
- checkAndUpdateThreads();
257
- processQueue();
258
- }, 10000);
259
- return async function getThreadInfoGraphQL(threadID, callback) {
260
- let resolveFunc = function() {};
261
- let rejectFunc = function() {};
262
- const returnPromise = new Promise(function(resolve, reject) {
263
- resolveFunc = resolve;
264
- rejectFunc = reject;
265
- });
266
- if (
267
- utils.getType(callback) != "Function" &&
268
- utils.getType(callback) != "AsyncFunction"
269
- ) {
270
- callback = function(err, data) {
271
- if (err) {
272
- return rejectFunc(err);
273
- }
274
- resolveFunc(data);
275
- };
276
- }
277
- if (utils.getType(threadID) !== "Array") {
278
- threadID = [threadID];
279
- }
280
- let result;
281
- try {
282
- result = await get(threadID[0]);
283
- if (result) {
284
- callback(null, result.data);
285
- } else {
286
- if (!processingThreads.has(threadID[0])) {
287
- processingThreads.add(threadID[0]);
288
- logger(`Created new thread data: ${threadID[0]}`, 'info');
289
- const response = await getMultiInfo(threadID);
290
- if (!response.Success) throw new Error("Failed to get thread info");
291
- const data = response.Data[0];
292
- await create(threadID[0], { data });
293
- callback(null, data);
294
- processingThreads.delete(threadID[0]);
295
- }
296
- }
297
- } catch (err) {
298
- callback(err);
299
- }
300
- return returnPromise;
301
- };
302
- };
303
- */
304
- "use strict";
305
-
306
- const utils = require("../utils");
307
- const log = require("npmlog");
308
-
309
- function formatEventReminders(reminder) {
310
- return {
311
- reminderID: reminder.id,
312
- eventCreatorID: reminder.lightweight_event_creator.id,
313
- time: reminder.time,
314
- eventType: reminder.lightweight_event_type.toLowerCase(),
315
- locationName: reminder.location_name,
316
- // @TODO verify this
317
- locationCoordinates: reminder.location_coordinates,
318
- locationPage: reminder.location_page,
319
- eventStatus: reminder.lightweight_event_status.toLowerCase(),
320
- note: reminder.note,
321
- repeatMode: reminder.repeat_mode.toLowerCase(),
322
- eventTitle: reminder.event_title,
323
- triggerMessage: reminder.trigger_message,
324
- secondsToNotifyBefore: reminder.seconds_to_notify_before,
325
- allowsRsvp: reminder.allows_rsvp,
326
- relatedEvent: reminder.related_event,
327
- members: reminder.event_reminder_members.edges.map(function (member) {
328
- return {
329
- memberID: member.node.id,
330
- state: member.guest_list_state.toLowerCase()
331
- };
332
- })
333
- };
334
- }
335
-
336
- function formatThreadGraphQLResponse(data) {
337
- if (data.errors)
338
- return data.errors;
339
- const messageThread = data.message_thread;
340
- if (!messageThread)
341
- return null;
342
- const threadID = messageThread.thread_key.thread_fbid
343
- ? messageThread.thread_key.thread_fbid
344
- : messageThread.thread_key.other_user_id;
345
-
346
- // Remove me
347
- const lastM = messageThread.last_message;
348
- const snippetID =
349
- lastM &&
350
- lastM.nodes &&
351
- lastM.nodes[0] &&
352
- lastM.nodes[0].message_sender &&
353
- lastM.nodes[0].message_sender.messaging_actor
354
- ? lastM.nodes[0].message_sender.messaging_actor.id
355
- : null;
356
- const snippetText =
357
- lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
358
- const lastR = messageThread.last_read_receipt;
359
- const lastReadTimestamp =
360
- lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
361
- ? lastR.nodes[0].timestamp_precise
362
- : null;
363
-
364
- return {
365
- threadID: threadID,
366
- threadName: messageThread.name,
367
- participantIDs: messageThread.all_participants.edges.map(d => d.node.messaging_actor.id),
368
- userInfo: messageThread.all_participants.edges.map(d => ({
369
- id: d.node.messaging_actor.id,
370
- name: d.node.messaging_actor.name,
371
- firstName: d.node.messaging_actor.short_name,
372
- vanity: d.node.messaging_actor.username,
373
- url: d.node.messaging_actor.url,
374
- thumbSrc: d.node.messaging_actor.big_image_src.uri,
375
- profileUrl: d.node.messaging_actor.big_image_src.uri,
376
- gender: d.node.messaging_actor.gender,
377
- type: d.node.messaging_actor.__typename,
378
- isFriend: d.node.messaging_actor.is_viewer_friend,
379
- isBirthday: !!d.node.messaging_actor.is_birthday //not sure?
380
- })),
381
- unreadCount: messageThread.unread_count,
382
- messageCount: messageThread.messages_count,
383
- timestamp: messageThread.updated_time_precise,
384
- muteUntil: messageThread.mute_until,
385
- isGroup: messageThread.thread_type == "GROUP",
386
- isSubscribed: messageThread.is_viewer_subscribed,
387
- isArchived: messageThread.has_viewer_archived,
388
- folder: messageThread.folder,
389
- cannotReplyReason: messageThread.cannot_reply_reason,
390
- eventReminders: messageThread.event_reminders
391
- ? messageThread.event_reminders.nodes.map(formatEventReminders)
392
- : null,
393
- emoji: messageThread.customization_info
394
- ? messageThread.customization_info.emoji
395
- : null,
396
- color:
397
- messageThread.customization_info &&
398
- messageThread.customization_info.outgoing_bubble_color
399
- ? messageThread.customization_info.outgoing_bubble_color.slice(2)
400
- : null,
401
- threadTheme: messageThread.thread_theme,
402
- nicknames:
403
- messageThread.customization_info &&
404
- messageThread.customization_info.participant_customizations
405
- ? messageThread.customization_info.participant_customizations.reduce(
406
- function (res, val) {
407
- if (val.nickname) res[val.participant_id] = val.nickname;
408
- return res;
409
- },
410
- {}
411
- )
412
- : {},
413
- adminIDs: messageThread.thread_admins,
414
- approvalMode: Boolean(messageThread.approval_mode),
415
- approvalQueue: messageThread.group_approval_queue.nodes.map(a => ({
416
- inviterID: a.inviter.id,
417
- requesterID: a.requester.id,
418
- timestamp: a.request_timestamp,
419
- request_source: a.request_source // @Undocumented
420
- })),
421
-
422
- // @Undocumented
423
- reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
424
- mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
425
- isPinProtected: messageThread.is_pin_protected,
426
- relatedPageThread: messageThread.related_page_thread,
427
-
428
- // @Legacy
429
- name: messageThread.name,
430
- snippet: snippetText,
431
- snippetSender: snippetID,
432
- snippetAttachments: [],
433
- serverTimestamp: messageThread.updated_time_precise,
434
- imageSrc: messageThread.image ? messageThread.image.uri : null,
435
- isCanonicalUser: messageThread.is_canonical_neo_user,
436
- isCanonical: messageThread.thread_type != "GROUP",
437
- recipientsLoadable: true,
438
- hasEmailParticipant: false,
439
- readOnly: false,
440
- canReply: messageThread.cannot_reply_reason == null,
441
- lastMessageTimestamp: messageThread.last_message
442
- ? messageThread.last_message.timestamp_precise
443
- : null,
444
- lastMessageType: "message",
445
- lastReadTimestamp: lastReadTimestamp,
446
- threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
447
-
448
- // update in Wed, 13 Jul 2022 19:41:12 +0700
449
- inviteLink: {
450
- enable: messageThread.joinable_mode ? messageThread.joinable_mode.mode == 1 : false,
451
- link: messageThread.joinable_mode ? messageThread.joinable_mode.link : null
452
- }
453
- };
454
- }
455
-
456
- module.exports = function (defaultFuncs, api, ctx) {
457
- return function getThreadInfoGraphQL(threadID, callback) {
458
- let resolveFunc = function () { };
459
- let rejectFunc = function () { };
460
- const returnPromise = new Promise(function (resolve, reject) {
461
- resolveFunc = resolve;
462
- rejectFunc = reject;
463
- });
464
-
465
- if (utils.getType(callback) != "Function" && utils.getType(callback) != "AsyncFunction") {
466
- callback = function (err, data) {
467
- if (err) {
468
- return rejectFunc(err);
469
- }
470
- resolveFunc(data);
471
- };
472
- }
473
-
474
- if (utils.getType(threadID) !== "Array") {
475
- threadID = [threadID];
476
- }
477
-
478
- let form = {};
479
- // `queries` has to be a string. I couldn't tell from the dev console. This
480
- // took me a really long time to figure out. I deserve a cookie for this.
481
- threadID.map(function (t, i) {
482
- form["o" + i] = {
483
- doc_id: "3449967031715030",
484
- query_params: {
485
- id: t,
486
- message_limit: 0,
487
- load_messages: false,
488
- load_read_receipts: false,
489
- before: null
490
- }
491
- };
492
- });
493
-
494
- form = {
495
- queries: JSON.stringify(form),
496
- batch_name: "MessengerGraphQLThreadFetcher"
497
- };
498
-
499
- defaultFuncs
500
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
501
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
502
- .then(function (resData) {
503
-
504
- if (resData.error) {
505
- throw resData;
506
- }
507
- // This returns us an array of things. The last one is the success /
508
- // failure one.
509
- // @TODO What do we do in this case?
510
- // if (resData[resData.length - 1].error_results !== 0) {
511
- // throw resData[0].o0.errors[0];
512
- // }
513
- // if (!resData[0].o0.data.message_thread) {
514
- // throw new Error("can't find this thread");
515
- // }
516
- const threadInfos = {};
517
- for (let i = resData.length - 2; i >= 0; i--) {
518
- const threadInfo = formatThreadGraphQLResponse(resData[i][Object.keys(resData[i])[0]].data);
519
- threadInfos[threadInfo?.threadID || threadID[threadID.length - 1 - i]] = threadInfo;
520
- }
521
- if (Object.values(threadInfos).length == 1) {
522
- callback(null, Object.values(threadInfos)[0]);
523
- }
524
- else {
525
- callback(null, threadInfos);
526
- }
527
- })
528
- .catch(function (err) {
529
- log.error("getThreadInfoGraphQL", err);
530
- return callback(err);
531
- });
532
-
533
- return returnPromise;
534
- };
535
- };
@@ -1,79 +0,0 @@
1
- "use strict";
2
-
3
- const utils = require("../utils");
4
- const log = require("npmlog");
5
-
6
- module.exports = function (defaultFuncs, api, ctx) {
7
- return function getThreadPictures(threadID, offset, limit, callback) {
8
- let resolveFunc = function () { };
9
- let rejectFunc = function () { };
10
- const returnPromise = new Promise(function (resolve, reject) {
11
- resolveFunc = resolve;
12
- rejectFunc = reject;
13
- });
14
-
15
- if (!callback) {
16
- callback = function (err, friendList) {
17
- if (err) {
18
- return rejectFunc(err);
19
- }
20
- resolveFunc(friendList);
21
- };
22
- }
23
-
24
- let form = {
25
- thread_id: threadID,
26
- offset: offset,
27
- limit: limit
28
- };
29
-
30
- defaultFuncs
31
- .post(
32
- "https://www.facebook.com/ajax/messaging/attachments/sharedphotos.php",
33
- ctx.jar,
34
- form
35
- )
36
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
37
- .then(function (resData) {
38
- if (resData.error) {
39
- throw resData;
40
- }
41
- return Promise.all(
42
- resData.payload.imagesData.map(function (image) {
43
- form = {
44
- thread_id: threadID,
45
- image_id: image.fbid
46
- };
47
- return defaultFuncs
48
- .post(
49
- "https://www.facebook.com/ajax/messaging/attachments/sharedphotos.php",
50
- ctx.jar,
51
- form
52
- )
53
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
54
- .then(function (resData) {
55
- if (resData.error) {
56
- throw resData;
57
- }
58
- // the response is pretty messy
59
- const queryThreadID =
60
- resData.jsmods.require[0][3][1].query_metadata.query_path[0]
61
- .message_thread;
62
- const imageData =
63
- resData.jsmods.require[0][3][1].query_results[queryThreadID]
64
- .message_images.edges[0].node.image2;
65
- return imageData;
66
- });
67
- })
68
- );
69
- })
70
- .then(function (resData) {
71
- callback(null, resData);
72
- })
73
- .catch(function (err) {
74
- log.error("Error in getThreadPictures", err);
75
- callback(err);
76
- });
77
- return returnPromise;
78
- };
79
- };
package/src/getUserID.js DELETED
@@ -1,66 +0,0 @@
1
- "use strict";
2
-
3
- const utils = require("../utils");
4
- const log = require("npmlog");
5
-
6
- function formatData(data) {
7
- return {
8
- userID: utils.formatID(data.uid.toString()),
9
- photoUrl: data.photo,
10
- indexRank: data.index_rank,
11
- name: data.text,
12
- isVerified: data.is_verified,
13
- profileUrl: data.path,
14
- category: data.category,
15
- score: data.score,
16
- type: data.type
17
- };
18
- }
19
-
20
- module.exports = function (defaultFuncs, api, ctx) {
21
- return function getUserID(name, callback) {
22
- let resolveFunc = function () { };
23
- let rejectFunc = function () { };
24
- const returnPromise = new Promise(function (resolve, reject) {
25
- resolveFunc = resolve;
26
- rejectFunc = reject;
27
- });
28
-
29
- if (!callback) {
30
- callback = function (err, friendList) {
31
- if (err) {
32
- return rejectFunc(err);
33
- }
34
- resolveFunc(friendList);
35
- };
36
- }
37
-
38
- const form = {
39
- value: name.toLowerCase(),
40
- viewer: ctx.i_userID || ctx.userID,
41
- rsp: "search",
42
- context: "search",
43
- path: "/home.php",
44
- request_id: utils.getGUID()
45
- };
46
-
47
- defaultFuncs
48
- .get("https://www.facebook.com/ajax/typeahead/search.php", ctx.jar, form)
49
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
50
- .then(function (resData) {
51
- if (resData.error) {
52
- throw resData;
53
- }
54
-
55
- const data = resData.payload.entries;
56
-
57
- callback(null, data.map(formatData));
58
- })
59
- .catch(function (err) {
60
- log.error("getUserID", err);
61
- return callback(err);
62
- });
63
-
64
- return returnPromise;
65
- };
66
- };