fca-riyad 37.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 (242) hide show
  1. package/CHANGELOG.md +325 -0
  2. package/DOCS.md +2712 -0
  3. package/README.md +410 -0
  4. package/func/checkUpdate.js +7 -0
  5. package/func/logAdapter.js +33 -0
  6. package/func/logger.js +48 -0
  7. package/index.d.ts +751 -0
  8. package/index.js +22 -0
  9. package/module/config.js +40 -0
  10. package/module/login.js +133 -0
  11. package/module/loginHelper.js +1359 -0
  12. package/module/options.js +44 -0
  13. package/package.json +95 -0
  14. package/src/api/action/addExternalModule.js +25 -0
  15. package/src/api/action/changeAvatar.js +137 -0
  16. package/src/api/action/changeBio.js +75 -0
  17. package/src/api/action/enableAutoSaveAppState.js +73 -0
  18. package/src/api/action/getCurrentUserID.js +7 -0
  19. package/src/api/action/handleFriendRequest.js +57 -0
  20. package/src/api/action/logout.js +76 -0
  21. package/src/api/action/refreshFb_dtsg.js +48 -0
  22. package/src/api/action/setPostReaction.js +106 -0
  23. package/src/api/action/unfriend.js +54 -0
  24. package/src/api/http/httpGet.js +46 -0
  25. package/src/api/http/httpPost.js +52 -0
  26. package/src/api/http/postFormData.js +47 -0
  27. package/src/api/messaging/addUserToGroup.js +68 -0
  28. package/src/api/messaging/changeAdminStatus.js +126 -0
  29. package/src/api/messaging/changeArchivedStatus.js +55 -0
  30. package/src/api/messaging/changeBlockedStatus.js +48 -0
  31. package/src/api/messaging/changeGroupImage.js +91 -0
  32. package/src/api/messaging/changeNickname.js +70 -0
  33. package/src/api/messaging/changeThreadColor.js +79 -0
  34. package/src/api/messaging/changeThreadEmoji.js +111 -0
  35. package/src/api/messaging/createNewGroup.js +88 -0
  36. package/src/api/messaging/createPoll.js +46 -0
  37. package/src/api/messaging/createThemeAI.js +98 -0
  38. package/src/api/messaging/deleteMessage.js +136 -0
  39. package/src/api/messaging/deleteThread.js +56 -0
  40. package/src/api/messaging/editMessage.js +90 -0
  41. package/src/api/messaging/forwardAttachment.js +57 -0
  42. package/src/api/messaging/forwardMessage.js +134 -0
  43. package/src/api/messaging/getEmojiUrl.js +29 -0
  44. package/src/api/messaging/getFriendsList.js +82 -0
  45. package/src/api/messaging/getMessage.js +829 -0
  46. package/src/api/messaging/getThemePictures.js +62 -0
  47. package/src/api/messaging/handleMessageRequest.js +65 -0
  48. package/src/api/messaging/markAsDelivered.js +57 -0
  49. package/src/api/messaging/markAsRead.js +88 -0
  50. package/src/api/messaging/markAsReadAll.js +49 -0
  51. package/src/api/messaging/markAsSeen.js +61 -0
  52. package/src/api/messaging/muteThread.js +50 -0
  53. package/src/api/messaging/pinMessage.js +115 -0
  54. package/src/api/messaging/removeUserFromGroup.js +62 -0
  55. package/src/api/messaging/resolvePhotoUrl.js +43 -0
  56. package/src/api/messaging/scheduler.js +264 -0
  57. package/src/api/messaging/searchForThread.js +53 -0
  58. package/src/api/messaging/sendBroadcast.js +93 -0
  59. package/src/api/messaging/sendMessage.js +269 -0
  60. package/src/api/messaging/sendTypingIndicator.js +74 -0
  61. package/src/api/messaging/sessionGuard.js +130 -0
  62. package/src/api/messaging/setMessageReaction.js +95 -0
  63. package/src/api/messaging/setTitle.js +124 -0
  64. package/src/api/messaging/shareContact.js +49 -0
  65. package/src/api/messaging/threadColors.js +128 -0
  66. package/src/api/messaging/unsendMessage.js +81 -0
  67. package/src/api/messaging/uploadAttachment.js +492 -0
  68. package/src/api/socket/OldMessage.js +186 -0
  69. package/src/api/socket/core/connectMqtt.js +269 -0
  70. package/src/api/socket/core/emitAuth.js +103 -0
  71. package/src/api/socket/core/getSeqID.js +321 -0
  72. package/src/api/socket/core/getTaskResponseData.js +25 -0
  73. package/src/api/socket/core/parseDelta.js +387 -0
  74. package/src/api/socket/detail/buildStream.js +215 -0
  75. package/src/api/socket/detail/constants.js +28 -0
  76. package/src/api/socket/e2ee/crypto.js +173 -0
  77. package/src/api/socket/e2ee/e2ee/crypto.js +173 -0
  78. package/src/api/socket/e2ee/e2ee/index.js +421 -0
  79. package/src/api/socket/e2ee/e2ee/proto/ArmadilloApplication.proto +281 -0
  80. package/src/api/socket/e2ee/e2ee/proto/ArmadilloICDC.proto +14 -0
  81. package/src/api/socket/e2ee/e2ee/proto/ConsumerApplication.proto +232 -0
  82. package/src/api/socket/e2ee/e2ee/proto/MessageApplication.proto +82 -0
  83. package/src/api/socket/e2ee/e2ee/proto/MessageTransport.proto +77 -0
  84. package/src/api/socket/e2ee/e2ee/proto/WACommon.proto +66 -0
  85. package/src/api/socket/e2ee/e2ee/proto/WAMediaTransport.proto +176 -0
  86. package/src/api/socket/e2ee/e2ee/proto/proto-writer.ts +76 -0
  87. package/src/api/socket/e2ee/e2ee/protocol.js +196 -0
  88. package/src/api/socket/e2ee/e2ee/ratchet.js +219 -0
  89. package/src/api/socket/e2ee/e2ee/store.js +182 -0
  90. package/src/api/socket/e2ee/e2ee/vendor/fb-e2ee.cjs +9162 -0
  91. package/src/api/socket/e2ee/e2ee/vendor/proto/ArmadilloApplication.proto +281 -0
  92. package/src/api/socket/e2ee/e2ee/vendor/proto/ArmadilloICDC.proto +14 -0
  93. package/src/api/socket/e2ee/e2ee/vendor/proto/ConsumerApplication.proto +232 -0
  94. package/src/api/socket/e2ee/e2ee/vendor/proto/MessageApplication.proto +82 -0
  95. package/src/api/socket/e2ee/e2ee/vendor/proto/MessageTransport.proto +77 -0
  96. package/src/api/socket/e2ee/e2ee/vendor/proto/WACommon.proto +66 -0
  97. package/src/api/socket/e2ee/e2ee/vendor/proto/WAMediaTransport.proto +176 -0
  98. package/src/api/socket/e2ee/e2ee/vendor/proto/proto-writer.ts +76 -0
  99. package/src/api/socket/e2ee/index.js +437 -0
  100. package/src/api/socket/e2ee/proto/ArmadilloApplication.proto +281 -0
  101. package/src/api/socket/e2ee/proto/ArmadilloICDC.proto +14 -0
  102. package/src/api/socket/e2ee/proto/ConsumerApplication.proto +232 -0
  103. package/src/api/socket/e2ee/proto/MessageApplication.proto +82 -0
  104. package/src/api/socket/e2ee/proto/MessageTransport.proto +77 -0
  105. package/src/api/socket/e2ee/proto/WACommon.proto +66 -0
  106. package/src/api/socket/e2ee/proto/WAMediaTransport.proto +176 -0
  107. package/src/api/socket/e2ee/proto/proto-writer.ts +76 -0
  108. package/src/api/socket/e2ee/protocol.js +196 -0
  109. package/src/api/socket/e2ee/ratchet.js +219 -0
  110. package/src/api/socket/e2ee/store.js +182 -0
  111. package/src/api/socket/e2ee/vendor/fb-e2ee.cjs +9162 -0
  112. package/src/api/socket/e2ee/vendor/proto/ArmadilloApplication.proto +281 -0
  113. package/src/api/socket/e2ee/vendor/proto/ArmadilloICDC.proto +14 -0
  114. package/src/api/socket/e2ee/vendor/proto/ConsumerApplication.proto +232 -0
  115. package/src/api/socket/e2ee/vendor/proto/MessageApplication.proto +82 -0
  116. package/src/api/socket/e2ee/vendor/proto/MessageTransport.proto +77 -0
  117. package/src/api/socket/e2ee/vendor/proto/WACommon.proto +66 -0
  118. package/src/api/socket/e2ee/vendor/proto/WAMediaTransport.proto +176 -0
  119. package/src/api/socket/e2ee/vendor/proto/proto-writer.ts +76 -0
  120. package/src/api/socket/listenE2EE.js +75 -0
  121. package/src/api/socket/listenMqtt.js +388 -0
  122. package/src/api/socket/middleware/index.js +216 -0
  123. package/src/api/socket/sendMessage.js +309 -0
  124. package/src/api/socket/sendMessageMqtt.js +69 -0
  125. package/src/api/threads/getThreadHistory.js +664 -0
  126. package/src/api/threads/getThreadInfo.js +296 -0
  127. package/src/api/threads/getThreadList.js +293 -0
  128. package/src/api/threads/getThreadPictures.js +78 -0
  129. package/src/api/users/getUserID.js +65 -0
  130. package/src/api/users/getUserInfo.js +402 -0
  131. package/src/api/users/getUserInfoV2.js +134 -0
  132. package/src/app/MessengerBot.js +209 -0
  133. package/src/app/MessengerContext.js +32 -0
  134. package/src/app/createFcaClient.js +136 -0
  135. package/src/app/threadInfoRealtimeSync.js +284 -0
  136. package/src/core/sendReqMqtt.js +96 -0
  137. package/src/database/helpers.js +53 -0
  138. package/src/database/models/index.js +88 -0
  139. package/src/database/models/thread.js +50 -0
  140. package/src/database/models/user.js +46 -0
  141. package/src/database/threadData.js +94 -0
  142. package/src/database/userData.js +98 -0
  143. package/src/remote/remoteClient.js +123 -0
  144. package/src/utils/broadcast.js +51 -0
  145. package/src/utils/client.js +10 -0
  146. package/src/utils/constants.js +23 -0
  147. package/src/utils/cookies.js +68 -0
  148. package/src/utils/format/attachment.js +357 -0
  149. package/src/utils/format/cookie.js +9 -0
  150. package/src/utils/format/date.js +50 -0
  151. package/src/utils/format/decode.js +44 -0
  152. package/src/utils/format/delta.js +194 -0
  153. package/src/utils/format/ids.js +64 -0
  154. package/src/utils/format/index.js +64 -0
  155. package/src/utils/format/message.js +88 -0
  156. package/src/utils/format/presence.js +132 -0
  157. package/src/utils/format/readTyp.js +44 -0
  158. package/src/utils/format/thread.js +42 -0
  159. package/src/utils/format/utils.js +141 -0
  160. package/src/utils/headers.js +115 -0
  161. package/src/utils/loginParser/autoLogin.js +125 -0
  162. package/src/utils/loginParser/helpers.js +43 -0
  163. package/src/utils/loginParser/index.js +10 -0
  164. package/src/utils/loginParser/parseAndCheckLogin.js +220 -0
  165. package/src/utils/loginParser/textUtils.js +28 -0
  166. package/src/utils/nexca-logger.js +144 -0
  167. package/src/utils/nexca-utils.js +686 -0
  168. package/src/utils/request/client.js +26 -0
  169. package/src/utils/request/config.js +23 -0
  170. package/src/utils/request/defaults.js +46 -0
  171. package/src/utils/request/helpers.js +46 -0
  172. package/src/utils/request/index.js +17 -0
  173. package/src/utils/request/methods.js +163 -0
  174. package/src/utils/request/proxy.js +21 -0
  175. package/src/utils/request/retry.js +77 -0
  176. package/src/utils/request/sanitize.js +49 -0
  177. package/src/utils/versionCheck.js +47 -0
  178. package/src/vendor/fca-unofficial/.github/workflows/nodejs.yml +26 -0
  179. package/src/vendor/fca-unofficial/.github/workflows/npmpublish.yml +30 -0
  180. package/src/vendor/fca-unofficial/.travis.yml +6 -0
  181. package/src/vendor/fca-unofficial/DOCS.md +1731 -0
  182. package/src/vendor/fca-unofficial/LICENSE-MIT +21 -0
  183. package/src/vendor/fca-unofficial/README.md +225 -0
  184. package/src/vendor/fca-unofficial/index.js +619 -0
  185. package/src/vendor/fca-unofficial/package.json +76 -0
  186. package/src/vendor/fca-unofficial/src/addExternalModule.js +19 -0
  187. package/src/vendor/fca-unofficial/src/addUserToGroup.js +113 -0
  188. package/src/vendor/fca-unofficial/src/changeAdminStatus.js +79 -0
  189. package/src/vendor/fca-unofficial/src/changeArchivedStatus.js +55 -0
  190. package/src/vendor/fca-unofficial/src/changeBio.js +77 -0
  191. package/src/vendor/fca-unofficial/src/changeBlockedStatus.js +47 -0
  192. package/src/vendor/fca-unofficial/src/changeGroupImage.js +129 -0
  193. package/src/vendor/fca-unofficial/src/changeNickname.js +59 -0
  194. package/src/vendor/fca-unofficial/src/changeThreadColor.js +71 -0
  195. package/src/vendor/fca-unofficial/src/changeThreadEmoji.js +55 -0
  196. package/src/vendor/fca-unofficial/src/createNewGroup.js +86 -0
  197. package/src/vendor/fca-unofficial/src/createPoll.js +71 -0
  198. package/src/vendor/fca-unofficial/src/deleteMessage.js +56 -0
  199. package/src/vendor/fca-unofficial/src/deleteThread.js +56 -0
  200. package/src/vendor/fca-unofficial/src/forwardAttachment.js +60 -0
  201. package/src/vendor/fca-unofficial/src/getCurrentUserID.js +7 -0
  202. package/src/vendor/fca-unofficial/src/getEmojiUrl.js +29 -0
  203. package/src/vendor/fca-unofficial/src/getFriendsList.js +84 -0
  204. package/src/vendor/fca-unofficial/src/getThreadHistory.js +645 -0
  205. package/src/vendor/fca-unofficial/src/getThreadHistoryDeprecated.js +93 -0
  206. package/src/vendor/fca-unofficial/src/getThreadInfo.js +201 -0
  207. package/src/vendor/fca-unofficial/src/getThreadInfoDeprecated.js +80 -0
  208. package/src/vendor/fca-unofficial/src/getThreadList.js +238 -0
  209. package/src/vendor/fca-unofficial/src/getThreadListDeprecated.js +75 -0
  210. package/src/vendor/fca-unofficial/src/getThreadPictures.js +79 -0
  211. package/src/vendor/fca-unofficial/src/getUserID.js +66 -0
  212. package/src/vendor/fca-unofficial/src/getUserInfo.js +72 -0
  213. package/src/vendor/fca-unofficial/src/handleFriendRequest.js +61 -0
  214. package/src/vendor/fca-unofficial/src/handleMessageRequest.js +65 -0
  215. package/src/vendor/fca-unofficial/src/httpGet.js +52 -0
  216. package/src/vendor/fca-unofficial/src/httpPost.js +52 -0
  217. package/src/vendor/fca-unofficial/src/listenMqtt.js +788 -0
  218. package/src/vendor/fca-unofficial/src/logout.js +75 -0
  219. package/src/vendor/fca-unofficial/src/markAsDelivered.js +58 -0
  220. package/src/vendor/fca-unofficial/src/markAsRead.js +80 -0
  221. package/src/vendor/fca-unofficial/src/markAsReadAll.js +50 -0
  222. package/src/vendor/fca-unofficial/src/markAsSeen.js +59 -0
  223. package/src/vendor/fca-unofficial/src/muteThread.js +52 -0
  224. package/src/vendor/fca-unofficial/src/removeUserFromGroup.js +79 -0
  225. package/src/vendor/fca-unofficial/src/resolvePhotoUrl.js +45 -0
  226. package/src/vendor/fca-unofficial/src/searchForThread.js +53 -0
  227. package/src/vendor/fca-unofficial/src/sendMessage.js +459 -0
  228. package/src/vendor/fca-unofficial/src/sendTypingIndicator.js +103 -0
  229. package/src/vendor/fca-unofficial/src/setMessageReaction.js +117 -0
  230. package/src/vendor/fca-unofficial/src/setPostReaction.js +76 -0
  231. package/src/vendor/fca-unofficial/src/setTitle.js +86 -0
  232. package/src/vendor/fca-unofficial/src/threadColors.js +57 -0
  233. package/src/vendor/fca-unofficial/src/unfriend.js +52 -0
  234. package/src/vendor/fca-unofficial/src/unsendMessage.js +49 -0
  235. package/src/vendor/fca-unofficial/test/data/shareAttach.js +146 -0
  236. package/src/vendor/fca-unofficial/test/data/something.mov +0 -0
  237. package/src/vendor/fca-unofficial/test/data/test.png +0 -0
  238. package/src/vendor/fca-unofficial/test/data/test.txt +7 -0
  239. package/src/vendor/fca-unofficial/test/example-config.json +18 -0
  240. package/src/vendor/fca-unofficial/test/test-page.js +140 -0
  241. package/src/vendor/fca-unofficial/test/test.js +385 -0
  242. package/src/vendor/fca-unofficial/utils.js +1358 -0
