@cexy/hoonfca 1.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/README.md +83 -0
- package/index.js +467 -0
- package/package.json +12 -0
- package/replit.nix +3 -0
- package/src/addExternalModule.js +25 -0
- package/src/addUserToGroup.js +98 -0
- package/src/changeAdminStatus.js +98 -0
- package/src/changeArchivedStatus.js +51 -0
- package/src/changeAvatar.js +89 -0
- package/src/changeBio.js +74 -0
- package/src/changeBlockedStatus.js +45 -0
- package/src/changeBlockedStatusMqtt.js +65 -0
- package/src/changeCover.js +92 -0
- package/src/changeGroupImage.js +110 -0
- package/src/changeName.js +106 -0
- package/src/changeNickname.js +58 -0
- package/src/changeThreadColor.js +62 -0
- package/src/changeThreadEmoji.js +54 -0
- package/src/changeUsername.js +80 -0
- package/src/createCommentPost.js +196 -0
- package/src/createNewGroup.js +81 -0
- package/src/createPoll.js +64 -0
- package/src/createPost.js +285 -0
- package/src/data/getThreadInfo.json +1 -0
- package/src/deleteMessage.js +55 -0
- package/src/deleteThread.js +55 -0
- package/src/editMessage.js +66 -0
- package/src/follow.js +71 -0
- package/src/forwardAttachment.js +57 -0
- package/src/getAccess.js +130 -0
- package/src/getAvatarUser.js +88 -0
- package/src/getBotInitialData.js +59 -0
- package/src/getCtx.js +5 -0
- package/src/getCurrentUserID.js +5 -0
- package/src/getEmojiUrl.js +18 -0
- package/src/getFriendsList.js +81 -0
- package/src/getMessage.js +827 -0
- package/src/getOptions.js +5 -0
- package/src/getRegion.js +7 -0
- package/src/getThreadHistory.js +496 -0
- package/src/getThreadHistoryDeprecated.js +95 -0
- package/src/getThreadInfo.js +194 -0
- package/src/getThreadInfoDeprecated.js +77 -0
- package/src/getThreadList.js +219 -0
- package/src/getThreadListDeprecated.js +86 -0
- package/src/getThreadPictures.js +85 -0
- package/src/getUserID.js +67 -0
- package/src/getUserInfo.js +89 -0
- package/src/handleFriendRequest.js +56 -0
- package/src/handleMessageRequest.js +65 -0
- package/src/httpGet.js +53 -0
- package/src/httpPost.js +53 -0
- package/src/httpPostFormData.js +58 -0
- package/src/listenMqtt.js +683 -0
- package/src/listenNotification.js +96 -0
- package/src/logout.js +77 -0
- package/src/markAsDelivered.js +53 -0
- package/src/markAsRead.js +74 -0
- package/src/markAsReadAll.js +46 -0
- package/src/markAsSeen.js +57 -0
- package/src/muteThread.js +49 -0
- package/src/pinMessage.js +60 -0
- package/src/refreshFb_dtsg.js +75 -0
- package/src/removeUserFromGroup.js +59 -0
- package/src/resolvePhotoUrl.js +47 -0
- package/src/searchForThread.js +55 -0
- package/src/searchStickers.js +59 -0
- package/src/sendMessage.js +444 -0
- package/src/sendMessageMqtt.js +326 -0
- package/src/sendTypingIndicator.js +54 -0
- package/src/setMessageReaction.js +126 -0
- package/src/setMessageReactionMqtt.js +74 -0
- package/src/setPostReaction.js +103 -0
- package/src/setProfileGuard.js +66 -0
- package/src/setStoryReaction.js +97 -0
- package/src/setTitle.js +100 -0
- package/src/shareContact.js +101 -0
- package/src/shareLink.js +105 -0
- package/src/stopListenMqtt.js +47 -0
- package/src/threadColors.js +119 -0
- package/src/unfriend.js +58 -0
- package/src/unsendMessage.js +51 -0
- package/src/uploadAttachment.js +98 -0
- package/utils.js +919 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var utils = require("../utils");
|
|
4
|
+
|
|
5
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
6
|
+
function uploadAttachment(attachments, callback) {
|
|
7
|
+
callback = callback || function () {};
|
|
8
|
+
var uploads = [];
|
|
9
|
+
|
|
10
|
+
// create an array of promises
|
|
11
|
+
for (var i = 0; i < attachments.length; i++) {
|
|
12
|
+
if (!utils.isReadableStream(attachments[i])) {
|
|
13
|
+
throw {
|
|
14
|
+
error:
|
|
15
|
+
"Attachment should be a readable stream and not " +
|
|
16
|
+
utils.getType(attachments[i]) +
|
|
17
|
+
".",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
var form = {
|
|
22
|
+
upload_1024: attachments[i],
|
|
23
|
+
voice_clip: "true",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
uploads.push(
|
|
27
|
+
defaultFuncs
|
|
28
|
+
.postFormData(
|
|
29
|
+
"https://upload.facebook.com/ajax/mercury/upload.php",
|
|
30
|
+
ctx.jar,
|
|
31
|
+
form,
|
|
32
|
+
{},
|
|
33
|
+
)
|
|
34
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
35
|
+
.then(function (resData) {
|
|
36
|
+
if (resData.error) {
|
|
37
|
+
throw resData;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// We have to return the data unformatted unless we want to change it
|
|
41
|
+
// back in sendMessage.
|
|
42
|
+
return resData.payload.metadata[0];
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// resolve all promises
|
|
48
|
+
Promise.all(uploads)
|
|
49
|
+
.then(function (resData) {
|
|
50
|
+
callback(null, resData);
|
|
51
|
+
})
|
|
52
|
+
.catch(function (err) {
|
|
53
|
+
utils.error("uploadAttachment", err);
|
|
54
|
+
return callback(err);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let variance = 0;
|
|
59
|
+
const epoch_id = () =>
|
|
60
|
+
Math.floor(Date.now() * (4194304 + (variance = (variance + 0.1) % 5)));
|
|
61
|
+
const emojiSizes = {
|
|
62
|
+
small: 1,
|
|
63
|
+
medium: 2,
|
|
64
|
+
large: 3,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function handleEmoji(msg, form, callback, cb) {
|
|
68
|
+
if (msg.emojiSize != null && msg.emoji == null) {
|
|
69
|
+
return callback({ error: "emoji property is empty" });
|
|
70
|
+
}
|
|
71
|
+
if (msg.emoji) {
|
|
72
|
+
if (!msg.emojiSize) {
|
|
73
|
+
msg.emojiSize = "small";
|
|
74
|
+
}
|
|
75
|
+
if (
|
|
76
|
+
msg.emojiSize !== "small" &&
|
|
77
|
+
msg.emojiSize !== "medium" &&
|
|
78
|
+
msg.emojiSize !== "large" &&
|
|
79
|
+
(isNaN(msg.emojiSize) || msg.emojiSize < 1 || msg.emojiSize > 3)
|
|
80
|
+
) {
|
|
81
|
+
return callback({ error: "emojiSize property is invalid" });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
form.payload.tasks[0].payload.send_type = 1;
|
|
85
|
+
form.payload.tasks[0].payload.text = msg.emoji;
|
|
86
|
+
form.payload.tasks[0].payload.hot_emoji_size = !isNaN(msg.emojiSize)
|
|
87
|
+
? Number(msg.emojiSize)
|
|
88
|
+
: emojiSizes[msg.emojiSize];
|
|
89
|
+
}
|
|
90
|
+
cb();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function handleSticker(msg, form, callback, cb) {
|
|
94
|
+
if (msg.sticker) {
|
|
95
|
+
form.payload.tasks[0].payload.send_type = 2;
|
|
96
|
+
form.payload.tasks[0].payload.sticker_id = msg.sticker;
|
|
97
|
+
}
|
|
98
|
+
cb();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function handleAttachment(msg, form, callback, cb) {
|
|
102
|
+
if (msg.attachment) {
|
|
103
|
+
form.payload.tasks[0].payload.send_type = 3;
|
|
104
|
+
form.payload.tasks[0].payload.attachment_fbids = [];
|
|
105
|
+
if (form.payload.tasks[0].payload.text == "") {
|
|
106
|
+
form.payload.tasks[0].payload.text = null;
|
|
107
|
+
}
|
|
108
|
+
if (utils.getType(msg.attachment) !== "Array") {
|
|
109
|
+
msg.attachment = [msg.attachment];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
uploadAttachment(msg.attachment, function (err, files) {
|
|
113
|
+
if (err) {
|
|
114
|
+
return callback(err);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
files.forEach(function (file) {
|
|
118
|
+
var key = Object.keys(file);
|
|
119
|
+
var type = key[0]; // image_id, file_id, etc
|
|
120
|
+
form.payload.tasks[0].payload.attachment_fbids.push(file[type]); // push the id
|
|
121
|
+
});
|
|
122
|
+
cb();
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
cb();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function handleMention(msg, form, callback, cb) {
|
|
130
|
+
if (msg.mentions) {
|
|
131
|
+
form.payload.tasks[0].payload.send_type = 1;
|
|
132
|
+
|
|
133
|
+
const arrayIds = [];
|
|
134
|
+
const arrayOffsets = [];
|
|
135
|
+
const arrayLengths = [];
|
|
136
|
+
const mention_types = [];
|
|
137
|
+
const bodyText = msg.body ? msg.body.toString() : "";
|
|
138
|
+
|
|
139
|
+
for (let i = 0; i < msg.mentions.length; i++) {
|
|
140
|
+
const mention = msg.mentions[i];
|
|
141
|
+
|
|
142
|
+
const tag = mention.tag;
|
|
143
|
+
if (typeof tag !== "string") {
|
|
144
|
+
return callback({ error: "Mention tags must be strings." });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const offset = bodyText.indexOf(tag, mention.fromIndex || 0);
|
|
148
|
+
|
|
149
|
+
if (offset < 0) {
|
|
150
|
+
utils.warn(
|
|
151
|
+
"handleMention",
|
|
152
|
+
'Mention for "' + tag + '" not found in message string.',
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (mention.id == null) {
|
|
157
|
+
utils.warn("handleMention", "Mention id should be non-null.");
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const id = mention.id || 0;
|
|
161
|
+
arrayIds.push(id);
|
|
162
|
+
arrayOffsets.push(offset);
|
|
163
|
+
arrayLengths.push(tag.length);
|
|
164
|
+
mention_types.push("p");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
form.payload.tasks[0].payload.mention_data = {
|
|
168
|
+
mention_ids: arrayIds.join(","),
|
|
169
|
+
mention_offsets: arrayOffsets.join(","),
|
|
170
|
+
mention_lengths: arrayLengths.join(","),
|
|
171
|
+
mention_types: mention_types.join(","),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
cb();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function handleLocation(msg, form, callback, cb) {
|
|
178
|
+
if (msg.location) {
|
|
179
|
+
if (msg.location.latitude == null || msg.location.longitude == null) {
|
|
180
|
+
return callback({
|
|
181
|
+
error: "location property needs both latitude and longitude",
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
form.payload.tasks[0].payload.send_type = 1;
|
|
186
|
+
form.payload.tasks[0].payload.location_data = {
|
|
187
|
+
coordinates: {
|
|
188
|
+
latitude: msg.location.latitude,
|
|
189
|
+
longitude: msg.location.longitude,
|
|
190
|
+
},
|
|
191
|
+
is_current_location: !!msg.location.current,
|
|
192
|
+
is_live_location: !!msg.location.live,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
cb();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function send(form, threadID, callback, replyToMessage) {
|
|
200
|
+
if (replyToMessage) {
|
|
201
|
+
form.payload.tasks[0].payload.reply_metadata = {
|
|
202
|
+
reply_source_id: replyToMessage.toString(),
|
|
203
|
+
reply_source_type: 1,
|
|
204
|
+
reply_type: 0,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const mqttClient = ctx.mqttClient;
|
|
208
|
+
if (!mqttClient) {
|
|
209
|
+
return callback({ error: "MQTT Client is not initialized." });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
form.payload.tasks.forEach((task) => {
|
|
213
|
+
task.payload = JSON.stringify(task.payload);
|
|
214
|
+
});
|
|
215
|
+
form.payload = JSON.stringify(form.payload);
|
|
216
|
+
|
|
217
|
+
return mqttClient.publish(
|
|
218
|
+
"/ls_req",
|
|
219
|
+
JSON.stringify(form),
|
|
220
|
+
{ qos: 1, retain: false },
|
|
221
|
+
function (err, data) {
|
|
222
|
+
if (err) {
|
|
223
|
+
utils.error("Error publishing message: ", err);
|
|
224
|
+
return callback(err);
|
|
225
|
+
} else {
|
|
226
|
+
return callback(null, data);
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return function sendMessageMqtt(msg, threadID, callback, replyToMessage) {
|
|
233
|
+
if (
|
|
234
|
+
!callback &&
|
|
235
|
+
(utils.getType(threadID) === "Function" ||
|
|
236
|
+
utils.getType(threadID) === "AsyncFunction")
|
|
237
|
+
) {
|
|
238
|
+
return threadID({ error: "Pass a threadID as a second argument." });
|
|
239
|
+
}
|
|
240
|
+
if (!replyToMessage && utils.getType(callback) === "String") {
|
|
241
|
+
replyToMessage = callback;
|
|
242
|
+
callback = function () {};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!callback) {
|
|
246
|
+
callback = function (err, data) {};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
var msgType = utils.getType(msg);
|
|
250
|
+
var threadIDType = utils.getType(threadID);
|
|
251
|
+
|
|
252
|
+
if (msgType !== "String" && msgType !== "Object") {
|
|
253
|
+
return callback({
|
|
254
|
+
error:
|
|
255
|
+
"Message should be of type string or object and not " + msgType + ".",
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!threadID) {
|
|
260
|
+
return callback({ error: "ThreadID is required." });
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (msgType === "String") {
|
|
264
|
+
msg = { body: msg };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const timestamp = Date.now();
|
|
268
|
+
const epoch = timestamp << 22;
|
|
269
|
+
const otid = epoch + Math.floor(Math.random() * 4194304);
|
|
270
|
+
|
|
271
|
+
const form = {
|
|
272
|
+
app_id: "2220391788200892",
|
|
273
|
+
payload: {
|
|
274
|
+
tasks: [
|
|
275
|
+
{
|
|
276
|
+
label: "46",
|
|
277
|
+
payload: {
|
|
278
|
+
thread_id: threadID.toString(),
|
|
279
|
+
otid: otid.toString(),
|
|
280
|
+
source: 0,
|
|
281
|
+
send_type: 1,
|
|
282
|
+
sync_group: 1,
|
|
283
|
+
text:
|
|
284
|
+
msg.body != null && msg.body !== undefined
|
|
285
|
+
? msg.body.toString()
|
|
286
|
+
: "",
|
|
287
|
+
initiating_source: 1,
|
|
288
|
+
skip_url_preview_gen: 0,
|
|
289
|
+
},
|
|
290
|
+
queue_name: threadID.toString(),
|
|
291
|
+
task_id: 0,
|
|
292
|
+
failure_count: null,
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
label: "21",
|
|
296
|
+
payload: {
|
|
297
|
+
thread_id: threadID.toString(),
|
|
298
|
+
last_read_watermark_ts: Date.now(),
|
|
299
|
+
sync_group: 1,
|
|
300
|
+
},
|
|
301
|
+
queue_name: threadID.toString(),
|
|
302
|
+
task_id: 1,
|
|
303
|
+
failure_count: null,
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
epoch_id: epoch_id(),
|
|
307
|
+
version_id: "6120284488008082",
|
|
308
|
+
data_trace_id: null,
|
|
309
|
+
},
|
|
310
|
+
request_id: 1,
|
|
311
|
+
type: 3,
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
handleEmoji(msg, form, callback, function () {
|
|
315
|
+
handleLocation(msg, form, callback, function () {
|
|
316
|
+
handleMention(msg, form, callback, function () {
|
|
317
|
+
handleSticker(msg, form, callback, function () {
|
|
318
|
+
handleAttachment(msg, form, callback, function () {
|
|
319
|
+
send(form, threadID, callback, replyToMessage);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var utils = require("../utils");
|
|
4
|
+
// @NethWs3Dev
|
|
5
|
+
|
|
6
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
7
|
+
let count_req = 0;
|
|
8
|
+
|
|
9
|
+
return async function sendTypingIndicatorV2(sendTyping, threadID, callback) {
|
|
10
|
+
if (typeof callback !== "function") {
|
|
11
|
+
callback = function () {};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!threadID) {
|
|
15
|
+
return callback({ error: "ThreadID is required." });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (!ctx.mqttClient) {
|
|
19
|
+
return callback({ error: "MQTT Client is not initialized." });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
var wsContent = {
|
|
23
|
+
app_id: 2220391788200892,
|
|
24
|
+
payload: JSON.stringify({
|
|
25
|
+
label: 3,
|
|
26
|
+
payload: JSON.stringify({
|
|
27
|
+
thread_key: threadID.toString(),
|
|
28
|
+
is_group_thread: +(threadID.toString().length >= 16),
|
|
29
|
+
is_typing: +sendTyping,
|
|
30
|
+
attribution: 0
|
|
31
|
+
}),
|
|
32
|
+
version: 5849951561777440
|
|
33
|
+
}),
|
|
34
|
+
request_id: ++count_req,
|
|
35
|
+
type: 4
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
await new Promise((resolve, reject) => {
|
|
40
|
+
ctx.mqttClient.publish('/ls_req', JSON.stringify(wsContent), { qos: 1, retain: false }, (err, _packet) => {
|
|
41
|
+
if (err) {
|
|
42
|
+
reject(err);
|
|
43
|
+
} else {
|
|
44
|
+
resolve();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
callback(null);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
utils.error("sendTypingIndicatorV2", err);
|
|
51
|
+
callback(err);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require("../utils");
|
|
4
|
+
// @NethWs3Dev
|
|
5
|
+
|
|
6
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
7
|
+
return function setMessageReaction(
|
|
8
|
+
reaction,
|
|
9
|
+
messageID,
|
|
10
|
+
callback,
|
|
11
|
+
forceCustomReaction,
|
|
12
|
+
) {
|
|
13
|
+
let resolveFunc = function () {};
|
|
14
|
+
let rejectFunc = function () {};
|
|
15
|
+
const returnPromise = new Promise(function (resolve, reject) {
|
|
16
|
+
resolveFunc = resolve;
|
|
17
|
+
rejectFunc = reject;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (!callback) {
|
|
21
|
+
callback = function (err, data) {
|
|
22
|
+
if (err) {
|
|
23
|
+
return rejectFunc(err);
|
|
24
|
+
}
|
|
25
|
+
resolveFunc(data);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!messageID) {
|
|
30
|
+
return callback({ error: "MessageID is required." });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
switch (reaction) {
|
|
34
|
+
case "\uD83D\uDE0D": //:heart_eyes:
|
|
35
|
+
case "\uD83D\uDE06": //:laughing:
|
|
36
|
+
case "\uD83D\uDE2E": //:open_mouth:
|
|
37
|
+
case "\uD83D\uDE22": //:cry:
|
|
38
|
+
case "\uD83D\uDE20": //:angry:
|
|
39
|
+
case "\uD83D\uDC4D": //:thumbsup:
|
|
40
|
+
case "\uD83D\uDC4E": //:thumbsdown:
|
|
41
|
+
case "\u2764": //:heart:
|
|
42
|
+
case "\uD83D\uDC97": //:glowingheart:
|
|
43
|
+
case "":
|
|
44
|
+
//valid
|
|
45
|
+
break;
|
|
46
|
+
case ":heart_eyes:":
|
|
47
|
+
case ":love:":
|
|
48
|
+
reaction = "\uD83D\uDE0D";
|
|
49
|
+
break;
|
|
50
|
+
case ":laughing:":
|
|
51
|
+
case ":haha:":
|
|
52
|
+
reaction = "\uD83D\uDE06";
|
|
53
|
+
break;
|
|
54
|
+
case ":open_mouth:":
|
|
55
|
+
case ":wow:":
|
|
56
|
+
reaction = "\uD83D\uDE2E";
|
|
57
|
+
break;
|
|
58
|
+
case ":cry:":
|
|
59
|
+
case ":sad:":
|
|
60
|
+
reaction = "\uD83D\uDE22";
|
|
61
|
+
break;
|
|
62
|
+
case ":angry:":
|
|
63
|
+
reaction = "\uD83D\uDE20";
|
|
64
|
+
break;
|
|
65
|
+
case ":thumbsup:":
|
|
66
|
+
case ":like:":
|
|
67
|
+
reaction = "\uD83D\uDC4D";
|
|
68
|
+
break;
|
|
69
|
+
case ":thumbsdown:":
|
|
70
|
+
case ":dislike:":
|
|
71
|
+
reaction = "\uD83D\uDC4E";
|
|
72
|
+
break;
|
|
73
|
+
case ":heart:":
|
|
74
|
+
reaction = "\u2764";
|
|
75
|
+
break;
|
|
76
|
+
case ":glowingheart:":
|
|
77
|
+
reaction = "\uD83D\uDC97";
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
if (forceCustomReaction) {
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
return callback({ error: "Reaction is not a valid emoji." });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const variables = {
|
|
87
|
+
data: {
|
|
88
|
+
client_mutation_id: ctx.clientMutationId++,
|
|
89
|
+
actor_id: ctx.userID,
|
|
90
|
+
action: reaction == "" ? "REMOVE_REACTION" : "ADD_REACTION",
|
|
91
|
+
message_id: messageID,
|
|
92
|
+
reaction: reaction,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const qs = {
|
|
97
|
+
doc_id: "1491398900900362",
|
|
98
|
+
variables: JSON.stringify(variables),
|
|
99
|
+
dpr: 1,
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
defaultFuncs
|
|
103
|
+
.postFormData(
|
|
104
|
+
"https://www.facebook.com/webgraphql/mutation/",
|
|
105
|
+
ctx.jar,
|
|
106
|
+
{},
|
|
107
|
+
qs,
|
|
108
|
+
)
|
|
109
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
110
|
+
.then(function (resData) {
|
|
111
|
+
if (!resData) {
|
|
112
|
+
throw { error: "setReaction returned empty object." };
|
|
113
|
+
}
|
|
114
|
+
if (resData.error) {
|
|
115
|
+
throw resData;
|
|
116
|
+
}
|
|
117
|
+
callback(null);
|
|
118
|
+
})
|
|
119
|
+
.catch(function (err) {
|
|
120
|
+
utils.error("setReaction", err);
|
|
121
|
+
return callback(err);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
return returnPromise;
|
|
125
|
+
};
|
|
126
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
6
|
+
return function setMessageReactionMqtt(reaction, messageID, threadID, callback) {
|
|
7
|
+
// safe callback check
|
|
8
|
+
if (typeof callback !== 'function') {
|
|
9
|
+
callback = function () {};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (!ctx.mqttClient) {
|
|
13
|
+
return callback({ error: 'Not connected to MQTT' });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!messageID || !threadID) {
|
|
17
|
+
return callback({ error: 'messageID and threadID are required.' });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
ctx.wsReqNumber += 1;
|
|
21
|
+
ctx.wsTaskNumber += 1;
|
|
22
|
+
|
|
23
|
+
const taskPayload = {
|
|
24
|
+
thread_key: threadID.toString(),
|
|
25
|
+
timestamp_ms: Date.now(),
|
|
26
|
+
message_id: messageID.toString(),
|
|
27
|
+
reaction: reaction || "", // reaction খালি হলে রিমুভ হবে
|
|
28
|
+
actor_id: ctx.userID.toString(),
|
|
29
|
+
reaction_style: null,
|
|
30
|
+
sync_group: 1,
|
|
31
|
+
send_attribution: Math.random() < 0.5 ? 65537 : 524289
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const task = {
|
|
35
|
+
failure_count: null,
|
|
36
|
+
label: '29',
|
|
37
|
+
payload: JSON.stringify(taskPayload),
|
|
38
|
+
queue_name: JSON.stringify(['reaction', messageID.toString()]),
|
|
39
|
+
task_id: ctx.wsTaskNumber,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const content = {
|
|
43
|
+
app_id: '2220391788200892',
|
|
44
|
+
payload: JSON.stringify({
|
|
45
|
+
data_trace_id: null,
|
|
46
|
+
epoch_id: parseInt(utils.generateOfflineThreadingID()),
|
|
47
|
+
tasks: [task],
|
|
48
|
+
version_id: '7158486590867448',
|
|
49
|
+
}),
|
|
50
|
+
request_id: ctx.wsReqNumber,
|
|
51
|
+
type: 3,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (ctx.reqCallbacks) {
|
|
55
|
+
ctx.reqCallbacks[ctx.wsReqNumber] = callback;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ctx.mqttClient.publish(
|
|
59
|
+
'/ls_req',
|
|
60
|
+
JSON.stringify(content),
|
|
61
|
+
{ qos: 1, retain: false },
|
|
62
|
+
function (err, data) {
|
|
63
|
+
if (err) {
|
|
64
|
+
utils.error("setMessageReactionMqtt", err);
|
|
65
|
+
return callback(err);
|
|
66
|
+
}
|
|
67
|
+
// যদি reqCallbacks রেজিস্টার্ড না থাকে, তবে পাবলিশের সাথে সাথে কলব্যাক ফায়ার করবে
|
|
68
|
+
if (!ctx.reqCallbacks) {
|
|
69
|
+
callback(null, data);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require("../utils");
|
|
4
|
+
|
|
5
|
+
function formatData(resData) {
|
|
6
|
+
return {
|
|
7
|
+
viewer_feedback_reaction_info: resData.feedback_react.feedback.viewer_feedback_reaction_info,
|
|
8
|
+
supported_reactions: resData.feedback_react.feedback.supported_reactions,
|
|
9
|
+
top_reactions: resData.feedback_react.feedback.top_reactions.edges,
|
|
10
|
+
reaction_count: resData.feedback_react.feedback.reaction_count,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
15
|
+
return function setPostReaction(postID, type, callback) {
|
|
16
|
+
let resolveFunc = function () {};
|
|
17
|
+
let rejectFunc = function () {};
|
|
18
|
+
const returnPromise = new Promise(function (resolve, reject) {
|
|
19
|
+
resolveFunc = resolve;
|
|
20
|
+
rejectFunc = reject;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (!callback) {
|
|
24
|
+
if (utils.getType(type) === "Function" || utils.getType(type) === "AsyncFunction") {
|
|
25
|
+
callback = type;
|
|
26
|
+
type = 0;
|
|
27
|
+
} else {
|
|
28
|
+
callback = function (err, data) {
|
|
29
|
+
if (err) {
|
|
30
|
+
return rejectFunc(err);
|
|
31
|
+
}
|
|
32
|
+
resolveFunc(data);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!postID) {
|
|
38
|
+
return callback({ error: "setPostReaction: postID is required" });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const map = {
|
|
42
|
+
unlike: 0,
|
|
43
|
+
like: 1,
|
|
44
|
+
heart: 2,
|
|
45
|
+
love: 16,
|
|
46
|
+
haha: 4,
|
|
47
|
+
wow: 3,
|
|
48
|
+
sad: 7,
|
|
49
|
+
angry: 8,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const originalType = type;
|
|
53
|
+
if (utils.getType(type) === "String") {
|
|
54
|
+
type = map[type.toLowerCase()];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (type === undefined || (utils.getType(type) !== "Number" && utils.getType(type) !== "String")) {
|
|
58
|
+
return callback({
|
|
59
|
+
error: "setPostReaction: Invalid reaction type (" + originalType + ")",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const form = {
|
|
64
|
+
av: ctx.userID,
|
|
65
|
+
fb_api_caller_class: "RelayModern",
|
|
66
|
+
fb_api_req_friendly_name: "CometUFIFeedbackReactMutation",
|
|
67
|
+
doc_id: "4769042373179384",
|
|
68
|
+
variables: JSON.stringify({
|
|
69
|
+
input: {
|
|
70
|
+
actor_id: ctx.userID,
|
|
71
|
+
feedback_id: Buffer.from("feedback:" + postID).toString("base64"),
|
|
72
|
+
feedback_reaction: type,
|
|
73
|
+
feedback_source: "OBJECT",
|
|
74
|
+
is_tracking_encrypted: true,
|
|
75
|
+
tracking: [],
|
|
76
|
+
session_id: "f7dd50dd-db6e-4598-8cd9-561d5002b423",
|
|
77
|
+
client_mutation_id: Math.round(Math.random() * 19).toString(),
|
|
78
|
+
},
|
|
79
|
+
useDefaultActor: false,
|
|
80
|
+
scale: 3,
|
|
81
|
+
}),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
defaultFuncs
|
|
85
|
+
.post("https://www.facebook.com/api/graphql/", ctx.jar, form)
|
|
86
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
87
|
+
.then(function (resData) {
|
|
88
|
+
if (!resData) {
|
|
89
|
+
throw { error: "setPostReaction returned empty response." };
|
|
90
|
+
}
|
|
91
|
+
if (resData.errors) {
|
|
92
|
+
throw resData;
|
|
93
|
+
}
|
|
94
|
+
return callback(null, formatData(resData.data));
|
|
95
|
+
})
|
|
96
|
+
.catch(function (err) {
|
|
97
|
+
utils.error("setPostReaction", err);
|
|
98
|
+
return callback(err);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return returnPromise;
|
|
102
|
+
};
|
|
103
|
+
};
|