@dongdev/fca-unofficial 3.0.31 → 4.0.1

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/LICENSE +191 -0
  2. package/README.md +238 -398
  3. package/dist/cjs.cjs +9 -0
  4. package/dist/index.d.mts +1250 -0
  5. package/dist/index.d.ts +1250 -0
  6. package/dist/index.js +27772 -0
  7. package/dist/index.mjs +27735 -0
  8. package/docs/ARCHITECTURE.md +467 -0
  9. package/docs/DOCS.md +709 -0
  10. package/fca-config.example.json +33 -0
  11. package/package.json +32 -22
  12. package/test/fca.test.cjs +540 -0
  13. package/CHANGELOG.md +0 -296
  14. package/DOCS.md +0 -2712
  15. package/func/checkUpdate.js +0 -222
  16. package/func/logAdapter.js +0 -33
  17. package/func/logger.js +0 -48
  18. package/index.d.ts +0 -751
  19. package/index.js +0 -8
  20. package/module/config.js +0 -40
  21. package/module/login.js +0 -133
  22. package/module/loginHelper.js +0 -1296
  23. package/module/options.js +0 -44
  24. package/src/api/action/addExternalModule.js +0 -25
  25. package/src/api/action/changeAvatar.js +0 -137
  26. package/src/api/action/changeBio.js +0 -75
  27. package/src/api/action/enableAutoSaveAppState.js +0 -73
  28. package/src/api/action/getCurrentUserID.js +0 -7
  29. package/src/api/action/handleFriendRequest.js +0 -57
  30. package/src/api/action/logout.js +0 -76
  31. package/src/api/action/refreshFb_dtsg.js +0 -48
  32. package/src/api/action/setPostReaction.js +0 -106
  33. package/src/api/action/unfriend.js +0 -54
  34. package/src/api/http/httpGet.js +0 -46
  35. package/src/api/http/httpPost.js +0 -52
  36. package/src/api/http/postFormData.js +0 -47
  37. package/src/api/messaging/addUserToGroup.js +0 -68
  38. package/src/api/messaging/changeAdminStatus.js +0 -126
  39. package/src/api/messaging/changeArchivedStatus.js +0 -55
  40. package/src/api/messaging/changeBlockedStatus.js +0 -48
  41. package/src/api/messaging/changeGroupImage.js +0 -91
  42. package/src/api/messaging/changeNickname.js +0 -70
  43. package/src/api/messaging/changeThreadColor.js +0 -79
  44. package/src/api/messaging/changeThreadEmoji.js +0 -111
  45. package/src/api/messaging/createNewGroup.js +0 -88
  46. package/src/api/messaging/createPoll.js +0 -46
  47. package/src/api/messaging/createThemeAI.js +0 -98
  48. package/src/api/messaging/deleteMessage.js +0 -136
  49. package/src/api/messaging/deleteThread.js +0 -56
  50. package/src/api/messaging/editMessage.js +0 -68
  51. package/src/api/messaging/forwardAttachment.js +0 -57
  52. package/src/api/messaging/getEmojiUrl.js +0 -29
  53. package/src/api/messaging/getFriendsList.js +0 -82
  54. package/src/api/messaging/getMessage.js +0 -829
  55. package/src/api/messaging/getThemePictures.js +0 -62
  56. package/src/api/messaging/handleMessageRequest.js +0 -65
  57. package/src/api/messaging/markAsDelivered.js +0 -57
  58. package/src/api/messaging/markAsRead.js +0 -88
  59. package/src/api/messaging/markAsReadAll.js +0 -49
  60. package/src/api/messaging/markAsSeen.js +0 -61
  61. package/src/api/messaging/muteThread.js +0 -50
  62. package/src/api/messaging/removeUserFromGroup.js +0 -62
  63. package/src/api/messaging/resolvePhotoUrl.js +0 -43
  64. package/src/api/messaging/scheduler.js +0 -264
  65. package/src/api/messaging/searchForThread.js +0 -53
  66. package/src/api/messaging/sendMessage.js +0 -270
  67. package/src/api/messaging/sendTypingIndicator.js +0 -74
  68. package/src/api/messaging/setMessageReaction.js +0 -90
  69. package/src/api/messaging/setTitle.js +0 -124
  70. package/src/api/messaging/shareContact.js +0 -49
  71. package/src/api/messaging/threadColors.js +0 -128
  72. package/src/api/messaging/unsendMessage.js +0 -81
  73. package/src/api/messaging/uploadAttachment.js +0 -492
  74. package/src/api/socket/core/connectMqtt.js +0 -258
  75. package/src/api/socket/core/emitAuth.js +0 -103
  76. package/src/api/socket/core/getSeqID.js +0 -320
  77. package/src/api/socket/core/getTaskResponseData.js +0 -25
  78. package/src/api/socket/core/parseDelta.js +0 -377
  79. package/src/api/socket/detail/buildStream.js +0 -215
  80. package/src/api/socket/detail/constants.js +0 -28
  81. package/src/api/socket/listenMqtt.js +0 -377
  82. package/src/api/socket/middleware/index.js +0 -216
  83. package/src/api/threads/getThreadHistory.js +0 -664
  84. package/src/api/threads/getThreadInfo.js +0 -296
  85. package/src/api/threads/getThreadList.js +0 -293
  86. package/src/api/threads/getThreadPictures.js +0 -78
  87. package/src/api/users/getUserID.js +0 -65
  88. package/src/api/users/getUserInfo.js +0 -402
  89. package/src/api/users/getUserInfoV2.js +0 -134
  90. package/src/core/sendReqMqtt.js +0 -96
  91. package/src/database/helpers.js +0 -53
  92. package/src/database/models/index.js +0 -88
  93. package/src/database/models/thread.js +0 -50
  94. package/src/database/models/user.js +0 -46
  95. package/src/database/threadData.js +0 -94
  96. package/src/database/userData.js +0 -98
  97. package/src/remote/remoteClient.js +0 -123
  98. package/src/utils/broadcast.js +0 -51
  99. package/src/utils/client.js +0 -10
  100. package/src/utils/constants.js +0 -23
  101. package/src/utils/cookies.js +0 -68
  102. package/src/utils/format/attachment.js +0 -357
  103. package/src/utils/format/cookie.js +0 -9
  104. package/src/utils/format/date.js +0 -50
  105. package/src/utils/format/decode.js +0 -44
  106. package/src/utils/format/delta.js +0 -194
  107. package/src/utils/format/ids.js +0 -64
  108. package/src/utils/format/index.js +0 -64
  109. package/src/utils/format/message.js +0 -88
  110. package/src/utils/format/presence.js +0 -132
  111. package/src/utils/format/readTyp.js +0 -44
  112. package/src/utils/format/thread.js +0 -42
  113. package/src/utils/format/utils.js +0 -141
  114. package/src/utils/headers.js +0 -115
  115. package/src/utils/loginParser/autoLogin.js +0 -125
  116. package/src/utils/loginParser/helpers.js +0 -43
  117. package/src/utils/loginParser/index.js +0 -10
  118. package/src/utils/loginParser/parseAndCheckLogin.js +0 -220
  119. package/src/utils/loginParser/textUtils.js +0 -28
  120. package/src/utils/request/client.js +0 -26
  121. package/src/utils/request/config.js +0 -23
  122. package/src/utils/request/defaults.js +0 -46
  123. package/src/utils/request/helpers.js +0 -46
  124. package/src/utils/request/index.js +0 -17
  125. package/src/utils/request/methods.js +0 -163
  126. package/src/utils/request/proxy.js +0 -21
  127. package/src/utils/request/retry.js +0 -77
  128. package/src/utils/request/sanitize.js +0 -49
