@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,264 +0,0 @@
1
- "use strict";
2
- const logger = require("../../../func/logger");
3
-
4
- /**
5
- * Message Scheduler System
6
- * Allows scheduling messages to be sent at a specific time in the future
7
- */
8
- module.exports = function (defaultFuncs, api, ctx) {
9
- // Initialize scheduler on first call
10
- if (!ctx._scheduler) {
11
- ctx._scheduler = createSchedulerInstance(api);
12
- }
13
-
14
- return ctx._scheduler;
15
- };
16
-
17
- function createSchedulerInstance(api) {
18
- const scheduledMessages = new Map(); // Map<id, ScheduledMessage>
19
- let nextId = 1;
20
-
21
- /**
22
- * Scheduled Message Object
23
- * @typedef {Object} ScheduledMessage
24
- * @property {string} id - Unique identifier
25
- * @property {string|Object} message - Message content
26
- * @property {string|string[]} threadID - Target thread ID(s)
27
- * @property {number} timestamp - When to send (Unix timestamp in ms)
28
- * @property {number} createdAt - When scheduled (Unix timestamp in ms)
29
- * @property {Object} options - Additional options (replyMessageID, isGroup, etc.)
30
- * @property {Function} callback - Optional callback when sent
31
- * @property {NodeJS.Timeout} timeout - Timeout reference
32
- * @property {boolean} cancelled - Whether cancelled
33
- */
34
-
35
- /**
36
- * Schedule a message to be sent at a specific time
37
- * @param {string|Object} message - Message content
38
- * @param {string|string[]} threadID - Target thread ID(s)
39
- * @param {Date|number|string} when - When to send (Date, timestamp, or ISO string)
40
- * @param {Object} [options] - Additional options
41
- * @param {string} [options.replyMessageID] - Message ID to reply to
42
- * @param {boolean} [options.isGroup] - Whether it's a group chat
43
- * @param {Function} [options.callback] - Callback when sent
44
- * @returns {string} Scheduled message ID
45
- */
46
- function scheduleMessage(message, threadID, when, options = {}) {
47
- let timestamp;
48
-
49
- // Parse when parameter
50
- if (when instanceof Date) {
51
- timestamp = when.getTime();
52
- } else if (typeof when === "number") {
53
- timestamp = when;
54
- } else if (typeof when === "string") {
55
- timestamp = new Date(when).getTime();
56
- } else {
57
- throw new Error("Invalid 'when' parameter. Must be Date, number (timestamp), or ISO string");
58
- }
59
-
60
- // Validate timestamp
61
- if (isNaN(timestamp)) {
62
- throw new Error("Invalid date/time");
63
- }
64
-
65
- const now = Date.now();
66
- if (timestamp <= now) {
67
- throw new Error("Scheduled time must be in the future");
68
- }
69
-
70
- const id = `scheduled_${nextId++}_${Date.now()}`;
71
- const delay = timestamp - now;
72
-
73
- // Create scheduled message object
74
- const scheduled = {
75
- id,
76
- message,
77
- threadID,
78
- timestamp,
79
- createdAt: now,
80
- options: {
81
- replyMessageID: options.replyMessageID,
82
- isGroup: options.isGroup,
83
- callback: options.callback
84
- },
85
- cancelled: false
86
- };
87
-
88
- // Set timeout to send message
89
- scheduled.timeout = setTimeout(() => {
90
- if (scheduled.cancelled) return;
91
-
92
- try {
93
- logger(`Sending scheduled message ${id}`, "info");
94
-
95
- // Send message
96
- api.sendMessage(
97
- message,
98
- threadID,
99
- scheduled.options.callback || (() => {}),
100
- scheduled.options.replyMessageID,
101
- scheduled.options.isGroup
102
- ).then(() => {
103
- logger(`Scheduled message ${id} sent successfully`, "info");
104
- scheduledMessages.delete(id);
105
- }).catch(err => {
106
- logger(`Error sending scheduled message ${id}: ${err && err.message ? err.message : String(err)}`, "error");
107
- if (scheduled.options.callback) {
108
- scheduled.options.callback(err);
109
- }
110
- scheduledMessages.delete(id);
111
- });
112
- } catch (err) {
113
- logger(`Error in scheduled message ${id}: ${err && err.message ? err.message : String(err)}`, "error");
114
- scheduledMessages.delete(id);
115
- }
116
- }, delay);
117
-
118
- scheduledMessages.set(id, scheduled);
119
- logger(`Message scheduled: ${id} (in ${Math.round(delay / 1000)}s)`, "info");
120
-
121
- return id;
122
- }
123
-
124
- /**
125
- * Cancel a scheduled message
126
- * @param {string} id - Scheduled message ID
127
- * @returns {boolean} True if cancelled, false if not found
128
- */
129
- function cancelScheduledMessage(id) {
130
- const scheduled = scheduledMessages.get(id);
131
- if (!scheduled) {
132
- return false;
133
- }
134
-
135
- if (scheduled.cancelled) {
136
- return false; // Already cancelled
137
- }
138
-
139
- clearTimeout(scheduled.timeout);
140
- scheduled.cancelled = true;
141
- scheduledMessages.delete(id);
142
- logger(`Scheduled message ${id} cancelled`, "info");
143
- return true;
144
- }
145
-
146
- /**
147
- * Get scheduled message info
148
- * @param {string} id - Scheduled message ID
149
- * @returns {ScheduledMessage|null} Scheduled message or null if not found
150
- */
151
- function getScheduledMessage(id) {
152
- const scheduled = scheduledMessages.get(id);
153
- if (!scheduled || scheduled.cancelled) {
154
- return null;
155
- }
156
-
157
- // Return a copy without internal properties
158
- return {
159
- id: scheduled.id,
160
- message: scheduled.message,
161
- threadID: scheduled.threadID,
162
- timestamp: scheduled.timestamp,
163
- createdAt: scheduled.createdAt,
164
- options: { ...scheduled.options },
165
- timeUntilSend: scheduled.timestamp - Date.now()
166
- };
167
- }
168
-
169
- /**
170
- * List all scheduled messages
171
- * @returns {ScheduledMessage[]} Array of scheduled messages
172
- */
173
- function listScheduledMessages() {
174
- const now = Date.now();
175
- const list = [];
176
-
177
- for (const scheduled of scheduledMessages.values()) {
178
- if (scheduled.cancelled) continue;
179
-
180
- list.push({
181
- id: scheduled.id,
182
- message: scheduled.message,
183
- threadID: scheduled.threadID,
184
- timestamp: scheduled.timestamp,
185
- createdAt: scheduled.createdAt,
186
- options: { ...scheduled.options },
187
- timeUntilSend: scheduled.timestamp - now
188
- });
189
- }
190
-
191
- // Sort by timestamp
192
- return list.sort((a, b) => a.timestamp - b.timestamp);
193
- }
194
-
195
- /**
196
- * Cancel all scheduled messages
197
- * @returns {number} Number of cancelled messages
198
- */
199
- function cancelAllScheduledMessages() {
200
- let count = 0;
201
- for (const id of scheduledMessages.keys()) {
202
- if (cancelScheduledMessage(id)) {
203
- count++;
204
- }
205
- }
206
- logger(`Cancelled ${count} scheduled messages`, "info");
207
- return count;
208
- }
209
-
210
- /**
211
- * Get count of scheduled messages
212
- * @returns {number} Count
213
- */
214
- function getScheduledCount() {
215
- return scheduledMessages.size;
216
- }
217
-
218
- /**
219
- * Clear expired/cancelled messages from memory
220
- */
221
- function cleanup() {
222
- const now = Date.now();
223
- let cleaned = 0;
224
-
225
- for (const [id, scheduled] of scheduledMessages.entries()) {
226
- if (scheduled.cancelled || scheduled.timestamp < now) {
227
- scheduledMessages.delete(id);
228
- cleaned++;
229
- }
230
- }
231
-
232
- if (cleaned > 0) {
233
- logger(`Cleaned up ${cleaned} scheduled messages`, "info");
234
- }
235
- }
236
-
237
- // Auto cleanup every 5 minutes
238
- const cleanupInterval = setInterval(cleanup, 5 * 60 * 1000);
239
-
240
- /**
241
- * Destroy scheduler and cleanup all resources
242
- * @returns {number} Number of cancelled messages
243
- */
244
- function destroy() {
245
- clearInterval(cleanupInterval);
246
- const count = cancelAllScheduledMessages();
247
- logger("Scheduler destroyed and all resources cleaned up", "info");
248
- return count;
249
- }
250
-
251
- // Return scheduler API
252
- return {
253
- scheduleMessage,
254
- cancelScheduledMessage,
255
- getScheduledMessage,
256
- listScheduledMessages,
257
- cancelAllScheduledMessages,
258
- getScheduledCount,
259
- cleanup,
260
- destroy,
261
- // Cleanup interval reference for manual cleanup if needed
262
- _cleanupInterval: cleanupInterval
263
- };
264
- }
@@ -1,53 +0,0 @@
1
- "use strict";
2
-
3
- const { parseAndCheckLogin } = require("../../utils/client");
4
- const { formatThread } = require("../../utils/format");
5
- module.exports = function(defaultFuncs, api, ctx) {
6
- return function searchForThread(name, callback) {
7
- let resolveFunc = function() {};
8
- let rejectFunc = function() {};
9
- const returnPromise = new Promise(function(resolve, reject) {
10
- resolveFunc = resolve;
11
- rejectFunc = reject;
12
- });
13
-
14
- if (!callback) {
15
- callback = function(err, friendList) {
16
- if (err) {
17
- return rejectFunc(err);
18
- }
19
- resolveFunc(friendList);
20
- };
21
- }
22
-
23
- const tmpForm = {
24
- client: "web_messenger",
25
- query: name,
26
- offset: 0,
27
- limit: 21,
28
- index: "fbid"
29
- };
30
-
31
- defaultFuncs
32
- .post(
33
- "https://www.facebook.com/ajax/mercury/search_threads.php",
34
- ctx.jar,
35
- tmpForm
36
- )
37
- .then(parseAndCheckLogin(ctx, defaultFuncs))
38
- .then(function(resData) {
39
- if (resData.error) {
40
- throw resData;
41
- }
42
- if (!resData.payload.mercury_payload.threads) {
43
- return callback({ error: "Could not find thread `" + name + "`." });
44
- }
45
- return callback(
46
- null,
47
- resData.payload.mercury_payload.threads.map(formatThread)
48
- );
49
- });
50
-
51
- return returnPromise;
52
- };
53
- };
@@ -1,270 +0,0 @@
1
- /**
2
- * Create by Donix-VN (DongDev)
3
- * Don't change credit
4
- * Send a message using MQTT.
5
- * @param {string} text - The text of the message to send.
6
- * @param {string} threadID - The ID of the thread to send the message to.
7
- * @param {string} [msgReplace] - Optional. The message ID of the message to replace.
8
- * @param {Array<Buffer|Stream>} [attachments] - Optional. The attachments to send with the message.
9
- * @param {function} [callback] - Optional. The callback function to call when the message is sent.
10
- * @returns {Promise<object>} A promise that resolves with the bodies of the sent message.
11
- */
12
-
13
- "use strict";
14
- const log = require("../../../func/logAdapter");
15
- const { getType } = require("../../utils/format");
16
- const { isReadableStream } = require("../../utils/constants");
17
- const { generateOfflineThreadingID } = require("../../utils/format");
18
-
19
- module.exports = function (defaultFuncs, api, ctx) {
20
- const uploadAttachment = require("./uploadAttachment")(defaultFuncs, api, ctx);
21
- const hasLinks = s => typeof s === "string" && /(https?:\/\/|www\.|t\.me\/|fb\.me\/|youtu\.be\/|facebook\.com\/|youtube\.com\/)/i.test(s);
22
- const emojiSizes = { small: 1, medium: 2, large: 3 };
23
-
24
- function extractIdsFromPayload(payload) {
25
- let messageID = null;
26
- let threadID = null;
27
- function walk(n) {
28
- if (Array.isArray(n)) {
29
- if (n[0] === 5 && (n[1] === "replaceOptimsiticMessage" || n[1] === "replaceOptimisticMessage")) {
30
- messageID = String(n[3]);
31
- }
32
- if (n[0] === 5 && n[1] === "writeCTAIdToThreadsTable") {
33
- const a = n[2];
34
- if (Array.isArray(a) && a[0] === 19) threadID = String(a[1]);
35
- }
36
- for (const x of n) walk(x);
37
- }
38
- }
39
- walk(payload?.step);
40
- return { threadID, messageID };
41
- }
42
-
43
- function publishWithAck(content, text, reqID, callback) {
44
- return new Promise((resolve, reject) => {
45
- // Ensure MQTT client is available before using it
46
- if (!ctx.mqttClient || typeof ctx.mqttClient.on !== "function" || typeof ctx.mqttClient.publish !== "function") {
47
- const err = new Error("MQTT client is not initialized");
48
- log.error("sendMessageMqtt", err);
49
- callback && callback(err);
50
- return reject(err);
51
- }
52
-
53
- // Remove default max listeners limit to avoid MaxListenersExceededWarning
54
- if (typeof ctx.mqttClient.setMaxListeners === "function") {
55
- ctx.mqttClient.setMaxListeners(0);
56
- }
57
-
58
- let done = false;
59
- const cleanup = () => {
60
- if (done) return;
61
- done = true;
62
- ctx.mqttClient.removeListener("message", handleRes);
63
- };
64
- const handleRes = (topic, message) => {
65
- if (topic !== "/ls_resp") return;
66
- let jsonMsg;
67
- try {
68
- jsonMsg = JSON.parse(message.toString());
69
- jsonMsg.payload = JSON.parse(jsonMsg.payload);
70
- } catch {
71
- return;
72
- }
73
- if (jsonMsg.request_id !== reqID) return;
74
- const { threadID, messageID } = extractIdsFromPayload(jsonMsg.payload);
75
- const bodies = { body: text || null, messageID, threadID };
76
- cleanup();
77
- callback && callback(undefined, bodies);
78
- resolve(bodies);
79
- };
80
- ctx.mqttClient.on("message", handleRes);
81
- ctx.mqttClient.publish("/ls_req", JSON.stringify(content), { qos: 1, retain: false }, err => {
82
- if (err) {
83
- cleanup();
84
- callback && callback(err);
85
- reject(err);
86
- }
87
- });
88
- setTimeout(() => {
89
- if (done) return;
90
- cleanup();
91
- const err = { error: "Timeout waiting for ACK" };
92
- callback && callback(err);
93
- reject(err);
94
- }, 15000);
95
- });
96
- }
97
-
98
- function buildMentionData(msg, baseBody) {
99
- if (!msg.mentions || !Array.isArray(msg.mentions) || !msg.mentions.length) return null;
100
- const base = typeof baseBody === "string" ? baseBody : "";
101
- const ids = [];
102
- const offsets = [];
103
- const lengths = [];
104
- const types = [];
105
- let cursor = 0;
106
- for (const m of msg.mentions) {
107
- const raw = String(m.tag || "");
108
- const name = raw.replace(/^@+/, "");
109
- const start = Number.isInteger(m.fromIndex) ? m.fromIndex : cursor;
110
- let idx = base.indexOf(raw, start);
111
- let adj = 0;
112
- if (idx === -1) {
113
- idx = base.indexOf(name, start);
114
- adj = 0;
115
- } else {
116
- adj = raw.length - name.length;
117
- }
118
- if (idx < 0) {
119
- idx = 0;
120
- adj = 0;
121
- }
122
- const off = idx + adj;
123
- ids.push(String(m.id || 0));
124
- offsets.push(off);
125
- lengths.push(name.length);
126
- types.push("p");
127
- cursor = off + name.length;
128
- }
129
- return {
130
- mention_ids: ids.join(","),
131
- mention_offsets: offsets.join(","),
132
- mention_lengths: lengths.join(","),
133
- mention_types: types.join(",")
134
- };
135
- }
136
-
137
- function coerceMsg(x) {
138
- if (x == null) return { body: "" };
139
- if (typeof x === "string") return { body: x };
140
- if (typeof x === "object") return x;
141
- return { body: String(x) };
142
- }
143
-
144
- return async function sendMessageMqtt(msg, threadID, callback, replyToMessage) {
145
- if (typeof threadID === "function") return threadID({ error: "Pass a threadID as a second argument." });
146
- if (typeof callback === "string" && !replyToMessage) {
147
- replyToMessage = callback;
148
- callback = () => { };
149
- }
150
- if (typeof callback !== "function") callback = () => { };
151
- if (!threadID) {
152
- const err = { error: "threadID is required" };
153
- callback(err);
154
- throw err;
155
- }
156
-
157
- const m = coerceMsg(msg);
158
- const baseBody = m.body != null ? String(m.body) : "";
159
- const reqID = Math.floor(100 + Math.random() * 900);
160
- const epoch = (BigInt(Date.now()) << 22n).toString();
161
-
162
- const payload0 = {
163
- thread_id: String(threadID),
164
- otid: generateOfflineThreadingID(),
165
- source: 2097153,
166
- send_type: 1,
167
- sync_group: 1,
168
- mark_thread_read: 1,
169
- text: baseBody === "" ? null : baseBody,
170
- initiating_source: 0,
171
- skip_url_preview_gen: 0,
172
- text_has_links: hasLinks(baseBody) ? 1 : 0,
173
- multitab_env: 0,
174
- metadata_dataclass: JSON.stringify({ media_accessibility_metadata: { alt_text: null } })
175
- };
176
-
177
- const mentionData = buildMentionData(m, baseBody);
178
- if (mentionData) payload0.mention_data = mentionData;
179
-
180
- if (m.sticker) {
181
- payload0.send_type = 2;
182
- payload0.sticker_id = m.sticker;
183
- }
184
-
185
- if (m.emoji) {
186
- const size = !isNaN(m.emojiSize) ? Number(m.emojiSize) : emojiSizes[m.emojiSize || "small"] || 1;
187
- payload0.send_type = 1;
188
- payload0.text = m.emoji;
189
- payload0.hot_emoji_size = Math.min(3, Math.max(1, size));
190
- }
191
-
192
- if (m.location && m.location.latitude != null && m.location.longitude != null) {
193
- payload0.send_type = 1;
194
- payload0.location_data = {
195
- coordinates: { latitude: m.location.latitude, longitude: m.location.longitude },
196
- is_current_location: !!m.location.current,
197
- is_live_location: !!m.location.live
198
- };
199
- }
200
-
201
- if (replyToMessage) {
202
- payload0.reply_metadata = { reply_source_id: replyToMessage, reply_source_type: 1, reply_type: 0 };
203
- }
204
-
205
- if (m.attachment) {
206
- payload0.send_type = 3;
207
- if (payload0.text === "") payload0.text = null;
208
- payload0.attachment_fbids = [];
209
- let list = m.attachment;
210
- if (getType(list) !== "Array") list = [list];
211
- const idsFromPairs = [];
212
- const streams = [];
213
- for (const it of list) {
214
- if (Array.isArray(it) && typeof it[0] === "string") {
215
- idsFromPairs.push(String(it[1]));
216
- } else if (isReadableStream(it)) {
217
- streams.push(it);
218
- }
219
- }
220
- if (idsFromPairs.length) payload0.attachment_fbids.push(...idsFromPairs);
221
- if (streams.length) {
222
- try {
223
- const files = await uploadAttachment(streams);
224
- for (const file of files) {
225
- const key = Object.keys(file)[0];
226
- payload0.attachment_fbids.push(file[key]);
227
- }
228
- } catch (err) {
229
- log.error("uploadAttachment", err);
230
- callback(err);
231
- throw err;
232
- }
233
- }
234
- }
235
-
236
- const content = {
237
- app_id: "2220391788200892",
238
- payload: {
239
- tasks: [
240
- {
241
- label: "46",
242
- payload: payload0,
243
- queue_name: String(threadID),
244
- task_id: 400,
245
- failure_count: null
246
- },
247
- {
248
- label: "21",
249
- payload: {
250
- thread_id: String(threadID),
251
- last_read_watermark_ts: Date.now(),
252
- sync_group: 1
253
- },
254
- queue_name: String(threadID),
255
- task_id: 401,
256
- failure_count: null
257
- }
258
- ],
259
- epoch_id: epoch,
260
- version_id: "24804310205905615",
261
- data_trace_id: "#" + Buffer.from(String(Math.random())).toString("base64").replace(/=+$/g, "")
262
- },
263
- request_id: reqID,
264
- type: 3
265
- };
266
- content.payload.tasks.forEach(t => (t.payload = JSON.stringify(t.payload)));
267
- content.payload = JSON.stringify(content.payload);
268
- return publishWithAck(content, baseBody, reqID, callback);
269
- };
270
- };
@@ -1,74 +0,0 @@
1
- "use strict";
2
- const { getType } = require("../../utils/format");
3
- module.exports = function (defaultFuncs, api, ctx) {
4
- return function sendTyping(threadID, isTyping, options, callback) {
5
- var resolveFunc = function () { };
6
- var rejectFunc = function () { };
7
- var returnPromise = new Promise(function (resolve, reject) {
8
- resolveFunc = resolve;
9
- rejectFunc = reject;
10
- });
11
- if (getType(options) == "Function" || getType(options) == "AsyncFunction") {
12
- callback = options;
13
- options = {};
14
- }
15
- options = options || {};
16
- if (!callback || getType(callback) != "Function" && getType(callback) != "AsyncFunction") {
17
- callback = function (err, data) {
18
- if (err) return rejectFunc(err);
19
- resolveFunc(data);
20
- };
21
- }
22
- if (!threadID) {
23
- return callback(new Error("threadID is required"));
24
- }
25
- if (!ctx.mqttClient) {
26
- const err = new Error("Not connected to MQTT");
27
- callback(err);
28
- rejectFunc(err);
29
- return returnPromise;
30
- }
31
- if (typeof ctx.wsReqNumber !== "number") ctx.wsReqNumber = 0;
32
- const threadIDs = Array.isArray(threadID) ? threadID : [threadID];
33
- threadIDs.forEach(tid => {
34
- var isGroupThread = getType(tid) === "Array" ? 0 : 1;
35
- var threadType = isGroupThread ? 2 : 1;
36
- var duration = options.duration || 10000;
37
- var autoStop = options.autoStop !== false;
38
- var attribution = options.type || 0;
39
- const publishTypingStatus = (isTypingStatus) => {
40
- ctx.mqttClient.publish('/ls_req',
41
- JSON.stringify({
42
- app_id: "772021112871879",
43
- payload: JSON.stringify({
44
- label: "3",
45
- payload: JSON.stringify({
46
- "thread_key": parseInt(tid),
47
- "is_group_thread": isGroupThread,
48
- "is_typing": isTypingStatus ? 1 : 0,
49
- "attribution": attribution,
50
- "sync_group": 1,
51
- "thread_type": threadType
52
- }),
53
- version: "8965252033599983"
54
- }),
55
- request_id: ++ctx.wsReqNumber,
56
- type: 4
57
- }),
58
- {
59
- qos: 1,
60
- retain: false,
61
- }
62
- );
63
- };
64
- publishTypingStatus(isTyping);
65
- if (isTyping && autoStop) {
66
- setTimeout(() => {
67
- publishTypingStatus(false);
68
- }, duration);
69
- }
70
- });
71
- callback(null, true);
72
- return returnPromise;
73
- };
74
- };