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,309 @@
1
+ "use strict";
2
+
3
+ var utils = require("../../utils/nexca-utils");
4
+ var logger = require("../../utils/nexca-logger");
5
+
6
+ var ALLOWED = {
7
+ attachment: true, url: true, sticker: true, emoji: true,
8
+ emojiSize: true, body: true, mentions: true, location: true,
9
+ replyToMessage: true, forwardAttachmentIds: true
10
+ };
11
+
12
+ var EMOJI_SIZES = { small: 1, medium: 2, large: 3 };
13
+
14
+ function toEmojiSize(size) {
15
+ if (typeof size === "number" && !isNaN(size)) return Math.min(3, Math.max(1, size));
16
+ if (typeof size === "string" && size in EMOJI_SIZES) return EMOJI_SIZES[size];
17
+ return 1;
18
+ }
19
+
20
+ function hasLinks(text) {
21
+ return /(https?:\/\/|www\.|t\.me\/|fb\.me\/|youtu\.be\/|facebook\.com\/|youtube\.com\/)/i.test(text);
22
+ }
23
+
24
+ function buildMentionData(msg, baseBody) {
25
+ if (!Array.isArray(msg.mentions) || !msg.mentions.length) return null;
26
+ var ids = [], offsets = [], lengths = [], types = [];
27
+ for (var i = 0; i < msg.mentions.length; i++) {
28
+ var mention = msg.mentions[i];
29
+ // Ensure tag always has @ prefix — Facebook counts @ in both offset and length
30
+ var tag = String(mention.tag || "");
31
+ if (tag && !tag.startsWith("@")) tag = "@" + tag;
32
+ var fromIndex = Number.isInteger(mention.fromIndex) ? mention.fromIndex : 0;
33
+ var offset = baseBody.indexOf(tag, fromIndex);
34
+ if (offset === -1) {
35
+ // Fallback: search for bare name without @
36
+ offset = baseBody.indexOf(tag.slice(1), fromIndex);
37
+ }
38
+ if (offset < 0) offset = 0;
39
+ ids.push(String(mention.id || 0));
40
+ offsets.push(offset);
41
+ lengths.push(tag.length); // includes @ — matches Facebook's expectation
42
+ types.push("p");
43
+ }
44
+ return {
45
+ mention_ids: ids.join(","),
46
+ mention_offsets: offsets.join(","),
47
+ mention_lengths: lengths.join(","),
48
+ mention_types: types.join(",")
49
+ };
50
+ }
51
+
52
+ function extractIdsFromPayload(payload) {
53
+ var messageID = null, threadID = null;
54
+ function walk(node) {
55
+ if (!Array.isArray(node)) return;
56
+ if (node[0] === 5 && (node[1] === "replaceOptimsiticMessage" || node[1] === "replaceOptimisticMessage")) {
57
+ messageID = String(node[3]);
58
+ }
59
+ if (node[0] === 5 && node[1] === "writeCTAIdToThreadsTable") {
60
+ var candidate = node[2];
61
+ if (Array.isArray(candidate) && candidate[0] === 19) threadID = String(candidate[1]);
62
+ }
63
+ for (var i = 0; i < node.length; i++) walk(node[i]);
64
+ }
65
+ try { walk(payload && payload.step); } catch (_) { }
66
+ return { threadID, messageID };
67
+ }
68
+
69
+ function publishLsRequestWithAck(mqttClient, content, requestId, timeout) {
70
+ timeout = timeout || 15000;
71
+ return new Promise((resolve, reject) => {
72
+ var timer = setTimeout(() => {
73
+ mqttClient.removeListener('message', onMessage);
74
+ reject(new Error('MQTT sendMessage timed out after ' + timeout + 'ms'));
75
+ }, timeout);
76
+
77
+ function onMessage(topic, message) {
78
+ if (topic !== '/ls_resp') return;
79
+ try {
80
+ var data = JSON.parse(message.toString());
81
+ if (String(data.request_id) === String(requestId)) {
82
+ clearTimeout(timer);
83
+ mqttClient.removeListener('message', onMessage);
84
+ var extracted = extractIdsFromPayload(data.payload ? JSON.parse(data.payload) : {});
85
+ resolve({ threadID: extracted.threadID, messageID: extracted.messageID });
86
+ }
87
+ } catch (_) { }
88
+ }
89
+
90
+ mqttClient.on('message', onMessage);
91
+ mqttClient.publish('/ls_req', JSON.stringify(content), { qos: 1 }, err => {
92
+ if (err) {
93
+ clearTimeout(timer);
94
+ mqttClient.removeListener('message', onMessage);
95
+ reject(err);
96
+ }
97
+ });
98
+ });
99
+ }
100
+
101
+ module.exports = function (defaultFuncs, api, ctx) {
102
+ var uploadAttachmentFn = require('../messaging/uploadAttachment')(defaultFuncs, api, ctx);
103
+
104
+ async function uploadAttachments(attachments) {
105
+ if (!Array.isArray(attachments)) attachments = [attachments];
106
+ return uploadAttachmentFn(attachments);
107
+ }
108
+
109
+ async function sendViaMqtt(msg, threadID, replyToMessage) {
110
+ var mqttClient = ctx.mqttClient || global.mqttClient;
111
+ if (!mqttClient) throw new Error('MQTT client not available');
112
+
113
+ var baseBody = msg.body != null ? String(msg.body) : "";
114
+ var requestId = Math.floor(100 + Math.random() * 900);
115
+ var epoch = (BigInt(Date.now()) << 22n).toString();
116
+
117
+ var payload0 = {
118
+ thread_id: String(threadID),
119
+ otid: utils.generateOfflineThreadingID(),
120
+ source: 2097153,
121
+ send_type: 1,
122
+ sync_group: 1,
123
+ mark_thread_read: 1,
124
+ text: baseBody === "" ? null : baseBody,
125
+ initiating_source: 0,
126
+ skip_url_preview_gen: 1,
127
+ text_has_links: hasLinks(baseBody) ? 1 : 0,
128
+ multitab_env: 0,
129
+ metadata_dataclass: JSON.stringify({ media_accessibility_metadata: { alt_text: null } })
130
+ };
131
+
132
+ var mentionData = buildMentionData(msg, baseBody);
133
+ if (mentionData) payload0.mention_data = mentionData;
134
+
135
+ if (msg.sticker) { payload0.send_type = 2; payload0.sticker_id = msg.sticker; }
136
+ if (msg.emoji) { payload0.send_type = 1; payload0.text = msg.emoji; payload0.hot_emoji_size = toEmojiSize(msg.emojiSize); }
137
+
138
+ if (msg.location && msg.location.latitude != null && msg.location.longitude != null) {
139
+ payload0.send_type = 1;
140
+ payload0.location_data = {
141
+ coordinates: { latitude: msg.location.latitude, longitude: msg.location.longitude },
142
+ is_current_location: Boolean(msg.location.current),
143
+ is_live_location: Boolean(msg.location.live)
144
+ };
145
+ }
146
+
147
+ var effectiveReplyTo = replyToMessage || msg.replyToMessage;
148
+ if (effectiveReplyTo) {
149
+ payload0.reply_metadata = {
150
+ reply_source_id: effectiveReplyTo,
151
+ reply_source_type: 1,
152
+ reply_type: 0
153
+ };
154
+ }
155
+
156
+ if (msg.attachment) {
157
+ payload0.send_type = 3;
158
+ if (payload0.text === "") payload0.text = null;
159
+ payload0.attachment_fbids = [];
160
+ var list = Array.isArray(msg.attachment) ? msg.attachment : [msg.attachment];
161
+ var preuploaded = [], toUpload = [];
162
+ for (var item of list) {
163
+ if (Array.isArray(item) && item.length >= 2 && typeof item[0] === "string") {
164
+ preuploaded.push(String(item[1]));
165
+ } else if (utils.isReadableStream(item)) {
166
+ toUpload.push(item);
167
+ }
168
+ }
169
+ if (preuploaded.length) payload0.attachment_fbids = payload0.attachment_fbids.concat(preuploaded);
170
+ if (msg.forwardAttachmentIds && msg.forwardAttachmentIds.length) {
171
+ payload0.attachment_fbids = payload0.attachment_fbids.concat(msg.forwardAttachmentIds.map(String));
172
+ }
173
+
174
+ if (toUpload.length) {
175
+ var uploaded = await uploadAttachments(toUpload);
176
+ for (var u of uploaded) {
177
+ if (!u) continue;
178
+ var fbid = u.image_id || u.video_id || u.audio_id || u.file_id || u.sticker_id || u.gif_id;
179
+ if (!fbid) {
180
+ var firstKey = Object.keys(u).find(function(k) { return u[k] && /^\d+$/.test(String(u[k])); });
181
+ if (firstKey) fbid = u[firstKey];
182
+ }
183
+ if (fbid) payload0.attachment_fbids.push(String(fbid));
184
+ }
185
+ }
186
+ if (!payload0.attachment_fbids.length) delete payload0.attachment_fbids;
187
+ }
188
+
189
+ var tasks = [
190
+ {
191
+ label: '46',
192
+ payload: JSON.stringify(payload0),
193
+ queue_name: String(threadID),
194
+ task_id: 400,
195
+ failure_count: null
196
+ },
197
+ {
198
+ label: '21',
199
+ payload: JSON.stringify({
200
+ thread_id: String(threadID),
201
+ last_read_watermark_ts: Date.now(),
202
+ sync_group: 1
203
+ }),
204
+ queue_name: String(threadID),
205
+ task_id: 401,
206
+ failure_count: null
207
+ }
208
+ ];
209
+
210
+ var content = {
211
+ app_id: '2220391788200892',
212
+ payload: JSON.stringify({
213
+ tasks: tasks,
214
+ epoch_id: epoch,
215
+ version_id: '24804310205905615',
216
+ data_trace_id: '#' + Buffer.from(String(Math.random())).toString('base64').replace(/=+$/, '')
217
+ }),
218
+ request_id: requestId,
219
+ type: 3
220
+ };
221
+
222
+ return publishLsRequestWithAck(mqttClient, content, requestId, 15000);
223
+ }
224
+
225
+ return async function sendMessage(msg, threadID, callback, replyToMessage, isSingleUser) {
226
+ if (typeof msg === "string") msg = { body: msg };
227
+ if (typeof callback !== "function") { callback = null; }
228
+
229
+ var resolve, reject;
230
+ var promise = new Promise((res, rej) => { resolve = res; reject = rej; });
231
+
232
+ for (var key in msg) {
233
+ if (!ALLOWED[key]) {
234
+ var err = { error: "sendMessage: Unknown property '" + key + "'" };
235
+ if (callback) callback(err);
236
+ else reject(err);
237
+ return promise;
238
+ }
239
+ }
240
+
241
+ // Auto-detect isSingleUser from ctx.threadTypes if not explicitly provided.
242
+ // parseDelta in listenMqtt.js populates ctx.threadTypes[senderID] = 'dm' | 'group'
243
+ if (isSingleUser === undefined && ctx.threadTypes) {
244
+ isSingleUser = ctx.threadTypes[String(threadID)] === 'dm';
245
+ }
246
+
247
+ // DM attachment sends — skip MQTT entirely.
248
+ // For E2EE DMs: route through the E2EE bridge (Noise WebSocket, Signal Protocol).
249
+ // Facebook strips attachment_fbids from MQTT messages in E2EE threads
250
+ // (can't re-encrypt CDN attachments on the fly), so MQTT silently drops them.
251
+ // The vendor's client.sendImage/sendVideo/sendAudio encrypts the file data
252
+ // and sends via the Noise WebSocket — the only path that actually delivers
253
+ // attachments in E2EE threads.
254
+ // For non-E2EE DMs: use OldMessage.
255
+ // /messaging/send/ with other_user_fbid routing works for plain DMs.
256
+ // (For E2EE DMs it returns 404 because the endpoint is deprecated for those.)
257
+ if (isSingleUser && msg.attachment) {
258
+ var useE2EE = api.e2ee && typeof api.e2ee.isConnected === "function" && api.e2ee.isConnected();
259
+ if (useE2EE) {
260
+ try {
261
+ var e2eeResult = await api.e2ee.sendMessage(String(threadID), msg, replyToMessage);
262
+ var wrapped = e2eeResult && e2eeResult.messageId
263
+ ? { threadID: String(threadID), messageID: String(e2eeResult.messageId) }
264
+ : e2eeResult;
265
+ if (callback) callback(null, wrapped);
266
+ else resolve(wrapped);
267
+ } catch (e2eeErr) {
268
+ logger.error("sendMessage", "E2EE DM attachment send failed: " + (e2eeErr.message || e2eeErr));
269
+ if (callback) callback(e2eeErr);
270
+ else reject(e2eeErr);
271
+ }
272
+ } else {
273
+ try {
274
+ var omResult = await new Promise((res2, rej2) => {
275
+ api.OldMessage(msg, threadID, (err2, data2) => err2 ? rej2(err2) : res2(data2), replyToMessage, true);
276
+ });
277
+ if (callback) callback(null, omResult);
278
+ else resolve(omResult);
279
+ } catch (omErr) {
280
+ logger.error("sendMessage", "DM attachment via OldMessage failed: " + (omErr.error || omErr.message || omErr));
281
+ if (callback) callback(omErr);
282
+ else reject(omErr);
283
+ }
284
+ }
285
+ return promise;
286
+ }
287
+
288
+ try {
289
+ var result = await sendViaMqtt(msg, threadID, replyToMessage);
290
+ if (callback) callback(null, result);
291
+ else resolve(result);
292
+ } catch (mqttErr) {
293
+ logger.warn("sendMessage", "MQTT failed, falling back to OldMessage: " + (mqttErr.message || mqttErr));
294
+ try {
295
+ var fbResult = await new Promise((res2, rej2) => {
296
+ api.OldMessage(msg, threadID, (err2, data2) => err2 ? rej2(err2) : res2(data2), replyToMessage, isSingleUser);
297
+ });
298
+ if (callback) callback(null, fbResult);
299
+ else resolve(fbResult);
300
+ } catch (fbErr) {
301
+ logger.error("sendMessage", fbErr.error || fbErr.message || fbErr);
302
+ if (callback) callback(fbErr);
303
+ else reject(fbErr);
304
+ }
305
+ }
306
+
307
+ return promise;
308
+ };
309
+ };
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+
3
+ var utils = require("../../utils/nexca-utils");
4
+
5
+ module.exports = function (defaultFuncs, api, ctx) {
6
+ return function sendMessageMqtt(msg, threadID, callback, replyToMessage) {
7
+ if (typeof msg === "string") msg = { body: msg };
8
+ var mqttClient = ctx.mqttClient || global.mqttClient;
9
+ if (!mqttClient) {
10
+ var err = { error: "MQTT not connected. Call listenMqtt first." };
11
+ if (typeof callback === "function") return callback(err);
12
+ return Promise.reject(err);
13
+ }
14
+
15
+ ctx.wsReqNumber = (ctx.wsReqNumber || 0) + 1;
16
+ ctx.wsTaskNumber = (ctx.wsTaskNumber || 0) + 1;
17
+
18
+ var baseBody = msg.body != null ? String(msg.body) : "";
19
+ var hasLinks = typeof baseBody === "string" && /(https?:\/\/|www\.|t\.me\/|fb\.me\/|youtu\.be\/|facebook\.com\/|youtube\.com\/)/i.test(baseBody);
20
+ var requestId = ctx.wsReqNumber;
21
+
22
+ var payload0 = {
23
+ thread_id: String(threadID),
24
+ otid: utils.generateOfflineThreadingID(),
25
+ source: 2097153,
26
+ send_type: 1,
27
+ sync_group: 1,
28
+ mark_thread_read: 1,
29
+ text: baseBody === "" ? null : baseBody,
30
+ initiating_source: 0,
31
+ skip_url_preview_gen: 1,
32
+ text_has_links: hasLinks ? 1 : 0,
33
+ multitab_env: 0
34
+ };
35
+
36
+ if (msg.sticker) { payload0.send_type = 2; payload0.sticker_id = msg.sticker; }
37
+ if (replyToMessage || msg.replyToMessage) {
38
+ payload0.reply_metadata = {
39
+ reply_source_id: replyToMessage || msg.replyToMessage,
40
+ reply_source_type: 1,
41
+ reply_type: 0
42
+ };
43
+ }
44
+
45
+ var content = {
46
+ app_id: '2220391788200892',
47
+ payload: JSON.stringify({
48
+ tasks: [{
49
+ failure_count: null,
50
+ label: '46',
51
+ payload: JSON.stringify(payload0),
52
+ queue_name: String(threadID),
53
+ task_id: ctx.wsTaskNumber
54
+ }],
55
+ epoch_id: utils.generateOfflineThreadingID(),
56
+ version_id: '7214102258676893'
57
+ }),
58
+ request_id: requestId,
59
+ type: 3
60
+ };
61
+
62
+ if (typeof callback === "function") {
63
+ ctx.reqCallbacks[requestId] = callback;
64
+ }
65
+
66
+ mqttClient.publish('/ls_req', JSON.stringify(content), { qos: 1 });
67
+ return Promise.resolve({ requestId });
68
+ };
69
+ };