@@ -1,25 +0,0 @@
1
- "use strict";
2
- /**
3
- * Maps /ls_resp task types to a normalized response shape for send_message_mqtt, set_message_reaction, edit_message.
4
- */
5
- module.exports = function getTaskResponseData(taskType, payload) {
6
- try {
7
- switch (taskType) {
8
- case "send_message_mqtt":
9
- return {
10
- type: taskType,
11
- threadID: payload.step[1][2][2][1][2],
12
- messageID: payload.step[1][2][2][1][3],
13
- payload: payload.step[1][2]
14
- };
15
- case "set_message_reaction":
16
- return { mid: payload.step[1][2][2][1][4] };
17
- case "edit_message":
18
- return { mid: payload.step[1][2][2][1][2] };
19
- default:
20
- return null;
21
- }
22
- } catch (e) {
23
- return null;
24
- }
25
- };
@@ -1,377 +0,0 @@
1
- "use strict";
2
- /**
3
- * Parses MQTT delta payloads into normalized events: NewMessage, ClientPayload (reactions, unsend, reply), read receipts, etc.
4
- */
5
- const { formatDeltaEvent, formatMessage, _formatAttachment, formatDeltaMessage, formatDeltaReadReceipt, formatID, getType, decodeClientPayload, getMentionsFromDeltaMessage } = require("../../../utils/format");
6
- const logger = require("../../../../func/logger");
7
-
8
- module.exports = function createParseDelta(deps) {
9
- const { parseAndCheckLogin } = deps;
10
- return function parseDelta(defaultFuncs, api, ctx, globalCallback, { delta }) {
11
- if (delta.class === "NewMessage") {
12
- const resolveAttachmentUrl = i => {
13
- if (!delta.attachments || i === delta.attachments.length || getType(delta.attachments) !== "Array") {
14
- let fmtMsg;
15
- try {
16
- fmtMsg = formatDeltaMessage(delta);
17
- } catch (err) {
18
- return;
19
- }
20
- if (fmtMsg) {
21
- if (!ctx.globalOptions.selfListen && fmtMsg.senderID === ctx.userID) return;
22
- if (typeof ctx._updateThreadFromMessage === "function") {
23
- try {
24
- ctx._updateThreadFromMessage(fmtMsg);
25
- } catch { }
26
- }
27
- globalCallback(null, fmtMsg);
28
- }
29
- } else {
30
- const attachment = delta.attachments[i];
31
- if (attachment && attachment.mercury && attachment.mercury.attach_type === "photo") {
32
- api.resolvePhotoUrl(attachment.fbid, (err, url) => {
33
- if (!err && attachment.mercury && attachment.mercury.metadata) {
34
- attachment.mercury.metadata.url = url;
35
- }
36
- resolveAttachmentUrl(i + 1);
37
- });
38
- } else {
39
- resolveAttachmentUrl(i + 1);
40
- }
41
- }
42
- };
43
- resolveAttachmentUrl(0);
44
- } else if (delta.class === "ClientPayload") {
45
- const clientPayload = decodeClientPayload(delta.payload);
46
- if (clientPayload && clientPayload.deltas) {
47
- for (const d of clientPayload.deltas) {
48
- if (d.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
49
- const messageReaction = {
50
- type: "message_reaction",
51
- threadID: (d.deltaMessageReaction.threadKey.threadFbId ? d.deltaMessageReaction.threadKey.threadFbId : d.deltaMessageReaction.threadKey.otherUserFbId).toString(),
52
- messageID: d.deltaMessageReaction.messageId,
53
- reaction: d.deltaMessageReaction.reaction,
54
- senderID: d.deltaMessageReaction.senderId.toString(),
55
- userID: d.deltaMessageReaction.userId.toString()
56
- };
57
- globalCallback(null, messageReaction);
58
- } else if (d.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
59
- const messageUnsend = {
60
- type: "message_unsend",
61
- threadID: (d.deltaRecallMessageData.threadKey.threadFbId ? d.deltaRecallMessageData.threadKey.threadFbId : d.deltaRecallMessageData.threadKey.otherUserFbId).toString(),
62
- messageID: d.deltaRecallMessageData.messageID,
63
- senderID: d.deltaRecallMessageData.senderID.toString(),
64
- deletionTimestamp: d.deltaRecallMessageData.deletionTimestamp,
65
- timestamp: d.deltaRecallMessageData.timestamp
66
- };
67
- globalCallback(null, messageUnsend);
68
- } else if (d.deltaMessageReply) {
69
- let callbackToReturn;
70
- try {
71
- const msg = d.deltaMessageReply.message;
72
- if (!msg || !msg.messageMetadata) {
73
- logger("parseDelta: deltaMessageReply.message or messageMetadata is missing", "warn");
74
- return;
75
- }
76
- const mentions = getMentionsFromDeltaMessage(msg);
77
- const msgMetadata = msg.messageMetadata;
78
- const threadKey = msgMetadata.threadKey || {};
79
- callbackToReturn = {
80
- type: "message_reply",
81
- threadID: (threadKey.threadFbId ? threadKey.threadFbId : threadKey.otherUserFbId || "").toString(),
82
- messageID: msgMetadata.messageId || "",
83
- senderID: (msgMetadata.actorFbId || "").toString(),
84
- attachments: (msg.attachments || []).map(att => {
85
- try {
86
- const mercury = JSON.parse(att.mercuryJSON);
87
- Object.assign(att, mercury);
88
- } catch (ex) {
89
- // Ignore parsing errors
90
- }
91
- return att;
92
- }).map(att => {
93
- let x;
94
- try {
95
- x = _formatAttachment(att);
96
- } catch (ex) {
97
- x = att;
98
- x.error = ex;
99
- x.type = "unknown";
100
- }
101
- return x;
102
- }),
103
- args: (msg.body || "").trim().split(/\s+/),
104
- body: msg.body || "",
105
- isGroup: !!threadKey.threadFbId,
106
- mentions,
107
- timestamp: parseInt(msgMetadata.timestamp || 0),
108
- participantIDs: (msg.participants || []).map(e => e.toString())
109
- };
110
- if (d.deltaMessageReply.repliedToMessage) {
111
- try {
112
- const repliedTo = d.deltaMessageReply.repliedToMessage;
113
- const rmentions = getMentionsFromDeltaMessage(repliedTo);
114
- const msgMetadata = repliedTo.messageMetadata;
115
- if (msgMetadata && msgMetadata.threadKey) {
116
- callbackToReturn.messageReply = {
117
- threadID: (msgMetadata.threadKey.threadFbId ? msgMetadata.threadKey.threadFbId : msgMetadata.threadKey.otherUserFbId || "").toString(),
118
- messageID: msgMetadata.messageId || "",
119
- senderID: (msgMetadata.actorFbId || "").toString(),
120
- attachments: (repliedTo.attachments || []).map(att => {
121
- let mercury;
122
- try {
123
- mercury = JSON.parse(att.mercuryJSON);
124
- Object.assign(att, mercury);
125
- } catch (ex) {
126
- mercury = {};
127
- }
128
- return att;
129
- }).map(att => {
130
- let x;
131
- try {
132
- x = _formatAttachment(att);
133
- } catch (ex) {
134
- x = att;
135
- x.error = ex;
136
- x.type = "unknown";
137
- }
138
- return x;
139
- }),
140
- args: (repliedTo.body || "").trim().split(/\s+/),
141
- body: repliedTo.body || "",
142
- isGroup: !!msgMetadata.threadKey.threadFbId,
143
- mentions: rmentions,
144
- timestamp: parseInt(msgMetadata.timestamp || 0),
145
- participantIDs: (repliedTo.participants || []).map(e => e.toString())
146
- };
147
- }
148
- } catch (err) {
149
- const errMsg = err && err.message ? err.message : String(err || "Unknown error");
150
- logger(`parseDelta message_reply repliedToMessage error: ${errMsg}`, "warn");
151
- }
152
- } else if (d.deltaMessageReply.replyToMessageId) {
153
- return defaultFuncs.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
154
- av: ctx.globalOptions.pageID,
155
- queries: JSON.stringify({
156
- o0: {
157
- doc_id: "2848441488556444",
158
- query_params: {
159
- thread_and_message_id: {
160
- thread_id: callbackToReturn.threadID,
161
- message_id: d.deltaMessageReply.replyToMessageId.id
162
- }
163
- }
164
- }
165
- })
166
- }).then(parseAndCheckLogin(ctx, defaultFuncs)).then(resData => {
167
- if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
168
- if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
169
- const fetchData = resData[0].o0.data.message;
170
- const mobj = {};
171
- for (const n in fetchData.message.ranges) {
172
- mobj[fetchData.message.ranges[n].entity.id] = (fetchData.message.text || "").substr(fetchData.message.ranges[n].offset, fetchData.message.ranges[n].length);
173
- }
174
- callbackToReturn.messageReply = {
175
- type: "Message",
176
- threadID: callbackToReturn.threadID,
177
- messageID: fetchData.message_id,
178
- senderID: fetchData.message_sender.id.toString(),
179
- attachments: fetchData.message.blob_attachment.map(att => _formatAttachment({ blob_attachment: att })),
180
- args: (fetchData.message.text || "").trim().split(/\s+/) || [],
181
- body: fetchData.message.text || "",
182
- isGroup: callbackToReturn.isGroup,
183
- mentions: mobj,
184
- timestamp: parseInt(fetchData.timestamp_precise)
185
- };
186
- }).catch(err => {
187
- const errMsg = err && err.message ? err.message : String(err || "Unknown error");
188
- logger(`parseDelta message_reply fetch error: ${errMsg}`, "warn");
189
- }).finally(() => {
190
- if (callbackToReturn) {
191
- if (!ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID) return;
192
- globalCallback(null, callbackToReturn);
193
- }
194
- });
195
- } else {
196
- if (callbackToReturn) callbackToReturn.delta = d;
197
- }
198
- } catch (err) {
199
- const errMsg = err && err.message ? err.message : String(err || "Unknown error");
200
- logger(`parseDelta message_reply error: ${errMsg}`, "warn");
201
- return;
202
- }
203
- if (callbackToReturn) {
204
- if (!ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID) return;
205
- globalCallback(null, callbackToReturn);
206
- }
207
- }
208
- }
209
- return;
210
- }
211
- }
212
- switch (delta.class) {
213
- case "ReadReceipt": {
214
- let fmtMsg;
215
- try {
216
- fmtMsg = formatDeltaReadReceipt(delta);
217
- } catch (err) {
218
- return;
219
- }
220
- globalCallback(null, fmtMsg);
221
- break;
222
- }
223
- case "AdminTextMessage": {
224
- switch (delta.type) {
225
- case "instant_game_dynamic_custom_update":
226
- case "accept_pending_thread":
227
- case "confirm_friend_request":
228
- case "shared_album_delete":
229
- case "shared_album_addition":
230
- case "pin_messages_v2":
231
- case "unpin_messages_v2":
232
- case "change_thread_theme":
233
- case "change_thread_nickname":
234
- case "change_thread_icon":
235
- case "change_thread_quick_reaction":
236
- case "change_thread_admins":
237
- case "group_poll":
238
- case "joinable_group_link_mode_change":
239
- case "magic_words":
240
- case "change_thread_approval_mode":
241
- case "messenger_call_log":
242
- case "participant_joined_group_call":
243
- case "rtc_call_log":
244
- case "update_vote": {
245
- let fmtMsg;
246
- try {
247
- fmtMsg = formatDeltaEvent(delta);
248
- } catch (err) {
249
- return;
250
- }
251
- globalCallback(null, fmtMsg);
252
- break;
253
- }
254
- }
255
- break;
256
- }
257
- case "ForcedFetch": {
258
- if (!delta.threadKey) return;
259
- const mid = delta.messageId;
260
- const tid = delta.threadKey.threadFbId;
261
- if (mid && tid) {
262
- const form = {
263
- av: ctx.globalOptions.pageID,
264
- queries: JSON.stringify({
265
- o0: {
266
- doc_id: "2848441488556444",
267
- query_params: {
268
- thread_and_message_id: {
269
- thread_id: tid.toString(),
270
- message_id: mid
271
- }
272
- }
273
- }
274
- })
275
- };
276
- defaultFuncs.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form).then(parseAndCheckLogin(ctx, defaultFuncs)).then(resData => {
277
- if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
278
- if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
279
- const fetchData = resData[0].o0.data.message;
280
- if (getType(fetchData) === "Object") {
281
- switch (fetchData.__typename) {
282
- case "ThreadImageMessage":
283
- if ((!ctx.globalOptions.selfListen && fetchData.message_sender.id.toString() === ctx.userID) || !ctx.loggedIn) {} else {
284
- globalCallback(null, {
285
- type: "event",
286
- threadID: formatID(tid.toString()),
287
- logMessageType: "log:thread-image",
288
- logMessageData: {
289
- image: {
290
- attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
291
- width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
292
- height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
293
- url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
294
- }
295
- },
296
- logMessageBody: fetchData.snippet,
297
- timestamp: fetchData.timestamp_precise,
298
- author: fetchData.message_sender.id
299
- });
300
- }
301
- break;
302
- case "UserMessage": {
303
- const event = {
304
- type: "message",
305
- senderID: formatID(fetchData.message_sender.id),
306
- body: fetchData.message.text || "",
307
- threadID: formatID(tid.toString()),
308
- messageID: fetchData.message_id,
309
- attachments: [
310
- {
311
- type: "share",
312
- ID: fetchData.extensible_attachment.legacy_attachment_id,
313
- url: fetchData.extensible_attachment.story_attachment.url,
314
- title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
315
- description: fetchData.extensible_attachment.story_attachment.description.text,
316
- source: fetchData.extensible_attachment.story_attachment.source,
317
- image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
318
- width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
319
- height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
320
- playable: ((fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false),
321
- duration: ((fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0),
322
- subattachments: fetchData.extensible_attachment.subattachments,
323
- properties: fetchData.extensible_attachment.story_attachment.properties
324
- }
325
- ],
326
- mentions: {},
327
- timestamp: parseInt(fetchData.timestamp_precise),
328
- isGroup: fetchData.message_sender.id !== tid.toString()
329
- };
330
- globalCallback(null, event);
331
- break;
332
- }
333
- default:
334
- break;
335
- }
336
- } else {
337
- return;
338
- }
339
- }).catch(err => {
340
- const errMsg = err && err.message ? err.message : String(err || "Unknown error");
341
- logger(`parseDelta ForcedFetch error: ${errMsg}`, "warn");
342
- });
343
- }
344
- break;
345
- }
346
- case "ThreadName":
347
- case "ParticipantsAddedToGroupThread":
348
- case "ParticipantLeftGroupThread": {
349
- let formattedEvent;
350
- try {
351
- formattedEvent = formatDeltaEvent(delta);
352
- } catch (err) {
353
- return;
354
- }
355
- if (!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID) return;
356
- if (!ctx.loggedIn) return;
357
- globalCallback(null, formattedEvent);
358
- break;
359
- }
360
- case "NewMessage": {
361
- const hasLiveLocation = d => {
362
- const attachment = d.attachments && d.attachments[0] && d.attachments[0].mercury && d.attachments[0].mercury.extensible_attachment;
363
- const storyAttachment = attachment && attachment.story_attachment;
364
- return storyAttachment && storyAttachment.style_list && storyAttachment.style_list.includes("message_live_location");
365
- };
366
- if (delta.attachments && delta.attachments.length === 1 && hasLiveLocation(delta)) {
367
- delta.class = "UserLocation";
368
- try {
369
- const fmtMsg = formatDeltaEvent(delta);
370
- globalCallback(null, fmtMsg);
371
- } catch (err) {}
372
- }
373
- break;
374
- }
375
- }
376
- };
377
- };
@@ -1,215 +0,0 @@
1
- "use strict";
2
- /**
3
- * Builds a duplex stream over WebSocket for MQTT: proxy for writes, PassThrough for reads.
4
- * Handles ping/pong, liveness timeout, and clean shutdown.
5
- */
6
- const { Writable, PassThrough } = require("stream");
7
- const Duplexify = require("duplexify");
8
-
9
- const PING_INTERVAL_MS = 30000;
10
- const LIVENESS_CHECK_MS = 10000;
11
- const LIVENESS_MAX_IDLE_MS = 65000;
12
-
13
- function buildProxy() {
14
- let target = null;
15
- let ended = false;
16
- const Proxy = new Writable({
17
- autoDestroy: true,
18
- write(chunk, enc, cb) {
19
- if (ended || this.destroyed) return cb();
20
- const ws = target;
21
- if (ws && ws.readyState === 1) {
22
- try {
23
- ws.send(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk), cb);
24
- } catch (e) {
25
- cb(e);
26
- }
27
- } else cb();
28
- },
29
- writev(chunks, cb) {
30
- if (ended || this.destroyed) return cb();
31
- const ws = target;
32
- if (!ws || ws.readyState !== 1) return cb();
33
- try {
34
- for (const { chunk } of chunks) {
35
- ws.send(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
36
- }
37
- cb();
38
- } catch (e) {
39
- cb(e);
40
- }
41
- },
42
- final(cb) {
43
- ended = true;
44
- const ws = target;
45
- target = null;
46
- if (ws && (ws.readyState === 0 || ws.readyState === 1)) {
47
- try {
48
- typeof ws.terminate === "function" ? ws.terminate() : ws.close();
49
- } catch { }
50
- }
51
- cb();
52
- }
53
- });
54
- Proxy.setTarget = ws => {
55
- if (ended) return;
56
- target = ws;
57
- };
58
- Proxy.hardEnd = () => {
59
- ended = true;
60
- target = null;
61
- };
62
- return Proxy;
63
- }
64
-
65
- function buildStream(options, WebSocket, Proxy) {
66
- const readable = new PassThrough();
67
- const Stream = Duplexify(undefined, undefined, Object.assign({ end: false, autoDestroy: true }, options));
68
- const NoopWritable = new Writable({ write(_c, _e, cb) { cb(); } });
69
- let ws = WebSocket;
70
- let pingTimer = null;
71
- let livenessTimer = null;
72
- let lastActivity = Date.now();
73
- let attached = false;
74
- let style = "prop";
75
- let closed = false;
76
-
77
- const toBuffer = d => {
78
- if (Buffer.isBuffer(d)) return d;
79
- if (d instanceof ArrayBuffer) return Buffer.from(d);
80
- if (ArrayBuffer.isView(d)) return Buffer.from(d.buffer, d.byteOffset, d.byteLength);
81
- return Buffer.from(String(d));
82
- };
83
-
84
- const swapToNoopWritable = () => {
85
- try { Stream.setWritable(NoopWritable); } catch { }
86
- };
87
-
88
- const onOpen = () => {
89
- if (closed) return;
90
- Proxy.setTarget(ws);
91
- Stream.setWritable(Proxy);
92
- Stream.setReadable(readable);
93
- Stream.emit("connect");
94
- lastActivity = Date.now();
95
- clearInterval(pingTimer);
96
- clearInterval(livenessTimer);
97
- pingTimer = setInterval(() => {
98
- if (!ws || ws.readyState !== 1) return;
99
- if (typeof ws.ping === "function") {
100
- try { ws.ping(); } catch { }
101
- } else {
102
- try { ws.send("ping"); } catch { }
103
- }
104
- }, PING_INTERVAL_MS);
105
- livenessTimer = setInterval(() => {
106
- if (!ws || ws.readyState !== 1) return;
107
- if (Date.now() - lastActivity > LIVENESS_MAX_IDLE_MS) {
108
- try { typeof ws.terminate === "function" ? ws.terminate() : ws.close(); } catch { }
109
- }
110
- }, LIVENESS_CHECK_MS);
111
- };
112
-
113
- const onMessage = data => {
114
- lastActivity = Date.now();
115
- readable.write(toBuffer(style === "dom" && data && data.data !== undefined ? data.data : data));
116
- };
117
-
118
- const onPong = () => {
119
- lastActivity = Date.now();
120
- };
121
-
122
- const cleanup = () => {
123
- if (closed) return;
124
- closed = true;
125
- clearInterval(pingTimer);
126
- clearInterval(livenessTimer);
127
- pingTimer = null;
128
- livenessTimer = null;
129
- Proxy.hardEnd();
130
- swapToNoopWritable();
131
- if (ws) {
132
- detach(ws);
133
- try {
134
- if (ws.readyState === 1) {
135
- typeof ws.terminate === "function" ? ws.terminate() : ws.close();
136
- }
137
- } catch { }
138
- ws = null;
139
- }
140
- readable.end();
141
- };
142
-
143
- const onError = err => {
144
- cleanup();
145
- Stream.destroy(err);
146
- };
147
-
148
- const onClose = () => {
149
- cleanup();
150
- Stream.end();
151
- if (!Stream.destroyed) Stream.destroy();
152
- };
153
-
154
- const attach = w => {
155
- if (attached || !w) return;
156
- attached = true;
157
- if (typeof w.on === "function" && typeof w.off === "function") {
158
- style = "node";
159
- w.on("open", onOpen);
160
- w.on("message", onMessage);
161
- w.on("error", onError);
162
- w.on("close", onClose);
163
- if (typeof w.on === "function") w.on("pong", onPong);
164
- } else if (typeof w.addEventListener === "function" && typeof w.removeEventListener === "function") {
165
- style = "dom";
166
- w.addEventListener("open", onOpen);
167
- w.addEventListener("message", onMessage);
168
- w.addEventListener("error", onError);
169
- w.addEventListener("close", onClose);
170
- } else {
171
- style = "prop";
172
- w.onopen = onOpen;
173
- w.onmessage = onMessage;
174
- w.onerror = onError;
175
- w.onclose = onClose;
176
- }
177
- };
178
-
179
- const detach = w => {
180
- if (!attached || !w) return;
181
- attached = false;
182
- if (style === "node" && typeof w.off === "function") {
183
- w.off("open", onOpen);
184
- w.off("message", onMessage);
185
- w.off("error", onError);
186
- w.off("close", onClose);
187
- if (typeof w.off === "function") w.off("pong", onPong);
188
- } else if (style === "dom" && typeof w.removeEventListener === "function") {
189
- w.removeEventListener("open", onOpen);
190
- w.removeEventListener("message", onMessage);
191
- w.removeEventListener("error", onError);
192
- w.removeEventListener("close", onClose);
193
- } else {
194
- w.onopen = null;
195
- w.onmessage = null;
196
- w.onerror = null;
197
- w.onclose = null;
198
- }
199
- };
200
-
201
- attach(ws);
202
- if (ws && ws.readyState === 1) onOpen();
203
-
204
- Stream.on("prefinish", swapToNoopWritable);
205
- Stream.on("finish", cleanup);
206
- Stream.on("close", cleanup);
207
- Proxy.on("close", swapToNoopWritable);
208
-
209
- return Stream;
210
- }
211
-
212
- module.exports = {
213
- buildProxy,
214
- buildStream
215
- };
@@ -1,28 +0,0 @@
1
- "use strict";
2
- /**
3
- * MQTT topic list for Facebook Messenger real-time connection.
4
- * Subscriptions are created in connectMqtt on "connect".
5
- */
6
- module.exports = {
7
- topics: [
8
- "/ls_req",
9
- "/ls_resp",
10
- "/legacy_web",
11
- "/webrtc",
12
- "/rtc_multi",
13
- "/onevc",
14
- "/br_sr",
15
- "/sr_res",
16
- "/t_ms",
17
- "/thread_typing",
18
- "/orca_typing_notifications",
19
- "/notify_disconnect",
20
- "/orca_presence",
21
- "/inbox",
22
- "/mercury",
23
- "/messaging_events",
24
- "/orca_message_notifications",
25
- "/pp",
26
- "/webrtc_response"
27
- ]
28
- };