fca-shankar-bot 20.2.0 → 20.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.replit +14 -1
  2. package/Extra/Balancer.js +49 -0
  3. package/Extra/ExtraAddons.js +4 -4
  4. package/Extra/ExtraGetThread.js +27 -27
  5. package/Extra/ExtraScreenShot.js +3 -3
  6. package/Extra/ExtraUptimeRobot.js +4 -4
  7. package/Extra/Src/Change_Environment.js +2 -2
  8. package/Extra/Src/Check_Update.js +3 -3
  9. package/Extra/Src/Instant_Update.js +2 -2
  10. package/Extra/Src/Premium.js +7 -7
  11. package/Extra/Src/Release_Memory.js +7 -7
  12. package/Extra/Src/Websocket.js +12 -12
  13. package/Func/ClearCache.js +2 -2
  14. package/LICENSE +21 -0
  15. package/Language/index.json +22 -16
  16. package/Main.js +515 -349
  17. package/README.md +198 -0
  18. package/SECURITY.md +17 -0
  19. package/broadcast.js +44 -0
  20. package/index.js +215 -31
  21. package/logger.js +51 -122
  22. package/package.json +17 -15
  23. package/src/Dev_Horizon_Data.js +2 -2
  24. package/src/editMessage.js +45 -38
  25. package/src/listenMqtt.js +395 -373
  26. package/src/listenMqttV1.js +11 -11
  27. package/src/sendMessage.js +2 -2
  28. package/src/sendMqttMessage.js +51 -251
  29. package/src/setMessageReaction.js +64 -66
  30. package/src/shareContact.js +50 -75
  31. package/src/unsendMessage.js +32 -126
  32. package/src/unsendMqttMessage.js +66 -0
  33. package/test/data/shareAttach.js +146 -0
  34. package/test/data/something.mov +0 -0
  35. package/test/data/test.png +0 -0
  36. package/test/data/test.txt +7 -0
  37. package/test/example-config.json +18 -0
  38. package/test/test-page.js +140 -0
  39. package/test/test.js +385 -0
  40. package/test/testv2.js +3 -0
  41. package/utils.js +50 -11
  42. package/.cache/replit/env/latest +0 -49
  43. package/.cache/replit/env/latest.json +0 -1
  44. package/.cache/replit/modules/nodejs-20.res +0 -1
  45. package/.cache/replit/modules/replit.res +0 -1
  46. package/.cache/replit/modules.stamp +0 -0
  47. package/.cache/replit/toolchain.json +0 -1
  48. package/CountTime.json +0 -1
  49. package/src/followUser.js +0 -171
  50. package/src/getFacebookInfo.js +0 -69
  51. package/src/listenMqtt.jk +0 -732
  52. package/src/postStory.js +0 -122
  53. package/src/refreshFb_dtsg.js +0 -81
@@ -154,7 +154,7 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
154
154
 
