bb-fca 2.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/LICENSE-MIT +21 -0
- package/README.md +0 -0
- package/dist/core/client.js +50 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/models/buildAPI.js +103 -0
- package/dist/core/models/buildAPI.js.map +1 -0
- package/dist/core/models/loginHelper.js +209 -0
- package/dist/core/models/loginHelper.js.map +1 -0
- package/dist/core/models/setOptions.js +47 -0
- package/dist/core/models/setOptions.js.map +1 -0
- package/dist/deltas/apis/create.js +30 -0
- package/dist/deltas/apis/create.js.map +1 -0
- package/dist/deltas/apis/extra/addExternalModule.js +23 -0
- package/dist/deltas/apis/extra/addExternalModule.js.map +1 -0
- package/dist/deltas/apis/extra/getAccess.js +110 -0
- package/dist/deltas/apis/extra/getAccess.js.map +1 -0
- package/dist/deltas/apis/http/httpGet.js +57 -0
- package/dist/deltas/apis/http/httpGet.js.map +1 -0
- package/dist/deltas/apis/http/httpPost.js +57 -0
- package/dist/deltas/apis/http/httpPost.js.map +1 -0
- package/dist/deltas/apis/http/httpPostFormData.js +61 -0
- package/dist/deltas/apis/http/httpPostFormData.js.map +1 -0
- package/dist/deltas/apis/login/GetBotInfo.js +83 -0
- package/dist/deltas/apis/login/GetBotInfo.js.map +1 -0
- package/dist/deltas/apis/login/getBotInitialData.js +46 -0
- package/dist/deltas/apis/login/getBotInitialData.js.map +1 -0
- package/dist/deltas/apis/login/logout.js +54 -0
- package/dist/deltas/apis/login/logout.js.map +1 -0
- package/dist/deltas/apis/messaging/editMessage.js +64 -0
- package/dist/deltas/apis/messaging/editMessage.js.map +1 -0
- package/dist/deltas/apis/messaging/emoji.js +120 -0
- package/dist/deltas/apis/messaging/emoji.js.map +1 -0
- package/dist/deltas/apis/messaging/gcmember.js +164 -0
- package/dist/deltas/apis/messaging/gcmember.js.map +1 -0
- package/dist/deltas/apis/messaging/gcname.js +119 -0
- package/dist/deltas/apis/messaging/gcname.js.map +1 -0
- package/dist/deltas/apis/messaging/gcrule.js +144 -0
- package/dist/deltas/apis/messaging/gcrule.js.map +1 -0
- package/dist/deltas/apis/messaging/markAsDelivered.js +44 -0
- package/dist/deltas/apis/messaging/markAsDelivered.js.map +1 -0
- package/dist/deltas/apis/messaging/markAsRead.js +84 -0
- package/dist/deltas/apis/messaging/markAsRead.js.map +1 -0
- package/dist/deltas/apis/messaging/markAsReadAll.js +34 -0
- package/dist/deltas/apis/messaging/markAsReadAll.js.map +1 -0
- package/dist/deltas/apis/messaging/markAsSeen.js +64 -0
- package/dist/deltas/apis/messaging/markAsSeen.js.map +1 -0
- package/dist/deltas/apis/messaging/nickname.js +129 -0
- package/dist/deltas/apis/messaging/nickname.js.map +1 -0
- package/dist/deltas/apis/messaging/notes.js +156 -0
- package/dist/deltas/apis/messaging/notes.js.map +1 -0
- package/dist/deltas/apis/messaging/resolvePhotoUrl.js +55 -0
- package/dist/deltas/apis/messaging/resolvePhotoUrl.js.map +1 -0
- package/dist/deltas/apis/messaging/sendMessage.js +239 -0
- package/dist/deltas/apis/messaging/sendMessage.js.map +1 -0
- package/dist/deltas/apis/messaging/sendTypingIndicator.js +41 -0
- package/dist/deltas/apis/messaging/sendTypingIndicator.js.map +1 -0
- package/dist/deltas/apis/messaging/setMessageReaction.js +30 -0
- package/dist/deltas/apis/messaging/setMessageReaction.js.map +1 -0
- package/dist/deltas/apis/messaging/shareContact.js +59 -0
- package/dist/deltas/apis/messaging/shareContact.js.map +1 -0
- package/dist/deltas/apis/messaging/stickers.js +246 -0
- package/dist/deltas/apis/messaging/stickers.js.map +1 -0
- package/dist/deltas/apis/messaging/theme.js +227 -0
- package/dist/deltas/apis/messaging/theme.js.map +1 -0
- package/dist/deltas/apis/messaging/unsendMessage.js +19 -0
- package/dist/deltas/apis/messaging/unsendMessage.js.map +1 -0
- package/dist/deltas/apis/mqtt/deltas/value.js +193 -0
- package/dist/deltas/apis/mqtt/deltas/value.js.map +1 -0
- package/dist/deltas/apis/mqtt/listenMqtt.js +306 -0
- package/dist/deltas/apis/mqtt/listenMqtt.js.map +1 -0
- package/dist/deltas/apis/mqtt/listenSpeed.js +166 -0
- package/dist/deltas/apis/mqtt/listenSpeed.js.map +1 -0
- package/dist/deltas/apis/mqtt/pinMessage.js +166 -0
- package/dist/deltas/apis/mqtt/pinMessage.js.map +1 -0
- package/dist/deltas/apis/mqtt/realtime.js +160 -0
- package/dist/deltas/apis/mqtt/realtime.js.map +1 -0
- package/dist/deltas/apis/mqtt/sendMessageMqtt.js +184 -0
- package/dist/deltas/apis/mqtt/sendMessageMqtt.js.map +1 -0
- package/dist/deltas/apis/mqtt/setMessageReactionMqtt.js +57 -0
- package/dist/deltas/apis/mqtt/setMessageReactionMqtt.js.map +1 -0
- package/dist/deltas/apis/posting/comment.js +195 -0
- package/dist/deltas/apis/posting/comment.js.map +1 -0
- package/dist/deltas/apis/posting/follow.js +82 -0
- package/dist/deltas/apis/posting/follow.js.map +1 -0
- package/dist/deltas/apis/posting/friend.js +253 -0
- package/dist/deltas/apis/posting/friend.js.map +1 -0
- package/dist/deltas/apis/posting/post.js +551 -0
- package/dist/deltas/apis/posting/post.js.map +1 -0
- package/dist/deltas/apis/posting/share.js +59 -0
- package/dist/deltas/apis/posting/share.js.map +1 -0
- package/dist/deltas/apis/posting/story.js +176 -0
- package/dist/deltas/apis/posting/story.js.map +1 -0
- package/dist/deltas/apis/threads/getThreadHistory.js +233 -0
- package/dist/deltas/apis/threads/getThreadHistory.js.map +1 -0
- package/dist/deltas/apis/threads/getThreadInfo.js +197 -0
- package/dist/deltas/apis/threads/getThreadInfo.js.map +1 -0
- package/dist/deltas/apis/threads/getThreadList.js +201 -0
- package/dist/deltas/apis/threads/getThreadList.js.map +1 -0
- package/dist/deltas/apis/users/getUserInfo.js +254 -0
- package/dist/deltas/apis/users/getUserInfo.js.map +1 -0
- package/dist/index.d.ts +696 -0
- package/dist/types/core/client.d.ts +2 -0
- package/dist/types/core/models/buildAPI.d.ts +13 -0
- package/dist/types/core/models/loginHelper.d.ts +15 -0
- package/dist/types/core/models/setOptions.d.ts +2 -0
- package/dist/types/deltas/apis/create.d.ts +23 -0
- package/dist/types/deltas/apis/extra/addExternalModule.d.ts +1 -0
- package/dist/types/deltas/apis/extra/getAccess.d.ts +1 -0
- package/dist/types/deltas/apis/http/httpGet.d.ts +1 -0
- package/dist/types/deltas/apis/http/httpPost.d.ts +1 -0
- package/dist/types/deltas/apis/http/httpPostFormData.d.ts +1 -0
- package/dist/types/deltas/apis/login/GetBotInfo.d.ts +32 -0
- package/dist/types/deltas/apis/login/getBotInitialData.d.ts +1 -0
- package/dist/types/deltas/apis/login/logout.d.ts +7 -0
- package/dist/types/deltas/apis/messaging/editMessage.d.ts +7 -0
- package/dist/types/deltas/apis/messaging/emoji.d.ts +1 -0
- package/dist/types/deltas/apis/messaging/gcmember.d.ts +1 -0
- package/dist/types/deltas/apis/messaging/gcname.d.ts +1 -0
- package/dist/types/deltas/apis/messaging/gcrule.d.ts +1 -0
- package/dist/types/deltas/apis/messaging/markAsDelivered.d.ts +7 -0
- package/dist/types/deltas/apis/messaging/markAsRead.d.ts +6 -0
- package/dist/types/deltas/apis/messaging/markAsReadAll.d.ts +7 -0
- package/dist/types/deltas/apis/messaging/markAsSeen.d.ts +6 -0
- package/dist/types/deltas/apis/messaging/nickname.d.ts +1 -0
- package/dist/types/deltas/apis/messaging/notes.d.ts +14 -0
- package/dist/types/deltas/apis/messaging/resolvePhotoUrl.d.ts +9 -0
- package/dist/types/deltas/apis/messaging/sendMessage.d.ts +1 -0
- package/dist/types/deltas/apis/messaging/sendTypingIndicator.d.ts +6 -0
- package/dist/types/deltas/apis/messaging/setMessageReaction.d.ts +1 -0
- package/dist/types/deltas/apis/messaging/shareContact.d.ts +8 -0
- package/dist/types/deltas/apis/messaging/stickers.d.ts +48 -0
- package/dist/types/deltas/apis/messaging/theme.d.ts +1 -0
- package/dist/types/deltas/apis/messaging/unsendMessage.d.ts +1 -0
- package/dist/types/deltas/apis/mqtt/deltas/value.d.ts +2 -0
- package/dist/types/deltas/apis/mqtt/listenMqtt.d.ts +20 -0
- package/dist/types/deltas/apis/mqtt/listenSpeed.d.ts +21 -0
- package/dist/types/deltas/apis/mqtt/pinMessage.d.ts +1 -0
- package/dist/types/deltas/apis/mqtt/realtime.d.ts +1 -0
- package/dist/types/deltas/apis/mqtt/sendMessageMqtt.d.ts +1 -0
- package/dist/types/deltas/apis/mqtt/setMessageReactionMqtt.d.ts +1 -0
- package/dist/types/deltas/apis/posting/comment.d.ts +9 -0
- package/dist/types/deltas/apis/posting/follow.d.ts +14 -0
- package/dist/types/deltas/apis/posting/friend.d.ts +61 -0
- package/dist/types/deltas/apis/posting/post.d.ts +20 -0
- package/dist/types/deltas/apis/posting/share.d.ts +1 -0
- package/dist/types/deltas/apis/posting/story.d.ts +39 -0
- package/dist/types/deltas/apis/threads/getThreadHistory.d.ts +7 -0
- package/dist/types/deltas/apis/threads/getThreadInfo.d.ts +7 -0
- package/dist/types/deltas/apis/threads/getThreadList.d.ts +7 -0
- package/dist/types/deltas/apis/users/getUserInfo.d.ts +1 -0
- package/dist/types/utils/axios.d.ts +7 -0
- package/dist/types/utils/clients.d.ts +4 -0
- package/dist/types/utils/constants.d.ts +24 -0
- package/dist/types/utils/formatters/data/formatAttachment.d.ts +2 -0
- package/dist/types/utils/formatters/data/formatDelta.d.ts +4 -0
- package/dist/types/utils/formatters/index.d.ts +17 -0
- package/dist/types/utils/formatters/value/formatCookie.d.ts +8 -0
- package/dist/types/utils/formatters/value/formatDate.d.ts +6 -0
- package/dist/types/utils/formatters/value/formatID.d.ts +7 -0
- package/dist/types/utils/headers.d.ts +2 -0
- package/dist/types/utils/index.d.ts +75 -0
- package/dist/types/utils/user-agents.d.ts +9 -0
- package/dist/utils/axios.js +148 -0
- package/dist/utils/axios.js.map +1 -0
- package/dist/utils/clients.js +120 -0
- package/dist/utils/clients.js.map +1 -0
- package/dist/utils/constants.js +249 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/formatters/data/formatAttachment.js +61 -0
- package/dist/utils/formatters/data/formatAttachment.js.map +1 -0
- package/dist/utils/formatters/data/formatDelta.js +67 -0
- package/dist/utils/formatters/data/formatDelta.js.map +1 -0
- package/dist/utils/formatters/index.js +132 -0
- package/dist/utils/formatters/index.js.map +1 -0
- package/dist/utils/formatters/value/formatCookie.js +13 -0
- package/dist/utils/formatters/value/formatCookie.js.map +1 -0
- package/dist/utils/formatters/value/formatDate.js +33 -0
- package/dist/utils/formatters/value/formatDate.js.map +1 -0
- package/dist/utils/formatters/value/formatID.js +17 -0
- package/dist/utils/formatters/value/formatID.js.map +1 -0
- package/dist/utils/headers.js +61 -0
- package/dist/utils/headers.js.map +1 -0
- package/dist/utils/index.js +105 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/user-agents.js +41 -0
- package/dist/utils/user-agents.js.map +1 -0
- package/examples/post.example.js +149 -0
- package/module/index.js +5 -0
- package/package.json +56 -0
- package/src/core/client.ts +66 -0
- package/src/core/models/buildAPI.ts +131 -0
- package/src/core/models/loginHelper.ts +226 -0
- package/src/core/models/setOptions.ts +48 -0
- package/src/deltas/apis/create.ts +28 -0
- package/src/deltas/apis/extra/addExternalModule.ts +23 -0
- package/src/deltas/apis/extra/getAccess.ts +141 -0
- package/src/deltas/apis/http/httpGet.ts +61 -0
- package/src/deltas/apis/http/httpPost.ts +61 -0
- package/src/deltas/apis/http/httpPostFormData.ts +67 -0
- package/src/deltas/apis/login/GetBotInfo.ts +88 -0
- package/src/deltas/apis/login/getBotInitialData.ts +42 -0
- package/src/deltas/apis/login/logout.ts +62 -0
- package/src/deltas/apis/messaging/editMessage.ts +69 -0
- package/src/deltas/apis/messaging/emoji.ts +135 -0
- package/src/deltas/apis/messaging/gcmember.ts +175 -0
- package/src/deltas/apis/messaging/gcname.ts +136 -0
- package/src/deltas/apis/messaging/gcrule.ts +152 -0
- package/src/deltas/apis/messaging/markAsDelivered.ts +47 -0
- package/src/deltas/apis/messaging/markAsRead.ts +94 -0
- package/src/deltas/apis/messaging/markAsReadAll.ts +38 -0
- package/src/deltas/apis/messaging/markAsSeen.ts +69 -0
- package/src/deltas/apis/messaging/nickname.ts +153 -0
- package/src/deltas/apis/messaging/notes.ts +165 -0
- package/src/deltas/apis/messaging/resolvePhotoUrl.ts +56 -0
- package/src/deltas/apis/messaging/sendMessage.ts +286 -0
- package/src/deltas/apis/messaging/sendTypingIndicator.ts +48 -0
- package/src/deltas/apis/messaging/setMessageReaction.ts +25 -0
- package/src/deltas/apis/messaging/shareContact.ts +63 -0
- package/src/deltas/apis/messaging/stickers.ts +255 -0
- package/src/deltas/apis/messaging/theme.ts +280 -0
- package/src/deltas/apis/messaging/unsendMessage.ts +15 -0
- package/src/deltas/apis/mqtt/deltas/value.ts +224 -0
- package/src/deltas/apis/mqtt/listenMqtt.ts +332 -0
- package/src/deltas/apis/mqtt/listenSpeed.ts +179 -0
- package/src/deltas/apis/mqtt/pinMessage.ts +135 -0
- package/src/deltas/apis/mqtt/realtime.ts +169 -0
- package/src/deltas/apis/mqtt/sendMessageMqtt.ts +206 -0
- package/src/deltas/apis/mqtt/setMessageReactionMqtt.ts +61 -0
- package/src/deltas/apis/posting/comment.ts +205 -0
- package/src/deltas/apis/posting/follow.ts +79 -0
- package/src/deltas/apis/posting/friend.ts +241 -0
- package/src/deltas/apis/posting/post.ts +599 -0
- package/src/deltas/apis/posting/share.ts +60 -0
- package/src/deltas/apis/posting/story.ts +207 -0
- package/src/deltas/apis/threads/getThreadHistory.ts +237 -0
- package/src/deltas/apis/threads/getThreadInfo.ts +210 -0
- package/src/deltas/apis/threads/getThreadList.ts +224 -0
- package/src/deltas/apis/users/getUserInfo.ts +244 -0
- package/src/types/index.d.ts +696 -0
- package/src/utils/axios.ts +178 -0
- package/src/utils/clients.ts +125 -0
- package/src/utils/constants.ts +281 -0
- package/src/utils/formatters/data/formatAttachment.ts +58 -0
- package/src/utils/formatters/data/formatDelta.ts +45 -0
- package/src/utils/formatters/index.ts +82 -0
- package/src/utils/formatters/value/formatCookie.ts +13 -0
- package/src/utils/formatters/value/formatDate.ts +34 -0
- package/src/utils/formatters/value/formatID.ts +14 -0
- package/src/utils/formatters.old.ts +1049 -0
- package/src/utils/headers.ts +65 -0
- package/src/utils/index.ts +65 -0
- package/src/utils/user-agents.ts +49 -0
- package/tsconfig.json +37 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import utils = require('../../../utils');
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import HttpsProxyAgent from 'https-proxy-agent';
|
|
4
|
+
import mqtt from 'mqtt';
|
|
5
|
+
import websocket from 'websocket-stream';
|
|
6
|
+
import { parseDelta } from './deltas/value';
|
|
7
|
+
|
|
8
|
+
let form: any = {};
|
|
9
|
+
let getSeqID;
|
|
10
|
+
const topics = [
|
|
11
|
+
'/legacy_web',
|
|
12
|
+
'/webrtc',
|
|
13
|
+
'/rtc_multi',
|
|
14
|
+
'/onevc',
|
|
15
|
+
'/br_sr',
|
|
16
|
+
'/sr_res',
|
|
17
|
+
'/t_ms',
|
|
18
|
+
'/thread_typing',
|
|
19
|
+
'/orca_typing_notifications',
|
|
20
|
+
'/notify_disconnect',
|
|
21
|
+
'/orca_presence',
|
|
22
|
+
'/inbox',
|
|
23
|
+
'/mercury',
|
|
24
|
+
'/messaging_events',
|
|
25
|
+
'/orca_message_notifications',
|
|
26
|
+
'/pp',
|
|
27
|
+
'/webrtc_response',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
function generateUUID() {
|
|
31
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
32
|
+
var r = (Math.random() * 16) | 0,
|
|
33
|
+
v = c == 'x' ? r : (r & 0x3) | 0x8;
|
|
34
|
+
return v.toString(16);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getRandomReconnectTime() {
|
|
39
|
+
const min = 26 * 60 * 1000;
|
|
40
|
+
const max = 60 * 60 * 1000;
|
|
41
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function calculate(previousTimestamp, currentTimestamp) {
|
|
45
|
+
return Math.floor(
|
|
46
|
+
previousTimestamp + (currentTimestamp - previousTimestamp) + 300,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {Object} ctx
|
|
52
|
+
* @param {Object} api
|
|
53
|
+
* @param {string} threadID
|
|
54
|
+
*/
|
|
55
|
+
function markAsRead(ctx, api, threadID) {
|
|
56
|
+
if (ctx.globalOptions.autoMarkRead && threadID) {
|
|
57
|
+
api.markAsRead(threadID, (err) => {
|
|
58
|
+
if (err) utils.error('autoMarkRead', err);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {Object} defaultFuncs
|
|
65
|
+
* @param {Object} api
|
|
66
|
+
* @param {Object} ctx
|
|
67
|
+
* @param {Function} globalCallback
|
|
68
|
+
*/
|
|
69
|
+
async function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
|
|
70
|
+
const chatOn = ctx.globalOptions.online;
|
|
71
|
+
const region = ctx.region;
|
|
72
|
+
const foreground = false;
|
|
73
|
+
const sessionID = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1;
|
|
74
|
+
const cid = ctx.clientID;
|
|
75
|
+
const username = {
|
|
76
|
+
u: ctx.userID,
|
|
77
|
+
s: sessionID,
|
|
78
|
+
chat_on: chatOn,
|
|
79
|
+
fg: foreground,
|
|
80
|
+
d: cid,
|
|
81
|
+
ct: 'websocket',
|
|
82
|
+
aid: ctx.mqttAppID,
|
|
83
|
+
mqtt_sid: '',
|
|
84
|
+
cp: 3,
|
|
85
|
+
ecp: 10,
|
|
86
|
+
st: [],
|
|
87
|
+
pm: [],
|
|
88
|
+
dc: '',
|
|
89
|
+
no_auto_fg: true,
|
|
90
|
+
gas: null,
|
|
91
|
+
pack: [],
|
|
92
|
+
a: ctx.globalOptions.userAgent,
|
|
93
|
+
};
|
|
94
|
+
const cookies = ctx.jar.getCookiesSync('https://www.facebook.com').join('; ');
|
|
95
|
+
let host;
|
|
96
|
+
const domain = 'wss://edge-chat.messenger.com/chat';
|
|
97
|
+
if (region) {
|
|
98
|
+
host = `${domain}?region=${region.toLowerCase()}&sid=${sessionID}&cid=${cid}`;
|
|
99
|
+
} else {
|
|
100
|
+
host = `${domain}?sid=${sessionID}&cid=${cid}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
utils.log('Connecting to MQTT with new IDs...', host);
|
|
104
|
+
|
|
105
|
+
const options: any = {
|
|
106
|
+
clientId: 'mqttwsclient',
|
|
107
|
+
protocolId: 'MQIsdp',
|
|
108
|
+
protocolVersion: 3,
|
|
109
|
+
username: JSON.stringify(username),
|
|
110
|
+
clean: true,
|
|
111
|
+
wsOptions: {
|
|
112
|
+
headers: {
|
|
113
|
+
Cookie: cookies,
|
|
114
|
+
Origin: 'https://www.messenger.com',
|
|
115
|
+
'User-Agent': username.a,
|
|
116
|
+
Referer: 'https://www.messenger.com/',
|
|
117
|
+
Host: new URL(host).hostname,
|
|
118
|
+
},
|
|
119
|
+
origin: 'https://www.messenger.com',
|
|
120
|
+
protocolVersion: 13,
|
|
121
|
+
binaryType: 'arraybuffer',
|
|
122
|
+
},
|
|
123
|
+
keepalive: 10,
|
|
124
|
+
reschedulePings: true,
|
|
125
|
+
connectTimeout: 60000,
|
|
126
|
+
reconnectPeriod: 1000,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
if (ctx.globalOptions.proxy)
|
|
130
|
+
options.wsOptions.agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
|
|
131
|
+
const mqttClient: any = new mqtt.Client(
|
|
132
|
+
(_) => websocket(host, options.wsOptions),
|
|
133
|
+
options,
|
|
134
|
+
);
|
|
135
|
+
mqttClient.publishSync = mqttClient.publish.bind(mqttClient);
|
|
136
|
+
mqttClient.publish = (topic, message, opts = {}, callback: any = () => {}) =>
|
|
137
|
+
new Promise<any>((resolve, reject) => {
|
|
138
|
+
mqttClient.publishSync(topic, message, opts, (err, data) => {
|
|
139
|
+
if (err) {
|
|
140
|
+
callback(err);
|
|
141
|
+
reject(err);
|
|
142
|
+
}
|
|
143
|
+
callback(null, data);
|
|
144
|
+
resolve(data);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
ctx.mqttClient = mqttClient;
|
|
148
|
+
mqttClient.on('error', (err) => {
|
|
149
|
+
utils.error('listenMqtt', err);
|
|
150
|
+
mqttClient.end();
|
|
151
|
+
if (ctx.globalOptions.autoReconnect) getSeqID();
|
|
152
|
+
else globalCallback({ type: 'stop_listen', error: 'Connection refused' });
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
mqttClient.on('connect', async () => {
|
|
156
|
+
topics.forEach((topic) => mqttClient.subscribe(topic));
|
|
157
|
+
const queue: any = {
|
|
158
|
+
sync_api_version: 10,
|
|
159
|
+
max_deltas_able_to_process: 1000,
|
|
160
|
+
delta_batch_size: 500,
|
|
161
|
+
encoding: 'JSON',
|
|
162
|
+
entity_fbid: ctx.userID,
|
|
163
|
+
};
|
|
164
|
+
let topic;
|
|
165
|
+
if (ctx.syncToken) {
|
|
166
|
+
topic = '/messenger_sync_get_diffs';
|
|
167
|
+
queue.last_seq_id = ctx.lastSeqId;
|
|
168
|
+
queue.sync_token = ctx.syncToken;
|
|
169
|
+
} else {
|
|
170
|
+
topic = '/messenger_sync_create_queue';
|
|
171
|
+
queue.initial_titan_sequence_id = ctx.lastSeqId;
|
|
172
|
+
queue.device_params = null;
|
|
173
|
+
}
|
|
174
|
+
utils.log(`Successfully connected to MQTT.`);
|
|
175
|
+
const {
|
|
176
|
+
name: botName = 'Facebook User',
|
|
177
|
+
uid = ctx.userID,
|
|
178
|
+
} = await api.getBotInitialData();
|
|
179
|
+
utils.log(`Hello, ${botName} (${uid})`);
|
|
180
|
+
mqttClient.publish(topic, JSON.stringify(queue), { qos: 1, retain: false });
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
let presenceInterval;
|
|
184
|
+
if (ctx.globalOptions.updatePresence) {
|
|
185
|
+
presenceInterval = setInterval(() => {
|
|
186
|
+
if (mqttClient.connected) {
|
|
187
|
+
const presencePayload = utils.generatePresence(ctx.userID);
|
|
188
|
+
mqttClient.publish(
|
|
189
|
+
'/orca_presence',
|
|
190
|
+
JSON.stringify({ p: presencePayload }),
|
|
191
|
+
(err) => {
|
|
192
|
+
if (err) {
|
|
193
|
+
utils.error('Failed to send presence update:', err);
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}, 50000);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
mqttClient.on('message', async (topic, message, _packet) => {
|
|
202
|
+
try {
|
|
203
|
+
const jsonMessage = JSON.parse(message.toString());
|
|
204
|
+
//const packet = JSON.parse(_packet.payload.toString());
|
|
205
|
+
if (topic === '/t_ms') {
|
|
206
|
+
if (jsonMessage.lastIssuedSeqId) {
|
|
207
|
+
ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
|
|
208
|
+
}
|
|
209
|
+
if (jsonMessage.deltas) {
|
|
210
|
+
for (const delta of jsonMessage.deltas) {
|
|
211
|
+
parseDelta(defaultFuncs, api, ctx, globalCallback, { delta });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
} else if (
|
|
215
|
+
topic === '/thread_typing' ||
|
|
216
|
+
topic === '/orca_typing_notifications'
|
|
217
|
+
) {
|
|
218
|
+
const typ = {
|
|
219
|
+
type: 'typ',
|
|
220
|
+
isTyping: !!jsonMessage.state,
|
|
221
|
+
from: jsonMessage.sender_fbid.toString(),
|
|
222
|
+
threadID: utils.formatID(
|
|
223
|
+
(jsonMessage.thread || jsonMessage.sender_fbid).toString(),
|
|
224
|
+
),
|
|
225
|
+
};
|
|
226
|
+
globalCallback(null, typ);
|
|
227
|
+
}
|
|
228
|
+
} catch (ex) {
|
|
229
|
+
utils.error('listenMqtt: onMessage', ex);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
235
|
+
let globalCallback: Function = () => {};
|
|
236
|
+
let reconnectInterval;
|
|
237
|
+
getSeqID = async () => {
|
|
238
|
+
try {
|
|
239
|
+
form = {
|
|
240
|
+
queries: JSON.stringify({
|
|
241
|
+
o0: {
|
|
242
|
+
doc_id: '3336396659757871',
|
|
243
|
+
query_params: {
|
|
244
|
+
limit: 1,
|
|
245
|
+
before: null,
|
|
246
|
+
tags: ['INBOX'],
|
|
247
|
+
includeDeliveryReceipts: false,
|
|
248
|
+
includeSeqID: true,
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
}),
|
|
252
|
+
};
|
|
253
|
+
const resData = await defaultFuncs
|
|
254
|
+
.post('https://www.facebook.com/api/graphqlbatch/', ctx.jar, form)
|
|
255
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
256
|
+
if (
|
|
257
|
+
utils.getType(resData) != 'Array' ||
|
|
258
|
+
(resData.error && resData.error !== 1357001)
|
|
259
|
+
)
|
|
260
|
+
throw resData;
|
|
261
|
+
ctx.lastSeqId =
|
|
262
|
+
resData[0].o0.data.viewer.message_threads.sync_sequence_id;
|
|
263
|
+
listenMqtt(defaultFuncs, api, ctx, globalCallback);
|
|
264
|
+
} catch (err) {
|
|
265
|
+
const descriptiveError: any = new Error(
|
|
266
|
+
'Failed to get sequence ID. This is often caused by an invalid appstate. Please try generating a new appstate.json file.',
|
|
267
|
+
);
|
|
268
|
+
descriptiveError.originalError = err;
|
|
269
|
+
return globalCallback(descriptiveError);
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
return async (callback) => {
|
|
274
|
+
class MessageEmitter extends EventEmitter {
|
|
275
|
+
stop() {
|
|
276
|
+
globalCallback = () => {};
|
|
277
|
+
if (reconnectInterval) {
|
|
278
|
+
clearTimeout(reconnectInterval);
|
|
279
|
+
reconnectInterval = null;
|
|
280
|
+
}
|
|
281
|
+
if (ctx.mqttClient) {
|
|
282
|
+
ctx.mqttClient.end();
|
|
283
|
+
ctx.mqttClient = undefined;
|
|
284
|
+
}
|
|
285
|
+
this.emit('stop');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const msgEmitter = new MessageEmitter();
|
|
290
|
+
|
|
291
|
+
globalCallback = (error, message) => {
|
|
292
|
+
if (error) return msgEmitter.emit('error', error);
|
|
293
|
+
if (message.type === 'message' || message.type === 'message_reply') {
|
|
294
|
+
markAsRead(ctx, api, message.threadID);
|
|
295
|
+
}
|
|
296
|
+
msgEmitter.emit('message', message);
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
if (typeof callback === 'function') globalCallback = callback;
|
|
300
|
+
|
|
301
|
+
if (!ctx.firstListen || !ctx.lastSeqId) await getSeqID();
|
|
302
|
+
else listenMqtt(defaultFuncs, api, ctx, globalCallback);
|
|
303
|
+
|
|
304
|
+
if (ctx.firstListen) {
|
|
305
|
+
try {
|
|
306
|
+
await api.markAsReadAll();
|
|
307
|
+
} catch (err) {
|
|
308
|
+
utils.error('Failed to mark all messages as read on startup:', err);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
ctx.firstListen = false;
|
|
313
|
+
|
|
314
|
+
async function scheduleReconnect() {
|
|
315
|
+
const time = getRandomReconnectTime();
|
|
316
|
+
utils.log(
|
|
317
|
+
`Scheduled reconnect in ${Math.floor(time / 60000)} minutes...`,
|
|
318
|
+
);
|
|
319
|
+
reconnectInterval = setTimeout(() => {
|
|
320
|
+
utils.log(`Reconnecting MQTT with new clientID...`);
|
|
321
|
+
if (ctx.mqttClient) ctx.mqttClient.end(true);
|
|
322
|
+
ctx.clientID = generateUUID();
|
|
323
|
+
listenMqtt(defaultFuncs, api, ctx, globalCallback);
|
|
324
|
+
scheduleReconnect();
|
|
325
|
+
}, time);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
scheduleReconnect();
|
|
329
|
+
|
|
330
|
+
return msgEmitter;
|
|
331
|
+
};
|
|
332
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import utils = require('../../../utils');
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import HttpsProxyAgent from 'https-proxy-agent';
|
|
4
|
+
import mqtt from 'mqtt';
|
|
5
|
+
import websocket from 'websocket-stream';
|
|
6
|
+
|
|
7
|
+
function connectLightspeed(ctx, globalCallback) {
|
|
8
|
+
let client;
|
|
9
|
+
let isStopped = false;
|
|
10
|
+
|
|
11
|
+
function startConnection(retryCount = 0) {
|
|
12
|
+
if (isStopped) return;
|
|
13
|
+
|
|
14
|
+
const chatOn = ctx.globalOptions.online;
|
|
15
|
+
const foreground = false;
|
|
16
|
+
const sessionID = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1;
|
|
17
|
+
const cookies = ctx.jar
|
|
18
|
+
.getCookiesSync('https://www.facebook.com')
|
|
19
|
+
.join('; ');
|
|
20
|
+
const cid = ctx.clientID;
|
|
21
|
+
|
|
22
|
+
const username = {
|
|
23
|
+
u: ctx.userID,
|
|
24
|
+
s: sessionID,
|
|
25
|
+
chat_on: chatOn,
|
|
26
|
+
fg: foreground,
|
|
27
|
+
d: cid,
|
|
28
|
+
ct: 'websocket',
|
|
29
|
+
aid: '2220391788200892',
|
|
30
|
+
mqtt_sid: '',
|
|
31
|
+
cp: 3,
|
|
32
|
+
ecp: 10,
|
|
33
|
+
st: [],
|
|
34
|
+
pm: [],
|
|
35
|
+
dc: '',
|
|
36
|
+
no_auto_fg: true,
|
|
37
|
+
gas: null,
|
|
38
|
+
pack: [],
|
|
39
|
+
a: ctx.globalOptions.userAgent,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const queryParams = new URLSearchParams({
|
|
43
|
+
'x-dgw-appid': '2220391788200892',
|
|
44
|
+
'x-dgw-appversion': '0',
|
|
45
|
+
'x-dgw-authtype': '1:0',
|
|
46
|
+
'x-dgw-version': '5',
|
|
47
|
+
'x-dgw-uuid': ctx.userID,
|
|
48
|
+
'x-dgw-tier': 'prod',
|
|
49
|
+
'x-dgw-loggingid': utils.getGUID(),
|
|
50
|
+
'x-dgw-regionhint': ctx.region || 'PRN',
|
|
51
|
+
'x-dgw-deviceid': ctx.clientID,
|
|
52
|
+
});
|
|
53
|
+
const host = `wss://gateway.facebook.com/ws/lightspeed?${queryParams.toString()}`;
|
|
54
|
+
|
|
55
|
+
const options: any = {
|
|
56
|
+
clientId: 'mqttwsclient',
|
|
57
|
+
protocolId: 'MQIsdp',
|
|
58
|
+
protocolVersion: 3,
|
|
59
|
+
username: JSON.stringify(username),
|
|
60
|
+
clean: true,
|
|
61
|
+
wsOptions: {
|
|
62
|
+
headers: {
|
|
63
|
+
Cookie: cookies,
|
|
64
|
+
Origin: 'https://www.facebook.com',
|
|
65
|
+
'User-Agent': username.a,
|
|
66
|
+
Referer: 'https://www.facebook.com/',
|
|
67
|
+
Host: new URL(host).hostname,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
keepalive: 10,
|
|
71
|
+
reconnectPeriod: 0,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
if (ctx.globalOptions.proxy) {
|
|
75
|
+
options.wsOptions.agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
client = new mqtt.Client(
|
|
80
|
+
(_) => websocket(host, options.wsOptions),
|
|
81
|
+
options,
|
|
82
|
+
);
|
|
83
|
+
utils.log('[Lightspeed] Attempting MQTT connection...');
|
|
84
|
+
} catch (err) {
|
|
85
|
+
utils.error('[Lightspeed] MQTT Client creation failed:', err.message);
|
|
86
|
+
reconnect(retryCount + 1);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
client.on('connect', () => {
|
|
91
|
+
utils.log(
|
|
92
|
+
'[Lightspeed] MQTT client connected. Attempting to subscribe to topics...',
|
|
93
|
+
);
|
|
94
|
+
retryCount = 0;
|
|
95
|
+
|
|
96
|
+
// --- ITO ANG IDINAGDAG NA SUBSCRIBE LOGIC ---
|
|
97
|
+
const topicsToSubscribe = [
|
|
98
|
+
'/t_ms', // Para sa mga messages at deltas
|
|
99
|
+
'/orca_presence', // Para sa online status
|
|
100
|
+
'/messaging_events', // Para sa ibang events
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
topicsToSubscribe.forEach((topic) => {
|
|
104
|
+
client.subscribe(topic, (err) => {
|
|
105
|
+
if (err) {
|
|
106
|
+
utils.error(
|
|
107
|
+
`[Lightspeed] Failed to subscribe to topic ${topic}:`,
|
|
108
|
+
err.message,
|
|
109
|
+
);
|
|
110
|
+
} else {
|
|
111
|
+
utils.log(`[Lightspeed] Subscribed to topic: ${topic}`);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
// -----------------------------------------
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
client.on('message', (topic, payload) => {
|
|
119
|
+
utils.log(`[Lightspeed] Payload Received on topic ${topic}:`);
|
|
120
|
+
globalCallback(null, {
|
|
121
|
+
type: 'lightspeed_message',
|
|
122
|
+
topic: topic.toString(),
|
|
123
|
+
payload: payload,
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
client.on('close', () => {
|
|
128
|
+
utils.warn(`[Lightspeed] Connection closed.`);
|
|
129
|
+
if (!isStopped) {
|
|
130
|
+
reconnect(retryCount + 1);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
client.on('error', (err) => {
|
|
135
|
+
utils.error('[Lightspeed] MQTT Connection Error:', err.message);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function reconnect(retryCount) {
|
|
140
|
+
const delay = Math.min(3000 * Math.pow(2, retryCount), 60000);
|
|
141
|
+
utils.log(`[Lightspeed] Reconnecting in ${delay / 1000} seconds...`);
|
|
142
|
+
setTimeout(() => startConnection(retryCount), delay);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
startConnection();
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
stop: () => {
|
|
149
|
+
isStopped = true;
|
|
150
|
+
if (client) client.end(true);
|
|
151
|
+
utils.log('[Lightspeed] Listener has been manually stopped.');
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
157
|
+
return (callback) => {
|
|
158
|
+
class MessageEmitter extends EventEmitter {
|
|
159
|
+
listener: any = null;
|
|
160
|
+
stop() {
|
|
161
|
+
if (this.listener) {
|
|
162
|
+
this.listener.stop();
|
|
163
|
+
}
|
|
164
|
+
this.emit('stop');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const msgEmitter = new MessageEmitter();
|
|
168
|
+
const globalCallback = (error, message) => {
|
|
169
|
+
if (error) return msgEmitter.emit('error', error);
|
|
170
|
+
msgEmitter.emit('message', message);
|
|
171
|
+
};
|
|
172
|
+
if (typeof callback === 'function') {
|
|
173
|
+
msgEmitter.listener = connectLightspeed(ctx, callback);
|
|
174
|
+
} else {
|
|
175
|
+
msgEmitter.listener = connectLightspeed(ctx, globalCallback);
|
|
176
|
+
}
|
|
177
|
+
return msgEmitter;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import utils = require("../../../utils");
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import _ from "lodash";
|
|
5
|
+
import deepdash from "deepdash";
|
|
6
|
+
import { JSONPath } from "jsonpath-plus";
|
|
7
|
+
|
|
8
|
+
deepdash(_);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Extract and save the full lightspeed_web_request object from thread data.
|
|
12
|
+
* Also search for specific pinned message commands.
|
|
13
|
+
* @param {Object} allJsonData - Raw JSON response from Facebook.
|
|
14
|
+
* @returns {Object|null} The full lightspeed_web_request object or null.
|
|
15
|
+
*/
|
|
16
|
+
function extractAndSearchLightspeedRequest(allJsonData) {
|
|
17
|
+
const outputFile = path.join(__dirname, "lightspeed_web_request.json");
|
|
18
|
+
|
|
19
|
+
const lightReq = _.get(allJsonData, "__bbox.result.data.viewer.lightspeed_web_request");
|
|
20
|
+
if (!lightReq) {
|
|
21
|
+
utils.warn("pin.js: lightspeed_web_request not found.");
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Save the entire object for debugging
|
|
26
|
+
try {
|
|
27
|
+
fs.writeFileSync(outputFile, JSON.stringify(lightReq, null, 2), "utf8");
|
|
28
|
+
utils.log(`pin.js: Saved lightspeed_web_request to ${outputFile}`);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
utils.error("pin.js: Failed to write lightspeed_web_request.json", err);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 🔍 Use JSONPath to search for both commands
|
|
34
|
+
try {
|
|
35
|
+
const matches = JSONPath({
|
|
36
|
+
path: `$..[?(@ === "setPinnedMessage" || @ === "deleteThenInsertMessage")]`,
|
|
37
|
+
json: lightReq
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
utils.log(`pin.js: Found ${matches.length} matching command(s).`);
|
|
41
|
+
matches.forEach((match, idx) => {
|
|
42
|
+
console.log(`📌 Match ${idx + 1}:`, match);
|
|
43
|
+
});
|
|
44
|
+
} catch (err) {
|
|
45
|
+
utils.error("pin.js: JSONPath search failed.", err);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return lightReq;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default function(defaultFuncs: any, api: any, ctx: any) {
|
|
52
|
+
return async function pin(action, threadID, messageID) {
|
|
53
|
+
if (action === "list") {
|
|
54
|
+
if (!threadID) throw new Error('Action "list" requires threadID.');
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const url = `https://www.facebook.com/messages/t/${threadID}/`;
|
|
58
|
+
const allJsonData = await utils.json(url, ctx.jar, null, ctx.globalOptions, ctx);
|
|
59
|
+
|
|
60
|
+
// Extract, save and search commands inside lightspeed_web_request
|
|
61
|
+
const lightReq = extractAndSearchLightspeedRequest(allJsonData);
|
|
62
|
+
return lightReq;
|
|
63
|
+
} catch (err) {
|
|
64
|
+
utils.error(`pin.js: Failed to process "list" for thread ${threadID}`, err);
|
|
65
|
+
throw err;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!ctx.mqttClient) throw new Error("MQTT not connected.");
|
|
70
|
+
if (!threadID || !messageID) throw new Error(`"${action}" requires threadID and messageID.`);
|
|
71
|
+
|
|
72
|
+
const epoch_id = parseInt(utils.generateOfflineThreadingID());
|
|
73
|
+
const version_id = "9523201934447612";
|
|
74
|
+
const app_id = "2220391788200892";
|
|
75
|
+
|
|
76
|
+
const createMqttRequest = (tasks, increment = 0) => ({
|
|
77
|
+
app_id,
|
|
78
|
+
payload: JSON.stringify({ epoch_id: epoch_id + increment, tasks, version_id }),
|
|
79
|
+
request_id: (ctx.wsReqNumber = (ctx.wsReqNumber || 0) + 1),
|
|
80
|
+
type: 3
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const publishMqtt = (content) =>
|
|
84
|
+
new Promise<any>((resolve, reject) => {
|
|
85
|
+
ctx.mqttClient.publish("/ls_req", JSON.stringify(content), { qos: 1, retain: false }, (err) => {
|
|
86
|
+
if (err) reject(err);
|
|
87
|
+
else resolve({ success: true, request_id: content.request_id });
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
if (action === "pin") {
|
|
92
|
+
const pinTask = {
|
|
93
|
+
label: "430",
|
|
94
|
+
payload: JSON.stringify({ thread_key: threadID, message_id: messageID, timestamp_ms: Date.now() }),
|
|
95
|
+
queue_name: `pin_msg_v2_${threadID}`,
|
|
96
|
+
task_id: (ctx.wsTaskNumber = (ctx.wsTaskNumber || 0) + 1)
|
|
97
|
+
};
|
|
98
|
+
const setSearchTask = {
|
|
99
|
+
label: "751",
|
|
100
|
+
payload: JSON.stringify({ thread_key: threadID, message_id: messageID, pinned_message_state: 1 }),
|
|
101
|
+
queue_name: "set_pinned_message_search",
|
|
102
|
+
task_id: (ctx.wsTaskNumber = (ctx.wsTaskNumber || 0) + 1)
|
|
103
|
+
};
|
|
104
|
+
const req1 = createMqttRequest([pinTask], 0);
|
|
105
|
+
const req2 = createMqttRequest([setSearchTask], 1);
|
|
106
|
+
return Promise.all([publishMqtt(req1), publishMqtt(req2)]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (action === "unpin") {
|
|
110
|
+
const setSearchTask1 = {
|
|
111
|
+
label: "751",
|
|
112
|
+
payload: JSON.stringify({ thread_key: threadID, message_id: messageID, pinned_message_state: 0 }),
|
|
113
|
+
queue_name: "set_pinned_message_search",
|
|
114
|
+
task_id: (ctx.wsTaskNumber = (ctx.wsTaskNumber || 0) + 1)
|
|
115
|
+
};
|
|
116
|
+
const unpinTask = {
|
|
117
|
+
label: "431",
|
|
118
|
+
payload: JSON.stringify({ thread_key: threadID, message_id: messageID, timestamp_ms: Date.now() }),
|
|
119
|
+
queue_name: `unpin_msg_v2_${threadID}`,
|
|
120
|
+
task_id: (ctx.wsTaskNumber = (ctx.wsTaskNumber || 0) + 1)
|
|
121
|
+
};
|
|
122
|
+
const setSearchTask2 = {
|
|
123
|
+
label: "751",
|
|
124
|
+
payload: JSON.stringify({ thread_key: threadID, message_id: messageID, pinned_message_state: 0 }),
|
|
125
|
+
queue_name: "set_pinned_message_search",
|
|
126
|
+
task_id: (ctx.wsTaskNumber = (ctx.wsTaskNumber || 0) + 1)
|
|
127
|
+
};
|
|
128
|
+
await publishMqtt(createMqttRequest([setSearchTask1], 0));
|
|
129
|
+
await publishMqtt(createMqttRequest([unpinTask], 1));
|
|
130
|
+
return publishMqtt(createMqttRequest([setSearchTask2], 2));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
throw new Error(`Invalid action: "${action}". Use "pin", "unpin", or "list".`);
|
|
134
|
+
};
|
|
135
|
+
};
|