hridoy-ultimate 8.0.2 → 9.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.
- package/CHANGELOG.md +68 -40
- package/LICENSE +23 -0
- package/MERGE_REPORT.md +54 -0
- package/README.md +158 -113
- package/THIRD_PARTY_NOTICES.md +36 -0
- package/docs/TEST_RESULTS.md +68 -0
- package/docs/UPSTREAM_API_DOCS.md +2712 -0
- package/func/checkUpdate.js +6 -0
- package/func/logAdapter.js +33 -0
- package/func/logger.js +48 -0
- package/index.d.ts +812 -0
- package/index.js +30 -824
- package/module/config.js +46 -0
- package/module/login.js +136 -0
- package/module/loginHelper.js +1413 -0
- package/module/options.js +55 -0
- package/package.json +75 -22
- package/scripts/run-tests.js +19 -0
- package/scripts/syntax-check.js +22 -0
- package/src/{addExternalModule.js → api/action/addExternalModule.js} +8 -8
- package/src/{changeAvatar.js → api/action/changeAvatar.js} +32 -33
- package/src/{changeBio.js → api/action/changeBio.js} +19 -22
- package/src/api/action/dismissScrapingWarning.js +50 -0
- package/src/api/action/enableAutoSaveAppState.js +73 -0
- package/src/{getCurrentUserID.js → api/action/getCurrentUserID.js} +1 -1
- package/src/api/action/handleFriendRequest.js +57 -0
- package/src/api/action/logout.js +95 -0
- package/src/api/action/refreshFb_dtsg.js +47 -0
- package/src/{setPostReaction.js → api/action/setPostReaction.js} +23 -31
- package/src/{unfriend.js → api/action/unfriend.js} +14 -14
- package/src/api/http/httpGet.js +46 -0
- package/src/api/http/httpPost.js +52 -0
- package/src/api/http/postFormData.js +47 -0
- package/src/api/messaging/addUserToGroup.js +68 -0
- package/src/api/messaging/changeAdminStatus.js +126 -0
- package/src/{changeArchivedStatus.js → api/messaging/changeArchivedStatus.js} +15 -17
- package/src/{changeBlockedStatus.js → api/messaging/changeBlockedStatus.js} +13 -16
- package/src/api/messaging/changeGroupImage.js +91 -0
- package/src/api/messaging/changeNickname.js +70 -0
- package/src/api/messaging/changeThreadColor.js +79 -0
- package/src/api/messaging/changeThreadEmoji.js +111 -0
- package/src/{createNewGroup.js → api/messaging/createNewGroup.js} +24 -26
- package/src/api/messaging/createPoll.js +46 -0
- package/src/api/messaging/createThemeAI.js +98 -0
- package/src/api/messaging/deleteMessage.js +136 -0
- package/src/{deleteThread.js → api/messaging/deleteThread.js} +14 -16
- package/src/api/messaging/editMessage.js +105 -0
- package/src/api/messaging/forwardAttachment.js +57 -0
- package/src/api/messaging/forwardMessage.js +134 -0
- package/src/{getEmojiUrl.js → api/messaging/getEmojiUrl.js} +2 -2
- package/src/{getFriendsList.js → api/messaging/getFriendsList.js} +16 -19
- package/src/{getMessage.js → api/messaging/getMessage.js} +160 -180
- package/src/api/messaging/getThemePictures.js +62 -0
- package/src/api/messaging/handleMessageRequest.js +65 -0
- package/src/api/messaging/markAsDelivered.js +69 -0
- package/src/api/messaging/markAsRead.js +110 -0
- package/src/api/messaging/markAsReadAll.js +56 -0
- package/src/api/messaging/markAsSeen.js +68 -0
- package/src/api/messaging/muteThread.js +50 -0
- package/src/api/messaging/pinMessage.js +115 -0
- package/src/api/messaging/removeUserFromGroup.js +62 -0
- package/src/{resolvePhotoUrl.js → api/messaging/resolvePhotoUrl.js} +11 -15
- package/src/api/messaging/scheduler.js +264 -0
- package/src/{searchForThread.js → api/messaging/searchForThread.js} +12 -12
- package/src/api/messaging/sendBroadcast.js +93 -0
- package/src/api/messaging/sendMessage.js +269 -0
- package/src/api/messaging/sendTypingIndicator.js +90 -0
- package/src/api/messaging/sessionGuard.js +130 -0
- package/src/api/messaging/setMessageReaction.js +114 -0
- package/src/api/messaging/setTitle.js +124 -0
- package/src/api/messaging/shareContact.js +98 -0
- package/src/{threadColors.js → api/messaging/threadColors.js} +2 -5
- package/src/api/messaging/unsendMessage.js +105 -0
- package/src/api/messaging/uploadAttachment.js +493 -0
- package/src/api/socket/OldMessage.js +199 -0
- package/src/api/socket/core/connectMqtt.js +304 -0
- package/src/api/socket/core/emitAuth.js +95 -0
- package/src/api/socket/core/getSeqID.js +331 -0
- package/src/api/socket/core/getTaskResponseData.js +25 -0
- package/src/api/socket/core/lifecycle.js +117 -0
- package/src/api/socket/core/parseDelta.js +387 -0
- package/src/api/socket/detail/buildStream.js +215 -0
- package/src/api/socket/detail/constants.js +28 -0
- package/src/api/socket/e2ee/crypto.js +173 -0
- package/src/api/socket/e2ee/index.js +977 -0
- package/src/api/socket/e2ee/localMediaServer.js +59 -0
- package/src/api/socket/e2ee/mediaDecode.js +155 -0
- package/src/api/socket/e2ee/native/NOTICE.md +29 -0
- package/{lib → src/api/socket/e2ee/native/lib}/index.mjs +109 -66
- package/src/api/socket/e2ee/native/nativeMediaBridge.js +273 -0
- package/src/api/socket/e2ee/proto/ArmadilloApplication.proto +281 -0
- package/src/api/socket/e2ee/proto/ArmadilloICDC.proto +14 -0
- package/src/api/socket/e2ee/proto/ConsumerApplication.proto +232 -0
- package/src/api/socket/e2ee/proto/MessageApplication.proto +82 -0
- package/src/api/socket/e2ee/proto/MessageTransport.proto +77 -0
- package/src/api/socket/e2ee/proto/WACommon.proto +66 -0
- package/src/api/socket/e2ee/proto/WAMediaTransport.proto +176 -0
- package/src/api/socket/e2ee/proto/proto-writer.ts +76 -0
- package/src/api/socket/e2ee/protocol.js +196 -0
- package/src/api/socket/e2ee/ratchet.js +219 -0
- package/src/api/socket/e2ee/store.js +182 -0
- package/src/api/socket/e2ee/vendor/fme/dist/index.cjs +6477 -0
- package/src/api/socket/e2ee/vendor/fme/proto/ArmadilloApplication.proto +281 -0
- package/src/api/socket/e2ee/vendor/fme/proto/ArmadilloICDC.proto +14 -0
- package/src/api/socket/e2ee/vendor/fme/proto/ConsumerApplication.proto +232 -0
- package/src/api/socket/e2ee/vendor/fme/proto/MessageApplication.proto +82 -0
- package/src/api/socket/e2ee/vendor/fme/proto/MessageTransport.proto +77 -0
- package/src/api/socket/e2ee/vendor/fme/proto/WACommon.proto +66 -0
- package/src/api/socket/e2ee/vendor/fme/proto/WAMediaTransport.proto +176 -0
- package/src/api/socket/listenE2EE.js +87 -0
- package/src/api/socket/listenMqtt.js +499 -0
- package/src/api/socket/middleware/index.js +216 -0
- package/src/api/socket/sendMessage.js +331 -0
- package/src/api/socket/sendMessageMqtt.js +69 -0
- package/src/{getThreadHistory.js → api/threads/getThreadHistory.js} +114 -132
- package/src/api/threads/getThreadInfo.js +329 -0
- package/src/api/threads/getThreadList.js +293 -0
- package/src/api/threads/getThreadPictures.js +78 -0
- package/src/{getUserID.js → api/users/getUserID.js} +22 -18
- package/src/api/users/getUserInfo.js +402 -0
- package/src/api/users/getUserInfoV2.js +134 -0
- package/src/app/MessengerBot.js +209 -0
- package/src/app/MessengerContext.js +32 -0
- package/src/app/createFcaClient.js +136 -0
- package/src/app/threadInfoRealtimeSync.js +284 -0
- package/src/core/sendReqMqtt.js +96 -0
- package/src/database/helpers.js +53 -0
- package/src/database/models/index.js +88 -0
- package/src/database/models/thread.js +50 -0
- package/src/database/models/user.js +46 -0
- package/src/database/threadData.js +94 -0
- package/src/database/userData.js +98 -0
- package/src/remote/remoteClient.js +123 -0
- package/src/utils/antiSuspension.js +219 -0
- package/src/utils/broadcast.js +51 -0
- package/src/utils/client.js +10 -0
- package/src/utils/constants.js +23 -0
- package/src/utils/cookies.js +85 -0
- package/src/utils/fingerprint.js +110 -0
- package/src/utils/format/attachment.js +357 -0
- package/src/utils/format/cookie.js +9 -0
- package/src/utils/format/date.js +50 -0
- package/src/utils/format/decode.js +44 -0
- package/src/utils/format/delta.js +195 -0
- package/src/utils/format/ids.js +64 -0
- package/src/utils/format/index.js +64 -0
- package/src/utils/format/message.js +88 -0
- package/src/utils/format/presence.js +132 -0
- package/src/utils/format/readTyp.js +44 -0
- package/src/utils/format/thread.js +42 -0
- package/src/utils/format/utils.js +141 -0
- package/src/utils/headers.js +125 -0
- package/src/utils/humanizer.js +256 -0
- package/src/utils/loginParser/autoLogin.js +125 -0
- package/src/utils/loginParser/extractDtsg.js +44 -0
- package/src/utils/loginParser/helpers.js +43 -0
- package/src/utils/loginParser/index.js +10 -0
- package/src/utils/loginParser/parseAndCheckLogin.js +241 -0
- package/src/utils/loginParser/textUtils.js +28 -0
- package/src/utils/nexca-logger.js +144 -0
- package/src/utils/nexca-utils.js +687 -0
- package/src/utils/request/client.js +26 -0
- package/src/utils/request/config.js +23 -0
- package/src/utils/request/defaults.js +46 -0
- package/src/utils/request/helpers.js +46 -0
- package/src/utils/request/index.js +17 -0
- package/src/utils/request/methods.js +163 -0
- package/src/utils/request/proxy.js +21 -0
- package/src/utils/request/retry.js +77 -0
- package/src/utils/request/sanitize.js +49 -0
- package/src/utils/typingIndicator.js +202 -0
- package/test/helpers/stub-modules.js +122 -0
- package/test/integration/logout.test.js +69 -0
- package/test/integration/mqtt-lifecycle.test.js +195 -0
- package/test/integration/package.test.js +116 -0
- package/test/integration/typing-wiring.test.js +71 -0
- package/test/unit/fingerprint.test.js +19 -0
- package/test/unit/humanizer.test.js +32 -0
- package/test/unit/lifecycle.test.js +92 -0
- package/test/unit/parsers.test.js +43 -0
- package/test/unit/typing.test.js +136 -0
- package/ANALYSIS.md +0 -31
- package/AUDIT_REPORT.md +0 -57
- package/advancedSystem.js +0 -95
- package/checkUpdate.js +0 -47
- package/config.json +0 -51
- package/e2ee.js +0 -738
- package/examples/basic-bot.js +0 -122
- package/examples/e2ee-bot.js +0 -141
- package/fca-config.example.json +0 -73
- package/scripts/check.js +0 -38
- package/src/OldMessage.js +0 -357
- package/src/addUserToGroup.js +0 -117
- package/src/changeAdminStatus.js +0 -105
- package/src/changeAvatarV2.js +0 -86
- package/src/changeAvt.js +0 -85
- package/src/changeBlockedStatusMqtt.js +0 -75
- package/src/changeCover.js +0 -73
- package/src/changeGroupImage.js +0 -137
- package/src/changeName.js +0 -79
- package/src/changeNickname.js +0 -61
- package/src/changeThreadColor.js +0 -67
- package/src/changeThreadEmoji.js +0 -57
- package/src/changeUsername.js +0 -59
- package/src/createCommentPost.js +0 -232
- package/src/createPoll.js +0 -73
- package/src/createPost.js +0 -276
- package/src/deleteMessage.js +0 -58
- package/src/editMessage.js +0 -76
- package/src/editMessageOld.js +0 -62
- package/src/follow.js +0 -74
- package/src/forwardAttachment.js +0 -62
- package/src/friendList.js +0 -104
- package/src/getAccess.js +0 -112
- package/src/getAvatarUser.js +0 -78
- package/src/getBotInitialData.js +0 -42
- package/src/getCtx.js +0 -5
- package/src/getOptions.js +0 -5
- package/src/getRegion.js +0 -7
- package/src/getThreadHistoryDeprecated.js +0 -71
- package/src/getThreadInfo.js +0 -232
- package/src/getThreadInfoDeprecated.js +0 -56
- package/src/getThreadList.js +0 -213
- package/src/getThreadListDeprecated.js +0 -46
- package/src/getThreadPictures.js +0 -59
- package/src/getThreadTheme.js +0 -81
- package/src/getUID.js +0 -119
- package/src/getUserInfo.js +0 -66
- package/src/handleFriendRequest.js +0 -46
- package/src/handleMessageRequest.js +0 -47
- package/src/httpGet.js +0 -49
- package/src/httpPost.js +0 -48
- package/src/httpPostFormData.js +0 -70
- package/src/listenMqtt.js +0 -1081
- package/src/listenNotification.js +0 -85
- package/src/logout.js +0 -18
- package/src/markAsDelivered.js +0 -47
- package/src/markAsRead.js +0 -72
- package/src/markAsReadAll.js +0 -40
- package/src/markAsSeen.js +0 -48
- package/src/metaTheme.js +0 -189
- package/src/muteThread.js +0 -45
- package/src/note.js +0 -228
- package/src/pinMessage.js +0 -54
- package/src/refreshFb_dtsg.js +0 -49
- package/src/removeSuspiciousAccount.js +0 -78
- package/src/removeUserFromGroup.js +0 -81
- package/src/reply.js +0 -442
- package/src/searchFriends.js +0 -140
- package/src/searchStickers.js +0 -53
- package/src/send.js +0 -46
- package/src/sendButtons.js +0 -163
- package/src/sendComment.js +0 -159
- package/src/sendFriendRequest.js +0 -112
- package/src/sendMessage.js +0 -441
- package/src/sendMessageMqtt.js +0 -323
- package/src/sendTypingIndicator.js +0 -68
- package/src/sendTypingIndicatorV2.js +0 -22
- package/src/setActiveStatus.js +0 -92
- package/src/setMessageReaction.js +0 -150
- package/src/setMessageReactionMqtt.js +0 -104
- package/src/setMessageReactionSafe.js +0 -44
- package/src/setProfileGuard.js +0 -44
- package/src/setProfileLock.js +0 -97
- package/src/setStoryReaction.js +0 -133
- package/src/setStorySeen.js +0 -108
- package/src/setThreadTheme.js +0 -102
- package/src/setTitle.js +0 -92
- package/src/shareContact.js +0 -110
- package/src/shareLink.js +0 -59
- package/src/stopListenMqtt.js +0 -60
- package/src/storyManager.js +0 -357
- package/src/suggestFriend.js +0 -132
- package/src/unsendMessage.js +0 -68
- package/src/uploadAttachment.js +0 -115
- package/test/fixes-1_2_4.test.js +0 -118
- package/test/mqtt-stop.test.js +0 -32
- package/test/reaction-mqtt.test.js +0 -57
- package/utils.js +0 -3056
- /package/{build → src/api/socket/e2ee/native/build}/messagix.dll +0 -0
- /package/{build → src/api/socket/e2ee/native/build}/messagix.so +0 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const logger = require("../../../../func/logger");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Middleware system for filtering and processing events before they are emitted
|
|
6
|
+
*
|
|
7
|
+
* Middleware functions receive (event, next) where:
|
|
8
|
+
* - event: The event object (can be modified)
|
|
9
|
+
* - next: Function to call to continue to next middleware
|
|
10
|
+
* - next() - continue to next middleware
|
|
11
|
+
* - next(false) or next(null) - stop processing, don't emit event
|
|
12
|
+
* - next(error) - emit error instead
|
|
13
|
+
*/
|
|
14
|
+
module.exports = function createMiddlewareSystem() {
|
|
15
|
+
const middlewareStack = [];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Add middleware to the stack
|
|
19
|
+
* @param {Function|string} middleware - Middleware function or name for named middleware
|
|
20
|
+
* @param {Function} [fn] - Middleware function (if first param is name)
|
|
21
|
+
* @returns {Function} Unsubscribe function
|
|
22
|
+
*/
|
|
23
|
+
function use(middleware, fn) {
|
|
24
|
+
let middlewareFn, name;
|
|
25
|
+
|
|
26
|
+
if (typeof middleware === "string" && typeof fn === "function") {
|
|
27
|
+
name = middleware;
|
|
28
|
+
middlewareFn = fn;
|
|
29
|
+
} else if (typeof middleware === "function") {
|
|
30
|
+
middlewareFn = middleware;
|
|
31
|
+
name = `middleware_${middlewareStack.length}`;
|
|
32
|
+
} else {
|
|
33
|
+
throw new Error("Middleware must be a function or (name, function)");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const wrapped = {
|
|
37
|
+
name,
|
|
38
|
+
fn: middlewareFn,
|
|
39
|
+
enabled: true
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
middlewareStack.push(wrapped);
|
|
43
|
+
logger(`Middleware "${name}" added`, "info");
|
|
44
|
+
|
|
45
|
+
// Return unsubscribe function
|
|
46
|
+
return function remove() {
|
|
47
|
+
const index = middlewareStack.indexOf(wrapped);
|
|
48
|
+
if (index !== -1) {
|
|
49
|
+
middlewareStack.splice(index, 1);
|
|
50
|
+
logger(`Middleware "${name}" removed`, "info");
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Remove middleware by name or function
|
|
57
|
+
* @param {string|Function} identifier - Name or function to remove
|
|
58
|
+
* @returns {boolean} True if removed
|
|
59
|
+
*/
|
|
60
|
+
function remove(identifier) {
|
|
61
|
+
if (typeof identifier === "string") {
|
|
62
|
+
const index = middlewareStack.findIndex(m => m.name === identifier);
|
|
63
|
+
if (index !== -1) {
|
|
64
|
+
const removed = middlewareStack.splice(index, 1)[0];
|
|
65
|
+
logger(`Middleware "${removed.name}" removed`, "info");
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
} else if (typeof identifier === "function") {
|
|
70
|
+
const index = middlewareStack.findIndex(m => m.fn === identifier);
|
|
71
|
+
if (index !== -1) {
|
|
72
|
+
const removed = middlewareStack.splice(index, 1)[0];
|
|
73
|
+
logger(`Middleware "${removed.name}" removed`, "info");
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Remove all middleware
|
|
83
|
+
*/
|
|
84
|
+
function clear() {
|
|
85
|
+
const count = middlewareStack.length;
|
|
86
|
+
middlewareStack.length = 0;
|
|
87
|
+
logger(`All middleware cleared (${count} removed)`, "info");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get list of middleware names
|
|
92
|
+
* @returns {string[]} Array of middleware names
|
|
93
|
+
*/
|
|
94
|
+
function list() {
|
|
95
|
+
return middlewareStack.filter(m => m.enabled).map(m => m.name);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Enable/disable middleware by name
|
|
100
|
+
* @param {string} name - Middleware name
|
|
101
|
+
* @param {boolean} enabled - Enable or disable
|
|
102
|
+
* @returns {boolean} True if found and updated
|
|
103
|
+
*/
|
|
104
|
+
function setEnabled(name, enabled) {
|
|
105
|
+
const middleware = middlewareStack.find(m => m.name === name);
|
|
106
|
+
if (middleware) {
|
|
107
|
+
middleware.enabled = enabled;
|
|
108
|
+
logger(`Middleware "${name}" ${enabled ? "enabled" : "disabled"}`, "info");
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Process event through middleware stack
|
|
116
|
+
* @param {*} event - Event object
|
|
117
|
+
* @param {Function} finalCallback - Callback to call after all middleware
|
|
118
|
+
* @returns {Promise} Promise that resolves when processing is complete
|
|
119
|
+
*/
|
|
120
|
+
function process(event, finalCallback) {
|
|
121
|
+
if (!middlewareStack.length) {
|
|
122
|
+
return finalCallback(null, event);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let index = 0;
|
|
126
|
+
const enabledMiddleware = middlewareStack.filter(m => m.enabled);
|
|
127
|
+
|
|
128
|
+
function next(err) {
|
|
129
|
+
// Error occurred, stop processing
|
|
130
|
+
if (err && err !== false && err !== null) {
|
|
131
|
+
return finalCallback(err, null);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Explicitly stopped (next(false) or next(null))
|
|
135
|
+
if (err === false || err === null) {
|
|
136
|
+
return finalCallback(null, null); // null event means don't emit
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// No more middleware, call final callback
|
|
140
|
+
if (index >= enabledMiddleware.length) {
|
|
141
|
+
return finalCallback(null, event);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Get next middleware
|
|
145
|
+
const middleware = enabledMiddleware[index++];
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
// Call middleware with event and next
|
|
149
|
+
const result = middleware.fn(event, next);
|
|
150
|
+
|
|
151
|
+
// If middleware returns a promise, handle it
|
|
152
|
+
if (result && typeof result.then === "function") {
|
|
153
|
+
result
|
|
154
|
+
.then(() => next())
|
|
155
|
+
.catch(err => next(err));
|
|
156
|
+
} else if (result === false || result === null) {
|
|
157
|
+
// Middleware returned false/null, stop processing
|
|
158
|
+
finalCallback(null, null);
|
|
159
|
+
}
|
|
160
|
+
// If middleware called next() synchronously, it will continue
|
|
161
|
+
} catch (err) {
|
|
162
|
+
logger(`Middleware "${middleware.name}" error: ${err && err.message ? err.message : String(err)}`, "error");
|
|
163
|
+
next(err);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Start processing
|
|
168
|
+
next();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Wrap a callback with middleware processing
|
|
173
|
+
* @param {Function} callback - Original callback (err, event)
|
|
174
|
+
* @returns {Function} Wrapped callback
|
|
175
|
+
*/
|
|
176
|
+
function wrapCallback(callback) {
|
|
177
|
+
return function wrappedCallback(err, event) {
|
|
178
|
+
if (err) {
|
|
179
|
+
// Errors bypass middleware
|
|
180
|
+
return callback(err, null);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (!event) {
|
|
184
|
+
return callback(null, null);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Process event through middleware
|
|
188
|
+
process(event, (middlewareErr, processedEvent) => {
|
|
189
|
+
if (middlewareErr) {
|
|
190
|
+
return callback(middlewareErr, null);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// If processedEvent is null, middleware blocked the event
|
|
194
|
+
if (processedEvent === null) {
|
|
195
|
+
return; // Don't emit
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Emit processed event
|
|
199
|
+
callback(null, processedEvent);
|
|
200
|
+
});
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
use,
|
|
206
|
+
remove,
|
|
207
|
+
clear,
|
|
208
|
+
list,
|
|
209
|
+
setEnabled,
|
|
210
|
+
process,
|
|
211
|
+
wrapCallback,
|
|
212
|
+
get count() {
|
|
213
|
+
return middlewareStack.filter(m => m.enabled).length;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
};
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var utils = require("../../utils/nexca-utils");
|
|
4
|
+
var logger = require("../../utils/nexca-logger");
|
|
5
|
+
var { globalAntiSuspension } = require("../../utils/antiSuspension");
|
|
6
|
+
|
|
7
|
+
var ALLOWED = {
|
|
8
|
+
attachment: true, url: true, sticker: true, emoji: true,
|
|
9
|
+
emojiSize: true, body: true, mentions: true, location: true,
|
|
10
|
+
replyToMessage: true, forwardAttachmentIds: true
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
var EMOJI_SIZES = { small: 1, medium: 2, large: 3 };
|
|
14
|
+
|
|
15
|
+
function toEmojiSize(size) {
|
|
16
|
+
if (typeof size === "number" && !isNaN(size)) return Math.min(3, Math.max(1, size));
|
|
17
|
+
if (typeof size === "string" && size in EMOJI_SIZES) return EMOJI_SIZES[size];
|
|
18
|
+
return 1;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function hasLinks(text) {
|
|
22
|
+
return /(https?:\/\/|www\.|t\.me\/|fb\.me\/|youtu\.be\/|facebook\.com\/|youtube\.com\/)/i.test(text);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function buildMentionData(msg, baseBody) {
|
|
26
|
+
if (!Array.isArray(msg.mentions) || !msg.mentions.length) return null;
|
|
27
|
+
var ids = [], offsets = [], lengths = [], types = [];
|
|
28
|
+
for (var i = 0; i < msg.mentions.length; i++) {
|
|
29
|
+
var mention = msg.mentions[i];
|
|
30
|
+
// Ensure tag always has @ prefix — Facebook counts @ in both offset and length
|
|
31
|
+
var tag = String(mention.tag || "");
|
|
32
|
+
if (tag && !tag.startsWith("@")) tag = "@" + tag;
|
|
33
|
+
var fromIndex = Number.isInteger(mention.fromIndex) ? mention.fromIndex : 0;
|
|
34
|
+
var offset = baseBody.indexOf(tag, fromIndex);
|
|
35
|
+
if (offset === -1) {
|
|
36
|
+
// Fallback: search for bare name without @
|
|
37
|
+
offset = baseBody.indexOf(tag.slice(1), fromIndex);
|
|
38
|
+
}
|
|
39
|
+
if (offset < 0) offset = 0;
|
|
40
|
+
ids.push(String(mention.id || 0));
|
|
41
|
+
offsets.push(offset);
|
|
42
|
+
lengths.push(tag.length); // includes @ — matches Facebook's expectation
|
|
43
|
+
types.push("p");
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
mention_ids: ids.join(","),
|
|
47
|
+
mention_offsets: offsets.join(","),
|
|
48
|
+
mention_lengths: lengths.join(","),
|
|
49
|
+
mention_types: types.join(",")
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function extractIdsFromPayload(payload) {
|
|
54
|
+
var messageID = null, threadID = null;
|
|
55
|
+
function walk(node) {
|
|
56
|
+
if (!Array.isArray(node)) return;
|
|
57
|
+
if (node[0] === 5 && (node[1] === "replaceOptimsiticMessage" || node[1] === "replaceOptimisticMessage")) {
|
|
58
|
+
messageID = String(node[3]);
|
|
59
|
+
}
|
|
60
|
+
if (node[0] === 5 && node[1] === "writeCTAIdToThreadsTable") {
|
|
61
|
+
var candidate = node[2];
|
|
62
|
+
if (Array.isArray(candidate) && candidate[0] === 19) threadID = String(candidate[1]);
|
|
63
|
+
}
|
|
64
|
+
for (var i = 0; i < node.length; i++) walk(node[i]);
|
|
65
|
+
}
|
|
66
|
+
try { walk(payload && payload.step); } catch (_) { }
|
|
67
|
+
return { threadID, messageID };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function publishLsRequestWithAck(mqttClient, content, requestId, timeout) {
|
|
71
|
+
timeout = timeout || 15000;
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
var timer = setTimeout(() => {
|
|
74
|
+
mqttClient.removeListener('message', onMessage);
|
|
75
|
+
reject(new Error('MQTT sendMessage timed out after ' + timeout + 'ms'));
|
|
76
|
+
}, timeout);
|
|
77
|
+
|
|
78
|
+
function onMessage(topic, message) {
|
|
79
|
+
if (topic !== '/ls_resp') return;
|
|
80
|
+
try {
|
|
81
|
+
var data = JSON.parse(message.toString());
|
|
82
|
+
if (String(data.request_id) === String(requestId)) {
|
|
83
|
+
clearTimeout(timer);
|
|
84
|
+
mqttClient.removeListener('message', onMessage);
|
|
85
|
+
var extracted = extractIdsFromPayload(data.payload ? JSON.parse(data.payload) : {});
|
|
86
|
+
resolve({ threadID: extracted.threadID, messageID: extracted.messageID });
|
|
87
|
+
}
|
|
88
|
+
} catch (_) { }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
mqttClient.on('message', onMessage);
|
|
92
|
+
mqttClient.publish('/ls_req', JSON.stringify(content), { qos: 1 }, err => {
|
|
93
|
+
if (err) {
|
|
94
|
+
clearTimeout(timer);
|
|
95
|
+
mqttClient.removeListener('message', onMessage);
|
|
96
|
+
reject(err);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
103
|
+
var uploadAttachmentFn = require('../messaging/uploadAttachment')(defaultFuncs, api, ctx);
|
|
104
|
+
|
|
105
|
+
async function uploadAttachments(attachments) {
|
|
106
|
+
if (!Array.isArray(attachments)) attachments = [attachments];
|
|
107
|
+
return uploadAttachmentFn(attachments);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function sendViaMqtt(msg, threadID, replyToMessage) {
|
|
111
|
+
var mqttClient = ctx.mqttClient || global.mqttClient;
|
|
112
|
+
if (!mqttClient) throw new Error('MQTT client not available');
|
|
113
|
+
|
|
114
|
+
var baseBody = msg.body != null ? String(msg.body) : "";
|
|
115
|
+
var requestId = Math.floor(100 + Math.random() * 900);
|
|
116
|
+
var epoch = (BigInt(Date.now()) << 22n).toString();
|
|
117
|
+
|
|
118
|
+
var payload0 = {
|
|
119
|
+
thread_id: String(threadID),
|
|
120
|
+
otid: utils.generateOfflineThreadingID(),
|
|
121
|
+
source: 2097153,
|
|
122
|
+
send_type: 1,
|
|
123
|
+
sync_group: 1,
|
|
124
|
+
mark_thread_read: 1,
|
|
125
|
+
text: baseBody === "" ? null : baseBody,
|
|
126
|
+
initiating_source: 0,
|
|
127
|
+
skip_url_preview_gen: 1,
|
|
128
|
+
text_has_links: hasLinks(baseBody) ? 1 : 0,
|
|
129
|
+
multitab_env: 0,
|
|
130
|
+
metadata_dataclass: JSON.stringify({ media_accessibility_metadata: { alt_text: null } })
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
var mentionData = buildMentionData(msg, baseBody);
|
|
134
|
+
if (mentionData) payload0.mention_data = mentionData;
|
|
135
|
+
|
|
136
|
+
if (msg.sticker) { payload0.send_type = 2; payload0.sticker_id = msg.sticker; }
|
|
137
|
+
if (msg.emoji) { payload0.send_type = 1; payload0.text = msg.emoji; payload0.hot_emoji_size = toEmojiSize(msg.emojiSize); }
|
|
138
|
+
|
|
139
|
+
if (msg.location && msg.location.latitude != null && msg.location.longitude != null) {
|
|
140
|
+
payload0.send_type = 1;
|
|
141
|
+
payload0.location_data = {
|
|
142
|
+
coordinates: { latitude: msg.location.latitude, longitude: msg.location.longitude },
|
|
143
|
+
is_current_location: Boolean(msg.location.current),
|
|
144
|
+
is_live_location: Boolean(msg.location.live)
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
var effectiveReplyTo = replyToMessage || msg.replyToMessage;
|
|
149
|
+
if (effectiveReplyTo) {
|
|
150
|
+
payload0.reply_metadata = {
|
|
151
|
+
reply_source_id: effectiveReplyTo,
|
|
152
|
+
reply_source_type: 1,
|
|
153
|
+
reply_type: 0
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (msg.attachment) {
|
|
158
|
+
payload0.send_type = 3;
|
|
159
|
+
if (payload0.text === "") payload0.text = null;
|
|
160
|
+
payload0.attachment_fbids = [];
|
|
161
|
+
var list = Array.isArray(msg.attachment) ? msg.attachment : [msg.attachment];
|
|
162
|
+
var preuploaded = [], toUpload = [];
|
|
163
|
+
for (var item of list) {
|
|
164
|
+
if (Array.isArray(item) && item.length >= 2 && typeof item[0] === "string") {
|
|
165
|
+
preuploaded.push(String(item[1]));
|
|
166
|
+
} else if (utils.isReadableStream(item)) {
|
|
167
|
+
toUpload.push(item);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (preuploaded.length) payload0.attachment_fbids = payload0.attachment_fbids.concat(preuploaded);
|
|
171
|
+
if (msg.forwardAttachmentIds && msg.forwardAttachmentIds.length) {
|
|
172
|
+
payload0.attachment_fbids = payload0.attachment_fbids.concat(msg.forwardAttachmentIds.map(String));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (toUpload.length) {
|
|
176
|
+
var uploaded = await uploadAttachments(toUpload);
|
|
177
|
+
for (var u of uploaded) {
|
|
178
|
+
if (!u) continue;
|
|
179
|
+
var fbid = u.image_id || u.video_id || u.audio_id || u.file_id || u.sticker_id || u.gif_id;
|
|
180
|
+
if (!fbid) {
|
|
181
|
+
var firstKey = Object.keys(u).find(function(k) { return u[k] && /^\d+$/.test(String(u[k])); });
|
|
182
|
+
if (firstKey) fbid = u[firstKey];
|
|
183
|
+
}
|
|
184
|
+
if (fbid) payload0.attachment_fbids.push(String(fbid));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (!payload0.attachment_fbids.length) delete payload0.attachment_fbids;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
var tasks = [
|
|
191
|
+
{
|
|
192
|
+
label: '46',
|
|
193
|
+
payload: JSON.stringify(payload0),
|
|
194
|
+
queue_name: String(threadID),
|
|
195
|
+
task_id: 400,
|
|
196
|
+
failure_count: null
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
label: '21',
|
|
200
|
+
payload: JSON.stringify({
|
|
201
|
+
thread_id: String(threadID),
|
|
202
|
+
last_read_watermark_ts: Date.now(),
|
|
203
|
+
sync_group: 1
|
|
204
|
+
}),
|
|
205
|
+
queue_name: String(threadID),
|
|
206
|
+
task_id: 401,
|
|
207
|
+
failure_count: null
|
|
208
|
+
}
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
var content = {
|
|
212
|
+
app_id: '2220391788200892',
|
|
213
|
+
payload: JSON.stringify({
|
|
214
|
+
tasks: tasks,
|
|
215
|
+
epoch_id: epoch,
|
|
216
|
+
version_id: '24804310205905615',
|
|
217
|
+
data_trace_id: '#' + Buffer.from(String(Math.random())).toString('base64').replace(/=+$/, '')
|
|
218
|
+
}),
|
|
219
|
+
request_id: requestId,
|
|
220
|
+
type: 3
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
return publishLsRequestWithAck(mqttClient, content, requestId, 15000);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return async function sendMessage(msg, threadID, callback, replyToMessage, isSingleUser) {
|
|
227
|
+
if (typeof msg === "string") msg = { body: msg };
|
|
228
|
+
if (typeof callback !== "function") { callback = null; }
|
|
229
|
+
|
|
230
|
+
var resolve, reject;
|
|
231
|
+
var promise = new Promise((res, rej) => { resolve = res; reject = rej; });
|
|
232
|
+
|
|
233
|
+
for (var key in msg) {
|
|
234
|
+
if (!ALLOWED[key]) {
|
|
235
|
+
var err = { error: "sendMessage: Unknown property '" + key + "'" };
|
|
236
|
+
if (callback) callback(err);
|
|
237
|
+
else reject(err);
|
|
238
|
+
return promise;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Auto-detect isSingleUser from ctx.threadTypes if not explicitly provided.
|
|
243
|
+
// parseDelta in listenMqtt.js populates ctx.threadTypes[senderID] = 'dm' | 'group'
|
|
244
|
+
if (isSingleUser === undefined && ctx.threadTypes) {
|
|
245
|
+
isSingleUser = ctx.threadTypes[String(threadID)] === 'dm';
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Rate-limit / pace / circuit-break outbound sends to avoid looking
|
|
249
|
+
// like automated bulk traffic to Facebook. Opt-out via
|
|
250
|
+
// globalOptions.antiBan === false; on by default. This never throws
|
|
251
|
+
// in normal operation (it only adds delay), the try/catch is
|
|
252
|
+
// defensive so a bug in here can never block a real send.
|
|
253
|
+
if (!ctx.globalOptions || ctx.globalOptions.antiBan !== false) {
|
|
254
|
+
try {
|
|
255
|
+
await globalAntiSuspension.prepareBeforeMessage(threadID, msg.body || "");
|
|
256
|
+
} catch (err) {
|
|
257
|
+
logger("AntiSuspension prepareBeforeMessage error: " + (err && err.message ? err.message : err), "warn");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// DM sends on E2EE threads — skip MQTT entirely, always.
|
|
262
|
+
// Facebook does not deliver plaintext MQTT bodies into an E2EE (Signal Protocol)
|
|
263
|
+
// thread — this applies to TEXT replies just as much as attachments. Previously
|
|
264
|
+
// only attachment sends were routed through the E2EE bridge, so every plain-text
|
|
265
|
+
// bot reply inside an E2EE DM silently vanished (sent over MQTT, never delivered).
|
|
266
|
+
// Now: if the DM is E2EE-connected, ALL sends (text or attachment) go through the
|
|
267
|
+
// Noise WebSocket / Signal Protocol bridge. Only non-E2EE DM attachments fall back
|
|
268
|
+
// to OldMessage; everything else falls through to the normal MQTT path below.
|
|
269
|
+
var useE2EE = isSingleUser && api.e2ee && typeof api.e2ee.isConnected === "function" && api.e2ee.isConnected();
|
|
270
|
+
var useE2EEGroup = !isSingleUser && api.e2ee && typeof api.e2ee.isKnownE2EEGroup === "function" &&
|
|
271
|
+
api.e2ee.isKnownE2EEGroup(String(threadID)) && typeof api.e2ee.isConnected === "function" && api.e2ee.isConnected();
|
|
272
|
+
useE2EE = useE2EE || useE2EEGroup;
|
|
273
|
+
|
|
274
|
+
if (useE2EE) {
|
|
275
|
+
try {
|
|
276
|
+
var e2eeResult = await api.e2ee.sendMessage(String(threadID), msg, replyToMessage);
|
|
277
|
+
var wrapped = e2eeResult && e2eeResult.messageId
|
|
278
|
+
? { threadID: String(threadID), messageID: String(e2eeResult.messageId) }
|
|
279
|
+
: e2eeResult;
|
|
280
|
+
if (callback) callback(null, wrapped);
|
|
281
|
+
else resolve(wrapped);
|
|
282
|
+
} catch (e2eeErr) {
|
|
283
|
+
globalAntiSuspension.checkAccountHealth(e2eeErr);
|
|
284
|
+
logger.error("sendMessage", "E2EE DM send failed: " + (e2eeErr.message || e2eeErr));
|
|
285
|
+
if (callback) callback(e2eeErr);
|
|
286
|
+
else reject(e2eeErr);
|
|
287
|
+
}
|
|
288
|
+
return promise;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (isSingleUser && msg.attachment) {
|
|
292
|
+
// Non-E2EE DM with attachment.
|
|
293
|
+
// /messaging/send/ with other_user_fbid routing works for plain DMs.
|
|
294
|
+
try {
|
|
295
|
+
var omResult = await new Promise((res2, rej2) => {
|
|
296
|
+
api.OldMessage(msg, threadID, (err2, data2) => err2 ? rej2(err2) : res2(data2), replyToMessage, true);
|
|
297
|
+
});
|
|
298
|
+
if (callback) callback(null, omResult);
|
|
299
|
+
else resolve(omResult);
|
|
300
|
+
} catch (omErr) {
|
|
301
|
+
globalAntiSuspension.checkAccountHealth(omErr);
|
|
302
|
+
logger.error("sendMessage", "DM attachment via OldMessage failed: " + (omErr.error || omErr.message || omErr));
|
|
303
|
+
if (callback) callback(omErr);
|
|
304
|
+
else reject(omErr);
|
|
305
|
+
}
|
|
306
|
+
return promise;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
try {
|
|
310
|
+
var result = await sendViaMqtt(msg, threadID, replyToMessage);
|
|
311
|
+
if (callback) callback(null, result);
|
|
312
|
+
else resolve(result);
|
|
313
|
+
} catch (mqttErr) {
|
|
314
|
+
logger.warn("sendMessage", "MQTT failed, falling back to OldMessage: " + (mqttErr.message || mqttErr));
|
|
315
|
+
try {
|
|
316
|
+
var fbResult = await new Promise((res2, rej2) => {
|
|
317
|
+
api.OldMessage(msg, threadID, (err2, data2) => err2 ? rej2(err2) : res2(data2), replyToMessage, isSingleUser);
|
|
318
|
+
});
|
|
319
|
+
if (callback) callback(null, fbResult);
|
|
320
|
+
else resolve(fbResult);
|
|
321
|
+
} catch (fbErr) {
|
|
322
|
+
globalAntiSuspension.checkAccountHealth(fbErr);
|
|
323
|
+
logger.error("sendMessage", fbErr.error || fbErr.message || fbErr);
|
|
324
|
+
if (callback) callback(fbErr);
|
|
325
|
+
else reject(fbErr);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return promise;
|
|
330
|
+
};
|
|
331
|
+
};
|
|
@@ -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
|
+
};
|