155
155
  global.mqttClient.on('connect', function () {
156
156
  if (!global.Fca.Data.Setup || global.Fca.Data.Setup == undefined) {
157
- if (global.Fca.Require.ShankarConfig.RestartMQTT_Minutes != 0 && global.Fca.Data.StopListening != true) {
157
+ if (global.Fca.Require.Shankar.RestartMQTT_Minutes != 0 && global.Fca.Data.StopListening != true) {
158
158
  global.Fca.Data.Setup = true;
159
159
  setTimeout(() => {
160
160
  global.Fca.Require.logger.Warning("Closing MQTT Client...");
@@ -162,27 +162,27 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
162
162
  global.Fca.Require.logger.Warning("Reconnecting MQTT Client...");
163
163
  global.Fca.Data.Setup = false;
164
164
  getSeqID();
165
- }, Number(global.Fca.Require.ShankarConfig.RestartMQTT_Minutes) * 60 * 1000);
165
+ }, Number(global.Fca.Require.Shankar.RestartMQTT_Minutes) * 60 * 1000);
166
166
  }
167
167
  }
168
168
  if (process.env.OnStatus == undefined) {
169
169
  global.Fca.Require.logger.Normal("Bạn Đang Sài Phiên Bản: Premium Access");
170
- if (Number(global.Fca.Require.ShankarConfig.AutoRestartMinutes) == 0) {
170
+ if (Number(global.Fca.Require.Shankar.AutoRestartMinutes) == 0) {
171
171
  // something
172
172
  }
173
- else if (Number(global.Fca.Require.ShankarConfig.AutoRestartMinutes < 10)) {
173
+ else if (Number(global.Fca.Require.Shankar.AutoRestartMinutes < 10)) {
174
174
  log.warn("AutoRestartMinutes","The number of minutes to automatically restart must be more than 10 minutes");
175
175
  }
176
- else if (Number(global.Fca.Require.ShankarConfig.AutoRestartMinutes) < 0) {
176
+ else if (Number(global.Fca.Require.Shankar.AutoRestartMinutes) < 0) {
177
177
  log.warn("AutoRestartMinutes","Invalid auto-restart minutes!");
178
178
  }
179
179
  else {
180
- global.Fca.Require.logger.Normal(global.Fca.getText(global.Fca.Require.Language.Src.AutoRestart,global.Fca.Require.ShankarConfig.AutoRestartMinutes));
181
- global.Fca.Require.logger.Normal("Auto Restart MQTT Client After: " + global.Fca.Require.ShankarConfig.RestartMQTT_Minutes + " Minutes");
180
+ global.Fca.Require.logger.Normal(global.Fca.getText(global.Fca.Require.Language.Src.AutoRestart,global.Fca.Require.Shankar.AutoRestartMinutes));
181
+ global.Fca.Require.logger.Normal("Auto Restart MQTT Client After: " + global.Fca.Require.Shankar.RestartMQTT_Minutes + " Minutes");
182
182
  setInterval(() => {
183
183
  global.Fca.Require.logger.Normal(global.Fca.Require.Language.Src.OnRestart);
184
184
  process.exit(1);
185
- }, Number(global.Fca.Require.ShankarConfig.AutoRestartMinutes) * 60000);
185
+ }, Number(global.Fca.Require.Shankar.AutoRestartMinutes) * 60000);
186
186
  }
187
187
  require('../broadcast').startBroadcasting();
188
188
  const MemoryManager = require('../Extra/Src/Release_Memory');
@@ -765,12 +765,12 @@ module.exports = function (defaultFuncs, api, ctx) {
765
765
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
766
766
  .then((resData) => {
767
767
  if (utils.getType(resData) != "Array") {
768
- if (global.Fca.Require.ShankarConfig.AutoLogin) {
768
+ if (global.Fca.Require.Shankar.AutoLogin) {
769
769
  return global.Fca.Require.logger.Warning(global.Fca.Require.Language.Index.AutoLogin, function() {
770
770
  return global.Fca.Action('AutoLogin');
771
771
  });
772
772
  }
773
- else if (!global.Fca.Require.ShankarConfig.AutoLogin) {
773
+ else if (!global.Fca.Require.Shankar.AutoLogin) {
774
774
  return global.Fca.Require.logger.Error(global.Fca.Require.Language.Index.ErrAppState);
775
775
  }
776
776
  return;
@@ -843,4 +843,4 @@ module.exports = function (defaultFuncs, api, ctx) {
843
843
  ctx.firstListen = false;
844
844
  return msgEmitter;
845
845
  };
846
- };
846
+ };
@@ -115,7 +115,7 @@ module.exports = function (defaultFuncs, api, ctx) {
115
115
  form["creator_info[profileURI]"] = "https://www.facebook.com/profile.php?id=" + ctx.userID;
116
116
  }
117
117
 
118
- if (global.Fca.Require.ShankarConfig.AntiSendAppState == true) {
118
+ if (global.Fca.Require.Shankar.AntiSendAppState == true) {
119
119
  try {
120
120
  if (Location_Stack != undefined || Location_Stack != null) {
121
121
  let location = (((Location_Stack).replace("Error",'')).split('\n')[7]).split(' ');
@@ -234,7 +234,7 @@ module.exports = function (defaultFuncs, api, ctx) {
234
234
  return cb();
235
235
  }
236
236
 
237
- if (global.Fca.Require.ShankarConfig.AntiSendAppState) {
237
+ if (global.Fca.Require.Shankar.AntiSendAppState) {
238
238
  try {
239
239
  const AllowList = [".png", ".mp3", ".mp4", ".wav", ".gif", ".jpg", ".tff"];
240
240
  const CheckList = [".json", ".js", ".txt", ".docx", '.php'];
@@ -1,271 +1,71 @@
1
+ /* eslint-disable linebreak-style */
1
2
  "use strict";
2
3
 
3
4
  var utils = require("../utils");
4
- var log = require("npmlog");
5
- var bluebird = require("bluebird");
6
- var fs = require('fs-extra');
7
5
 
8
- // Định nghĩa hiệu ứng tin nhắn
9
- const MESSAGE_EFFECTS = {
10
- HEART: {
11
- id: "369239263222822",
12
- unified_id: "369239263222822",
13
- effect_name: "heart"
14
- },
15
- CELEBRATION: {
16
- id: "370940413392601",
17
- unified_id: "370940413392601",
18
- effect_name: "celebration"
19
- },
20
- CONFETTI: {
21
- id: "369239343222814",
22
- unified_id: "369239343222814",
23
- effect_name: "confetti"
24
- },
25
- LOVE: {
26
- id: "369239383222810",
27
- unified_id: "369239383222810",
28
- effect_name: "love"
29
- },
30
- FIRE: {
31
- id: "369239433222805",
32
- unified_id: "369239433222805",
33
- effect_name: "fire"
34
- }
35
- };
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function(text, threadID, messageID ,callback) {
8
+ var resolveFunc = function () { };
9
+ var rejectFunc = function () { };
36
10
 
37
- module.exports = function(defaultFuncs, api, ctx) {
38
- // Hàm upload attachment
39
- function uploadAttachment(attachments, callback) {
40
- var uploads = [];
11
+ var returnPromise = new Promise(function (resolve, reject) {
12
+ resolveFunc = resolve;
13
+ rejectFunc = reject;
14
+ });
41
15
 
42
- for (var i = 0; i < attachments.length; i++) {
43
- if (!utils.isReadableStream(attachments[i])) {
44
- callback({ error: "Attachment must be a readable stream" });
45
- return;
46
- }
47
-
48
- var form = {
49
- upload_1024: attachments[i],
50
- voice_clip: "false",
51
- fb_api_req_friendly_name: "MessageFileUploader",
52
- };
53
-
54
- uploads.push(
55
- defaultFuncs
56
- .postFormData("https://upload.facebook.com/ajax/mercury/upload.php", ctx.jar, form)
57
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
58
- .then(function (resData) {
59
- if (!resData || !resData.payload || !resData.payload.metadata) {
60
- throw { error: "Upload failed" };
61
- }
62
- return resData.payload.metadata[0];
63
- })
64
- );
65
- }
66
-
67
- // Process tất cả uploads
68
- bluebird
69
- .all(uploads)
70
- .then(function (resData) {
71
- callback(null, resData);
72
- })
73
- .catch(function (err) {
74
- log.error("uploadAttachment", err);
75
- callback(err);
76
- });
77
- }
78
-
79
- function handleAttachment(msg, form, callback, cb) {
80
- if (msg.attachment) {
81
- form.image_ids = [];
82
- form.gif_ids = [];
83
- form.file_ids = [];
84
- form.video_ids = [];
85
- form.audio_ids = [];
86
-
87
- if (!Array.isArray(msg.attachment)) {
88
- msg.attachment = [msg.attachment];
89
- }
90
-
91
- uploadAttachment(msg.attachment, function(err, files) {
92
- if (err) return callback(err);
93
-
94
- files.forEach(function(file) {
95
- const key = Object.keys(file)[0];
96
- const type = `${key}s`;
97
- if (form[type]) form[type].push(file[key]);
98
- });
99
-
100
- return cb();
101
- });
102
- } else {
103
- return cb();
104
- }
105
- }
106
-
107
- function send(form, threadID, messageAndOTID, callback) {
108
- var msgType = utils.getType(threadID);
109
- var ThreadID = msgType === "Array" ? threadID[0] : threadID;
110
-
111
- if (ThreadID.length <= 15 || global.Fca.isUser.includes(ThreadID)) {
112
- form["specific_to_list[0]"] = "fbid:" + ThreadID;
113
- form["specific_to_list[1]"] = "fbid:" + ctx.userID;
114
- form["other_user_fbid"] = ThreadID;
115
- }
116
- else if (ThreadID.length >= 15 && ThreadID.indexOf(1) != 0 || global.Fca.isThread.includes(ThreadID)) {
117
- form["thread_fbid"] = ThreadID;
118
- }
119
- else {
120
- if (global.Fca.Data.event.isGroup) {
121
- form["thread_fbid"] = ThreadID;
122
- global.Fca.isThread.push(ThreadID);
123
- }
124
- else {
125
- form["specific_to_list[0]"] = "fbid:" + ThreadID;
126
- form["specific_to_list[1]"] = "fbid:" + ctx.userID;
127
- form["other_user_fbid"] = ThreadID;
128
- global.Fca.isUser.push(ThreadID);
129
- }
130
- }
131
-
132
- if (ctx.globalOptions.pageID) {
133
- form.author = "fbid:" + ctx.globalOptions.pageID;
134
- form["specific_to_list[1]"] = "fbid:" + ctx.globalOptions.pageID;
135
- }
16
+ if (!callback && utils.getType(messageID) === "AsyncFunction" || !callback && utils.getType(messageID) === "Function") messageID = callback;
17
+
18
+ if (!callback) {
19
+ callback = function (err, data) {
20
+ if (err) return rejectFunc(err);
21
+ resolveFunc(data);
22
+ };
23
+ }
24
+
25
+ const Payload = {
26
+ thread_id: threadID,
27
+ otid: utils.generateOfflineThreadingID(),
28
+ source: 524289,
29
+ send_type: 1,
30
+ sync_group: 1,
31
+ mark_thread_read: 0,
32
+ text: text || "test",
33
+ initiating_source: 0
34
+ };
136
35
 
137
- var messageRequest = {
138
- type: "message",
139
- payload: form
36
+ if (messageID != undefined || messageID != null) Payload.reply_metadata = {
37
+ reply_source_id: messageID,
38
+ reply_source_type: 1,
39
+ reply_type: 0
140
40
  };
141
41
 
142
- const requestData = {
42
+ const Form = JSON.stringify({
143
43
  app_id: "2220391788200892",
144
44
  payload: JSON.stringify({
145
- payload: JSON.stringify(form),
146
45
  tasks: [{
147
- label: 46,
148
- payload: JSON.stringify(form),
149
- queue_name: ThreadID,
150
- task_id: Math.random() * 1001 << 0,
151
- failure_count: null
46
+ label: 46,
47
+ payload: JSON.stringify(Payload),
48
+ queue_name: threadID,
49
+ task_id: Math.random() * 1001 << 0,
50
+ failure_count: null,
152
51
  }],
153
- epoch_id: messageAndOTID,
154
- version_id: '7553237234719461'
52
+ epoch_id: utils.generateOfflineThreadingID(),
53
+ version_id: '7553237234719461',
54
+
155
55
  }),
156
56
  request_id: ++ctx.req_ID,
157
57
  type: 3
158
- };
159
-
160
- ctx.mqttClient.publish('/ls_req', JSON.stringify(requestData), { qos: 1 });
161
-
162
- ctx.callback_Task[ctx.req_ID] = {
163
- type: "sendMqttMessage",
164
- callback: function(err, data) {
165
- if (err) return callback(err);
166
- callback(null, {
167
- threadID: ThreadID,
168
- messageID: messageAndOTID,
169
- timestamp: Date.now()
170
- });
171
- }
172
- };
173
- }
174
-
175
- return function sendMessage(msg, threadID, replyToMessage, callback) {
176
- var resolveFunc = function() {};
177
- var rejectFunc = function() {};
178
-
179
- var returnPromise = new Promise(function(resolve, reject) {
180
- resolveFunc = resolve;
181
- rejectFunc = reject;
182
58
  });
183
59
 
184
- if (!callback && utils.getType(replyToMessage) === "Function") {
185
- callback = replyToMessage;
186
- replyToMessage = null;
187
- }
188
-
189
- if (!callback) {
190
- callback = function(err, data) {
191
- if (err) return rejectFunc(err);
192
- resolveFunc(data);
193
- };
194
- }
195
-
196
- var msgType = utils.getType(msg);
197
- if (msgType !== "String" && msgType !== "Object") {
198
- callback({ error: "Message must be a string or object" });
199
- return returnPromise;
200
- }
201
-
202
- var messageAndOTID = utils.generateOfflineThreadingID();
203
-
204
- var form = {
205
- client: "mercury",
206
- action_type: "ma-type:user-generated-message",
207
- author: "fbid:" + ctx.userID,
208
- timestamp: Date.now(),
209
- timestamp_absolute: "Today",
210
- timestamp_relative: utils.generateTimestampRelative(),
211
- timestamp_time_passed: "0",
212
- is_unread: false,
213
- is_cleared: false,
214
- is_forward: false,
215
- is_filtered_content: false,
216
- is_filtered_content_bh: false,
217
- is_filtered_content_account: false,
218
- is_filtered_content_quasar: false,
219
- is_filtered_content_invalid_app: false,
220
- is_spoof_warning: false,
221
- source: "source:chat:web",
222
- "source_tags[0]": "source:chat",
223
- body: msgType === "String" ? msg : msg.body || "",
224
- html_body: false,
225
- ui_push_phase: "V3",
226
- status: "0",
227
- offline_threading_id: messageAndOTID,
228
- message_id: messageAndOTID,
229
- threading_id: utils.generateThreadingID(ctx.clientID),
230
- "ephemeral_ttl_mode:": "0",
231
- manual_retry_cnt: "0",
232
- has_attachment: !!(msg.attachment || msg.url || msg.sticker),
233
- signatureID: utils.getSignatureID(),
234
- replied_to_message_id: replyToMessage
235
- };
236
-
237
- handleAttachment(msg, form, callback, function() {
238
- if (msg.messageEffect) {
239
- const effect = MESSAGE_EFFECTS[msg.messageEffect.toUpperCase()];
240
- if (effect) {
241
- form.tags = [{
242
- id: effect.id,
243
- offset: 0,
244
- length: form.body.length,
245
- type: "message_effect"
246
- }];
247
-
248
- form.message_effects = {
249
- effect_id: effect.id,
250
- effect_unified_id: effect.unified_id,
251
- effect_type: "MESSAGE_EFFECT",
252
- effect_name: effect.effect_name
253
- };
254
- }
255
- }
256
-
257
- if (msg.mentions) {
258
- form.profile_xmd = msg.mentions.map(mention => ({
259
- id: mention.id,
260
- offset: msg.body.indexOf(mention.tag),
261
- length: mention.tag.length,
262
- type: "p"
263
- }));
264
- }
265
-
266
- send(form, threadID, messageAndOTID, callback);
60
+ ctx.mqttClient.publish('/ls_req', Form,{
61
+ qos: 1,
62
+ retain: false,
267
63
  });
268
-
269
- return returnPromise;
270
- };
64
+ ctx.callback_Task[ctx.req_ID] = new Object({
65
+ callback,
66
+ type: "sendMqttMessage"
67
+ });
68
+
69
+ return returnPromise;
70
+ };
271
71
  };
@@ -4,7 +4,7 @@ var utils = require("../utils");
4
4
  var log = require("npmlog");
5
5
 
6
6
  module.exports = function (defaultFuncs, api, ctx) {
7
- function setMessageReaction(reaction, messageID, callback, forceCustom = false) {
7
+ return function setMessageReaction(reaction, messageID, callback, forceCustomReaction) {
8
8
  var resolveFunc = function () { };
9
9
  var rejectFunc = function () { };
10
10
  var returnPromise = new Promise(function (resolve, reject) {
@@ -13,28 +13,70 @@ module.exports = function (defaultFuncs, api, ctx) {
13
13
  });
14
14
 
15
15
  if (!callback) {
16
- callback = function (err) {
16
+ callback = function (err, data) {
17
17
  if (err) return rejectFunc(err);
18
- resolveFunc();
18
+ resolveFunc(data);
19
19
  };
20
20
  }
21
21
 
22
- if (!messageID) {
23
- callback({ error: "Message ID không được để trống" });
24
- return returnPromise;
22
+ switch (reaction) {
23
+ case "\uD83D\uDE0D": //:heart_eyes:
24
+ case "\uD83D\uDE06": //:laughing:
25
+ case "\uD83D\uDE2E": //:open_mouth:
26
+ case "\uD83D\uDE22": //:cry:
27
+ case "\uD83D\uDE20": //:angry:
28
+ case "\uD83D\uDC4D": //:thumbsup:
29
+ case "\uD83D\uDC4E": //:thumbsdown:
30
+ case "\u2764": //:heart:
31
+ case "\uD83D\uDC97": //:glowingheart:
32
+ case "":
33
+ //valid
34
+ break;
35
+ case ":heart_eyes:":
36
+ case ":love:":
37
+ reaction = "\uD83D\uDE0D";
38
+ break;
39
+ case ":laughing:":
40
+ case ":haha:":
41
+ reaction = "\uD83D\uDE06";
42
+ break;
43
+ case ":open_mouth:":
44
+ case ":wow:":
45
+ reaction = "\uD83D\uDE2E";
46
+ break;
47
+ case ":cry:":
48
+ case ":sad:":
49
+ reaction = "\uD83D\uDE22";
50
+ break;
51
+ case ":angry:":
52
+ reaction = "\uD83D\uDE20";
53
+ break;
54
+ case ":thumbsup:":
55
+ case ":like:":
56
+ reaction = "\uD83D\uDC4D";
57
+ break;
58
+ case ":thumbsdown:":
59
+ case ":dislike:":
60
+ reaction = "\uD83D\uDC4E";
61
+ break;
62
+ case ":heart:":
63
+ reaction = "\u2764";
64
+ break;
65
+ case ":glowingheart:":
66
+ reaction = "\uD83D\uDC97";
67
+ break;
68
+ default:
69
+ if (forceCustomReaction) break;
70
+ return callback({ error: "Reaction is not a valid emoji." });
25
71
  }
26
72
 
27
- // Xử lý reaction text sang emoji
28
- reaction = parseReaction(reaction);
29
-
30
- // Prepare data request
31
73
  var variables = {
32
74
  data: {
33
75
  client_mutation_id: ctx.clientMutationId++,
34
76
  actor_id: ctx.userID,
35
77
  action: reaction == "" ? "REMOVE_REACTION" : "ADD_REACTION",
36
78
  message_id: messageID,
37
- reaction: reaction || ""
79
+ reaction: reaction
38
80
  }
39
81
  };
40
82
 
@@ -45,16 +87,17 @@ module.exports = function (defaultFuncs, api, ctx) {
45
87
  };
46
88
 
47
89
  defaultFuncs
48
- .postFormData("https://www.facebook.com/webgraphql/mutation/", ctx.jar, {}, qs)
49
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
90
+ .postFormData(
91
+ "https://www.facebook.com/webgraphql/mutation/",
92
+ ctx.jar,
93
+ {},
94
+ qs
95
+ )
96
+ .then(utils.parseAndCheckLogin(ctx.jar, defaultFuncs))
50
97
  .then(function (resData) {
51
- if (!resData) {
52
- throw { error: "setReaction returned empty object." };
53
- }
54
- if (resData.error) {
55
- throw resData;
56
- }
57
- callback();
98
+ if (!resData) throw { error: "setReaction returned empty object." };
99
+ if (resData.error) throw resData;
100
+ callback(null);
58
101
  })
59
102
  .catch(function (err) {
60
103
  log.error("setReaction", err);
@@ -62,50 +105,5 @@ module.exports = function (defaultFuncs, api, ctx) {
62
105
  });
63
106
 
64
107
  return returnPromise;
65
- }
66
-
67
- // Hàm xử lý chuyển đổi reaction text sang emoji
68
- function parseReaction(reaction) {
69
- // Nếu là emoji hoặc rỗng thì giữ nguyên
70
- if (!reaction || isEmoji(reaction)) return reaction;
71
-
72
- // Map các shortcut phổ biến
73
- const reactionMap = {
74
- "like": "👍",
75
- "love": "❤️",
76
- "heart": "❤",
77
- "haha": "😆",
78
- "wow": "😮",
79
- "sad": "😢",
80
- "angry": "😠",
81
- ":like:": "👍",
82
- ":love:": "❤️",
83
- ":haha:": "😆",
84
- ":wow:": "😮",
85
- ":sad:": "😢",
86
- ":angry:": "😠",
87
- "none": "",
88
- "remove": "",
89
- "clear": ""
90
- };
91
-
92
- // Trả về emoji tương ứng hoặc giữ nguyên nếu không có trong map
93
- return reactionMap[reaction.toLowerCase()] || reaction;
94
- }
95
-
96
- // Hàm kiểm tra một string có phải là emoji không - sử dụng regex đơn giản
97
- function isEmoji(str) {
98
- const emojiPattern = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/;
99
- return emojiPattern.test(str);
100
- }
101
-
102
- return function (reaction, messageID, callback, forceCustom = false) {
103
- try {
104
- return setMessageReaction(reaction, messageID, callback, forceCustom);
105
- } catch (error) {
106
- log.error("setMessageReaction", error);
107
- if (callback) callback(error);
108
- throw error;
109
- }
110
108
  };
111
- };
109
+ };