@@ -0,0 +1,25 @@
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
+ };
@@ -0,0 +1,387 @@
1
+ "use strict";
2
+ const { formatDeltaEvent, formatMessage, _formatAttachment, formatDeltaMessage, formatDeltaReadReceipt, formatID, getType, decodeClientPayload, getMentionsFromDeltaMessage } = require("../../../utils/format");
3
+ const logger = require("../../../../func/logger");
4
+ module.exports = function createParseDelta(deps) {
5
+ const { parseAndCheckLogin } = deps;
6
+ return function parseDelta(defaultFuncs, api, ctx, globalCallback, { delta }) {
7
+ if (delta.class === "NewMessage") {
8
+ const resolveAttachmentUrl = i => {
9
+ if (!delta.attachments || i === delta.attachments.length || getType(delta.attachments) !== "Array") {
10
+ let fmtMsg;
11
+ try {
12
+ fmtMsg = formatDeltaMessage(delta);
13
+ } catch (err) {
14
+ return;
15
+ }
16
+ if (fmtMsg) {
17
+ if (!ctx.globalOptions.selfListen && fmtMsg.senderID === ctx.userID) return;
18
+ globalCallback(null, fmtMsg);
19
+ }
20
+ } else {
21
+ const attachment = delta.attachments[i];
22
+ if (attachment && attachment.mercury && attachment.mercury.attach_type === "photo") {
23
+ api.resolvePhotoUrl(attachment.fbid, (err, url) => {
24
+ if (!err && attachment.mercury && attachment.mercury.metadata) {
25
+ attachment.mercury.metadata.url = url;
26
+ }
27
+ resolveAttachmentUrl(i + 1);
28
+ });
29
+ } else {
30
+ resolveAttachmentUrl(i + 1);
31
+ }
32
+ }
33
+ };
34
+ resolveAttachmentUrl(0);
35
+ } else if (delta.class === "ClientPayload") {
36
+ const clientPayload = decodeClientPayload(delta.payload);
37
+ if (clientPayload && clientPayload.deltas) {
38
+ for (const d of clientPayload.deltas) {
39
+ if (d.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
40
+ const messageReaction = {
41
+ type: "message_reaction",
42
+ threadID: (d.deltaMessageReaction.threadKey.threadFbId ? d.deltaMessageReaction.threadKey.threadFbId : d.deltaMessageReaction.threadKey.otherUserFbId).toString(),
43
+ messageID: d.deltaMessageReaction.messageId,
44
+ reaction: d.deltaMessageReaction.reaction,
45
+ senderID: d.deltaMessageReaction.senderId.toString(),
46
+ userID: d.deltaMessageReaction.userId.toString()
47
+ };
48
+ globalCallback(null, messageReaction);
49
+ } else if (d.deltaMessageEdit && !!ctx.globalOptions.listenEvents) {
50
+ try {
51
+ const edit = d.deltaMessageEdit;
52
+ const threadKey = edit.threadKey || {};
53
+ const messageEdit = {
54
+ type: "message_edit",
55
+ threadID: (threadKey.threadFbId ? threadKey.threadFbId : threadKey.otherUserFbId || "").toString(),
56
+ messageID: edit.messageId || "",
57
+ senderID: (edit.senderId || "").toString(),
58
+ body: edit.body || "",
59
+ timestamp: edit.timestamp ? parseInt(edit.timestamp) : Date.now()
60
+ };
61
+ globalCallback(null, messageEdit);
62
+ } catch (err) {
63
+ logger("parseDelta: deltaMessageEdit error: " + (err && err.message ? err.message : String(err)), "warn");
64
+ }
65
+ } else if (d.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
66
+ const messageUnsend = {
67
+ type: "message_unsend",
68
+ threadID: (d.deltaRecallMessageData.threadKey.threadFbId ? d.deltaRecallMessageData.threadKey.threadFbId : d.deltaRecallMessageData.threadKey.otherUserFbId).toString(),
69
+ messageID: d.deltaRecallMessageData.messageID,
70
+ senderID: d.deltaRecallMessageData.senderID.toString(),
71
+ deletionTimestamp: d.deltaRecallMessageData.deletionTimestamp,
72
+ timestamp: d.deltaRecallMessageData.timestamp
73
+ };
74
+ globalCallback(null, messageUnsend);
75
+ } else if (d.deltaMessageReply) {
76
+ let callbackToReturn;
77
+ try {
78
+ const msg = d.deltaMessageReply.message;
79
+ if (!msg || !msg.messageMetadata) {
80
+ logger("parseDelta: deltaMessageReply.message or messageMetadata is missing", "warn");
81
+ return;
82
+ }
83
+ const mentions = getMentionsFromDeltaMessage(msg);
84
+ const msgMetadata = msg.messageMetadata;
85
+ const threadKey = msgMetadata.threadKey || {};
86
+ callbackToReturn = {
87
+ type: "message_reply",
88
+ threadID: (threadKey.threadFbId ? threadKey.threadFbId : threadKey.otherUserFbId || "").toString(),
89
+ messageID: msgMetadata.messageId || "",
90
+ senderID: (msgMetadata.actorFbId || "").toString(),
91
+ attachments: (msg.attachments || []).map(att => {
92
+ try {
93
+ const mercury = JSON.parse(att.mercuryJSON);
94
+ Object.assign(att, mercury);
95
+ } catch (ex) {
96
+ // Ignore parsing errors
97
+ }
98
+ return att;
99
+ }).map(att => {
100
+ let x;
101
+ try {
102
+ x = _formatAttachment(att);
103
+ } catch (ex) {
104
+ x = att;
105
+ x.error = ex;
106
+ x.type = "unknown";
107
+ }
108
+ return x;
109
+ }),
110
+ args: (msg.body || "").trim().split(/\s+/),
111
+ body: msg.body || "",
112
+ isGroup: !!threadKey.threadFbId,
113
+ mentions,
114
+ timestamp: parseInt(msgMetadata.timestamp || 0),
115
+ participantIDs: (msg.participants || []).map(e => e.toString())
116
+ };
117
+ if (d.deltaMessageReply.repliedToMessage) {
118
+ try {
119
+ const repliedTo = d.deltaMessageReply.repliedToMessage;
120
+ const rmentions = getMentionsFromDeltaMessage(repliedTo);
121
+ const msgMetadata = repliedTo.messageMetadata;
122
+ if (msgMetadata && msgMetadata.threadKey) {
123
+ callbackToReturn.messageReply = {
124
+ threadID: (msgMetadata.threadKey.threadFbId ? msgMetadata.threadKey.threadFbId : msgMetadata.threadKey.otherUserFbId || "").toString(),
125
+ messageID: msgMetadata.messageId || "",
126
+ senderID: (msgMetadata.actorFbId || "").toString(),
127
+ attachments: (repliedTo.attachments || []).map(att => {
128
+ let mercury;
129
+ try {
130
+ mercury = JSON.parse(att.mercuryJSON);
131
+ Object.assign(att, mercury);
132
+ } catch (ex) {
133
+ mercury = {};
134
+ }
135
+ return att;
136
+ }).map(att => {
137
+ let x;
138
+ try {
139
+ x = _formatAttachment(att);
140
+ } catch (ex) {
141
+ x = att;
142
+ x.error = ex;
143
+ x.type = "unknown";
144
+ }
145
+ return x;
146
+ }),
147
+ args: (repliedTo.body || "").trim().split(/\s+/),
148
+ body: repliedTo.body || "",
149
+ isGroup: !!msgMetadata.threadKey.threadFbId,
150
+ mentions: rmentions,
151
+ timestamp: parseInt(msgMetadata.timestamp || 0),
152
+ participantIDs: (repliedTo.participants || []).map(e => e.toString())
153
+ };
154
+ }
155
+ } catch (err) {
156
+ const errMsg = err && err.message ? err.message : String(err || "Unknown error");
157
+ logger(`parseDelta message_reply repliedToMessage error: ${errMsg}`, "warn");
158
+ }
159
+ } else if (d.deltaMessageReply.replyToMessageId) {
160
+ return defaultFuncs.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
161
+ av: ctx.globalOptions.pageID,
162
+ queries: JSON.stringify({
163
+ o0: {
164
+ doc_id: "2848441488556444",
165
+ query_params: {
166
+ thread_and_message_id: {
167
+ thread_id: callbackToReturn.threadID,
168
+ message_id: d.deltaMessageReply.replyToMessageId.id
169
+ }
170
+ }
171
+ }
172
+ })
173
+ }).then(parseAndCheckLogin(ctx, defaultFuncs)).then(resData => {
174
+ if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
175
+ if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
176
+ const fetchData = resData[0].o0.data.message;
177
+ const mobj = {};
178
+ for (const n in fetchData.message.ranges) {
179
+ mobj[fetchData.message.ranges[n].entity.id] = (fetchData.message.text || "").substr(fetchData.message.ranges[n].offset, fetchData.message.ranges[n].length);
180
+ }
181
+ callbackToReturn.messageReply = {
182
+ type: "Message",
183
+ threadID: callbackToReturn.threadID,
184
+ messageID: fetchData.message_id,
185
+ senderID: fetchData.message_sender.id.toString(),
186
+ attachments: fetchData.message.blob_attachment.map(att => _formatAttachment({ blob_attachment: att })),
187
+ args: (fetchData.message.text || "").trim().split(/\s+/) || [],
188
+ body: fetchData.message.text || "",
189
+ isGroup: callbackToReturn.isGroup,
190
+ mentions: mobj,
191
+ timestamp: parseInt(fetchData.timestamp_precise)
192
+ };
193
+ }).catch(err => {
194
+ const errMsg = err && err.message ? err.message : String(err || "Unknown error");
195
+ logger(`parseDelta message_reply fetch error: ${errMsg}`, "warn");
196
+ }).finally(() => {
197
+ if (callbackToReturn) {
198
+ if (!ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID) return;
199
+ globalCallback(null, callbackToReturn);
200
+ }
201
+ });
202
+ } else {
203
+ if (callbackToReturn) callbackToReturn.delta = d;
204
+ }
205
+ } catch (err) {
206
+ const errMsg = err && err.message ? err.message : String(err || "Unknown error");
207
+ logger(`parseDelta message_reply error: ${errMsg}`, "warn");
208
+ return;
209
+ }
210
+ if (callbackToReturn) {
211
+ if (!ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID) return;
212
+ globalCallback(null, callbackToReturn);
213
+ }
214
+ }
215
+ }
216
+ return;
217
+ }
218
+ }
219
+ switch (delta.class) {
220
+ case "ReadReceipt": {
221
+ let fmtMsg;
222
+ try {
223
+ fmtMsg = formatDeltaReadReceipt(delta);
224
+ } catch (err) {
225
+ return;
226
+ }
227
+ globalCallback(null, fmtMsg);
228
+ break;
229
+ }
230
+ case "AdminTextMessage": {
231
+ switch (delta.type) {
232
+ case "instant_game_dynamic_custom_update":
233
+ case "accept_pending_thread":
234
+ case "confirm_friend_request":
235
+ case "shared_album_delete":
236
+ case "shared_album_addition":
237
+ case "pin_messages_v2":
238
+ case "unpin_messages_v2":
239
+ case "change_thread_theme":
240
+ case "change_thread_nickname":
241
+ case "change_thread_icon":
242
+ case "change_thread_quick_reaction":
243
+ case "change_thread_admins":
244
+ case "group_poll":
245
+ case "joinable_group_link_mode_change":
246
+ case "magic_words":
247
+ case "change_thread_approval_mode":
248
+ case "messenger_call_log":
249
+ case "participant_joined_group_call":
250
+ case "rtc_call_log":
251
+ case "update_vote": {
252
+ let fmtMsg;
253
+ try {
254
+ fmtMsg = formatDeltaEvent(delta);
255
+ } catch (err) {
256
+ return;
257
+ }
258
+ globalCallback(null, fmtMsg);
259
+ break;
260
+ }
261
+ }
262
+ break;
263
+ }
264
+ case "ForcedFetch": {
265
+ if (!delta.threadKey) return;
266
+ const mid = delta.messageId;
267
+ const tid = delta.threadKey.threadFbId || delta.threadKey.otherUserFbId;
268
+ if (mid && tid) {
269
+ const form = {
270
+ av: ctx.globalOptions.pageID,
271
+ queries: JSON.stringify({
272
+ o0: {
273
+ doc_id: "2848441488556444",
274
+ query_params: {
275
+ thread_and_message_id: {
276
+ thread_id: tid.toString(),
277
+ message_id: mid
278
+ }
279
+ }
280
+ }
281
+ })
282
+ };
283
+ defaultFuncs.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form).then(parseAndCheckLogin(ctx, defaultFuncs)).then(resData => {
284
+ if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
285
+ if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
286
+ const fetchData = resData[0].o0.data.message;
287
+ if (getType(fetchData) === "Object") {
288
+ switch (fetchData.__typename) {
289
+ case "ThreadImageMessage":
290
+ if ((!ctx.globalOptions.selfListen && fetchData.message_sender.id.toString() === ctx.userID) || !ctx.loggedIn) {} else {
291
+ globalCallback(null, {
292
+ type: "event",
293
+ threadID: formatID(tid.toString()),
294
+ logMessageType: "log:thread-image",
295
+ logMessageData: {
296
+ image: {
297
+ attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
298
+ width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
299
+ height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
300
+ url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
301
+ }
302
+ },
303
+ logMessageBody: fetchData.snippet,
304
+ timestamp: fetchData.timestamp_precise,
305
+ author: fetchData.message_sender.id
306
+ });
307
+ }
308
+ break;
309
+ case "UserMessage": {
310
+ const event = {
311
+ type: "message",
312
+ senderID: formatID(fetchData.message_sender.id),
313
+ body: fetchData.message.text || "",
314
+ threadID: formatID(tid.toString()),
315
+ messageID: fetchData.message_id,
316
+ attachments: [
317
+ {
318
+ type: "share",
319
+ ID: fetchData.extensible_attachment.legacy_attachment_id,
320
+ url: fetchData.extensible_attachment.story_attachment.url,
321
+ title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
322
+ description: fetchData.extensible_attachment.story_attachment.description.text,
323
+ source: fetchData.extensible_attachment.story_attachment.source,
324
+ image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
325
+ width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
326
+ height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
327
+ playable: ((fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false),
328
+ duration: ((fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0),
329
+ subattachments: fetchData.extensible_attachment.subattachments,
330
+ properties: fetchData.extensible_attachment.story_attachment.properties
331
+ }
332
+ ],
333
+ mentions: {},
334
+ timestamp: parseInt(fetchData.timestamp_precise),
335
+ isGroup: fetchData.message_sender.id !== tid.toString()
336
+ };
337
+ globalCallback(null, event);
338
+ break;
339
+ }
340
+ default:
341
+ break;
342
+ }
343
+ } else {
344
+ return;
345
+ }
346
+ }).catch(err => {
347
+ const errMsg = err && err.message ? err.message : String(err || "Unknown error");
348
+ logger(`parseDelta ForcedFetch error: ${errMsg}`, "warn");
349
+ });
350
+ }
351
+ break;
352
+ }
353
+ case "ThreadName":
354
+ case "ParticipantsAddedToGroupThread":
355
+ case "ParticipantLeftGroupThread": {
356
+ let formattedEvent;
357
+ try {
358
+ formattedEvent = formatDeltaEvent(delta);
359
+ } catch (err) {
360
+ return;
361
+ }
362
+ if (!ctx.globalOptions.selfListen && formattedEvent.author != null && formattedEvent.author.toString() === ctx.userID) return;
363
+ if (!ctx.loggedIn) return;
364
+ globalCallback(null, formattedEvent);
365
+ if (formattedEvent && formattedEvent.type === "event" && formattedEvent.threadID != null && typeof ctx._syncThreadInfoFromEvent === "function") {
366
+ try { ctx._syncThreadInfoFromEvent(formattedEvent); } catch { }
367
+ }
368
+ break;
369
+ }
370
+ case "NewMessage": {
371
+ const hasLiveLocation = d => {
372
+ const attachment = d.attachments && d.attachments[0] && d.attachments[0].mercury && d.attachments[0].mercury.extensible_attachment;
373
+ const storyAttachment = attachment && attachment.story_attachment;
374
+ return storyAttachment && storyAttachment.style_list && storyAttachment.style_list.includes("message_live_location");
375
+ };
376
+ if (delta.attachments && delta.attachments.length === 1 && hasLiveLocation(delta)) {
377
+ delta.class = "UserLocation";
378
+ try {
379
+ const fmtMsg = formatDeltaEvent(delta);
380
+ globalCallback(null, fmtMsg);
381
+ } catch (err) {}
382
+ }
383
+ break;
384
+ }
385
+ }
386
+ };
387
+ };
@@ -0,0 +1,215 @@
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
+ };
@@ -0,0 +1,28 @@
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
+ };