fca-neokex-fix 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +220 -0
- package/LICENSE +26 -0
- package/README.md +346 -0
- package/THEME_FEATURES.md +137 -0
- package/examples/README.md +131 -0
- package/examples/apply-ai-theme.js +127 -0
- package/examples/check-current-theme.js +74 -0
- package/examples/simple-bot.js +114 -0
- package/examples/test-bot.js +752 -0
- package/examples/test-logging.js +85 -0
- package/examples/theme-usage-example.js +53 -0
- package/index.js +2 -0
- package/package.json +105 -0
- package/src/apis/addExternalModule.js +24 -0
- package/src/apis/addUserToGroup.js +108 -0
- package/src/apis/changeAdminStatus.js +148 -0
- package/src/apis/changeArchivedStatus.js +61 -0
- package/src/apis/changeAvatar.js +103 -0
- package/src/apis/changeBio.js +69 -0
- package/src/apis/changeBlockedStatus.js +54 -0
- package/src/apis/changeGroupImage.js +136 -0
- package/src/apis/changeThreadColor.js +116 -0
- package/src/apis/comment.js +207 -0
- package/src/apis/createAITheme.js +129 -0
- package/src/apis/createNewGroup.js +79 -0
- package/src/apis/createPoll.js +73 -0
- package/src/apis/deleteMessage.js +44 -0
- package/src/apis/deleteThread.js +52 -0
- package/src/apis/editMessage.js +70 -0
- package/src/apis/emoji.js +124 -0
- package/src/apis/fetchThemeData.js +65 -0
- package/src/apis/follow.js +81 -0
- package/src/apis/forwardMessage.js +52 -0
- package/src/apis/friend.js +243 -0
- package/src/apis/gcmember.js +122 -0
- package/src/apis/gcname.js +123 -0
- package/src/apis/gcrule.js +119 -0
- package/src/apis/getAccess.js +111 -0
- package/src/apis/getBotInfo.js +88 -0
- package/src/apis/getBotInitialData.js +43 -0
- package/src/apis/getFriendsList.js +79 -0
- package/src/apis/getMessage.js +423 -0
- package/src/apis/getTheme.js +104 -0
- package/src/apis/getThemeInfo.js +96 -0
- package/src/apis/getThreadHistory.js +239 -0
- package/src/apis/getThreadInfo.js +257 -0
- package/src/apis/getThreadList.js +222 -0
- package/src/apis/getThreadPictures.js +58 -0
- package/src/apis/getUserID.js +83 -0
- package/src/apis/getUserInfo.js +495 -0
- package/src/apis/getUserInfoV2.js +146 -0
- package/src/apis/handleMessageRequest.js +50 -0
- package/src/apis/httpGet.js +63 -0
- package/src/apis/httpPost.js +89 -0
- package/src/apis/httpPostFormData.js +69 -0
- package/src/apis/listenMqtt.js +796 -0
- package/src/apis/listenSpeed.js +170 -0
- package/src/apis/logout.js +63 -0
- package/src/apis/markAsDelivered.js +47 -0
- package/src/apis/markAsRead.js +95 -0
- package/src/apis/markAsReadAll.js +41 -0
- package/src/apis/markAsSeen.js +70 -0
- package/src/apis/mqttDeltaValue.js +330 -0
- package/src/apis/muteThread.js +45 -0
- package/src/apis/nickname.js +132 -0
- package/src/apis/notes.js +163 -0
- package/src/apis/pinMessage.js +141 -0
- package/src/apis/produceMetaTheme.js +180 -0
- package/src/apis/realtime.js +161 -0
- package/src/apis/removeUserFromGroup.js +117 -0
- package/src/apis/resolvePhotoUrl.js +58 -0
- package/src/apis/searchForThread.js +154 -0
- package/src/apis/sendMessage.js +281 -0
- package/src/apis/sendMessageMqtt.js +188 -0
- package/src/apis/sendTypingIndicator.js +41 -0
- package/src/apis/setMessageReaction.js +27 -0
- package/src/apis/setMessageReactionMqtt.js +61 -0
- package/src/apis/setThreadTheme.js +260 -0
- package/src/apis/setThreadThemeMqtt.js +94 -0
- package/src/apis/share.js +107 -0
- package/src/apis/shareContact.js +66 -0
- package/src/apis/stickers.js +257 -0
- package/src/apis/story.js +181 -0
- package/src/apis/theme.js +233 -0
- package/src/apis/unfriend.js +47 -0
- package/src/apis/unsendMessage.js +17 -0
- package/src/database/appStateBackup.js +189 -0
- package/src/database/models/index.js +56 -0
- package/src/database/models/thread.js +31 -0
- package/src/database/models/user.js +32 -0
- package/src/database/threadData.js +101 -0
- package/src/database/userData.js +90 -0
- package/src/engine/client.js +91 -0
- package/src/engine/models/buildAPI.js +109 -0
- package/src/engine/models/loginHelper.js +326 -0
- package/src/engine/models/setOptions.js +53 -0
- package/src/utils/auth-helpers.js +149 -0
- package/src/utils/autoReLogin.js +169 -0
- package/src/utils/axios.js +290 -0
- package/src/utils/clients.js +270 -0
- package/src/utils/constants.js +396 -0
- package/src/utils/formatters/data/formatAttachment.js +370 -0
- package/src/utils/formatters/data/formatDelta.js +153 -0
- package/src/utils/formatters/index.js +159 -0
- package/src/utils/formatters/value/formatCookie.js +91 -0
- package/src/utils/formatters/value/formatDate.js +36 -0
- package/src/utils/formatters/value/formatID.js +16 -0
- package/src/utils/formatters.js +1067 -0
- package/src/utils/headers.js +199 -0
- package/src/utils/index.js +151 -0
- package/src/utils/monitoring.js +358 -0
- package/src/utils/rateLimiter.js +380 -0
- package/src/utils/tokenRefresh.js +311 -0
- package/src/utils/user-agents.js +238 -0
|
@@ -0,0 +1,752 @@
|
|
|
1
|
+
const { login } = require('../index');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
const APPSTATE_PATH = path.join(__dirname, '../test/appstate.json');
|
|
6
|
+
const appState = JSON.parse(fs.readFileSync(APPSTATE_PATH, 'utf8'));
|
|
7
|
+
|
|
8
|
+
const PREFIX = '/';
|
|
9
|
+
const ADMIN_ID = null; // Set to your user ID to restrict some commands
|
|
10
|
+
|
|
11
|
+
console.log('🤖 NeoKEX-FCA Test Bot Starting...\n');
|
|
12
|
+
|
|
13
|
+
login({ appState }, (err, api) => {
|
|
14
|
+
if (err) {
|
|
15
|
+
console.error('❌ Login failed:', err);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
console.log('✅ Login successful!');
|
|
20
|
+
const botID = api.getCurrentUserID();
|
|
21
|
+
console.log(`🤖 Bot ID: ${botID}\n`);
|
|
22
|
+
|
|
23
|
+
api.listenMqtt((err, event) => {
|
|
24
|
+
if (err) {
|
|
25
|
+
console.error('MQTT Error:', err);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (event.type === 'message' && event.body) {
|
|
30
|
+
const { threadID, messageID, senderID, body, isGroup } = event;
|
|
31
|
+
|
|
32
|
+
if (senderID === botID) return;
|
|
33
|
+
|
|
34
|
+
if (!body.startsWith(PREFIX)) return;
|
|
35
|
+
|
|
36
|
+
const args = body.slice(PREFIX.length).trim().split(/\s+/);
|
|
37
|
+
const command = args.shift().toLowerCase();
|
|
38
|
+
|
|
39
|
+
console.log(`📨 Command: ${command} from ${senderID} in ${threadID}`);
|
|
40
|
+
|
|
41
|
+
handleCommand(api, command, args, event);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
console.log('🎧 Bot is listening for commands...');
|
|
46
|
+
console.log(`📝 Use prefix: ${PREFIX}`);
|
|
47
|
+
console.log('💡 Example: /help\n');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
async function handleCommand(api, command, args, event) {
|
|
51
|
+
const { threadID, messageID, senderID, isGroup } = event;
|
|
52
|
+
try {
|
|
53
|
+
switch (command) {
|
|
54
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
55
|
+
// 📌 BASIC COMMANDS
|
|
56
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
57
|
+
case 'help':
|
|
58
|
+
case 'commands':
|
|
59
|
+
await api.sendMessage(`🤖 NeoKEX-FCA Test Bot Commands
|
|
60
|
+
|
|
61
|
+
📌 BASIC
|
|
62
|
+
${PREFIX}help - Show this menu
|
|
63
|
+
${PREFIX}ping - Test response time
|
|
64
|
+
${PREFIX}about - Bot information
|
|
65
|
+
|
|
66
|
+
👤 USER INFO
|
|
67
|
+
${PREFIX}me - Your user info
|
|
68
|
+
${PREFIX}userid <name> - Get user ID by name
|
|
69
|
+
${PREFIX}friends - List your friends
|
|
70
|
+
${PREFIX}userv2 <userID> - Get detailed user info (v2)
|
|
71
|
+
${PREFIX}bio <text> - Change your bio
|
|
72
|
+
|
|
73
|
+
💬 THREAD COMMANDS
|
|
74
|
+
${PREFIX}info - Thread information
|
|
75
|
+
${PREFIX}history [limit] - Get message history
|
|
76
|
+
${PREFIX}members - List thread members
|
|
77
|
+
${PREFIX}photo - Thread photo URL
|
|
78
|
+
${PREFIX}threads - List your threads
|
|
79
|
+
${PREFIX}themeinfo - Get current theme info
|
|
80
|
+
${PREFIX}mute - Toggle mute for this thread
|
|
81
|
+
${PREFIX}archive - Toggle archive status
|
|
82
|
+
${PREFIX}deletethis - Delete this thread
|
|
83
|
+
|
|
84
|
+
🎨 THEMES
|
|
85
|
+
${PREFIX}themes - List all available themes
|
|
86
|
+
${PREFIX}theme <name> - Change thread theme
|
|
87
|
+
${PREFIX}color <hex> - Change thread color
|
|
88
|
+
${PREFIX}changetheme <prompt> - Generate & apply AI theme
|
|
89
|
+
|
|
90
|
+
✏️ THREAD SETTINGS
|
|
91
|
+
${PREFIX}name <name> - Change thread name
|
|
92
|
+
${PREFIX}emoji <emoji> - Change thread emoji
|
|
93
|
+
${PREFIX}nickname <@mention> <nickname> - Set nickname
|
|
94
|
+
|
|
95
|
+
📎 MESSAGING
|
|
96
|
+
${PREFIX}typing - Send typing indicator
|
|
97
|
+
${PREFIX}react <emoji> - React to this message
|
|
98
|
+
${PREFIX}unsend - Unsend this message
|
|
99
|
+
${PREFIX}edit <text> - Edit this message
|
|
100
|
+
${PREFIX}forward <threadID> - Forward this message
|
|
101
|
+
${PREFIX}poll <question> | <option1> | <option2> - Create poll
|
|
102
|
+
${PREFIX}pin - Pin this message
|
|
103
|
+
${PREFIX}unpin - Unpin this message
|
|
104
|
+
${PREFIX}markread - Mark thread as read
|
|
105
|
+
${PREFIX}markreadall - Mark all threads as read
|
|
106
|
+
|
|
107
|
+
👥 GROUP MANAGEMENT
|
|
108
|
+
${PREFIX}creategroup <name> | <userID1> | <userID2> - Create group
|
|
109
|
+
${PREFIX}adduser <userID> - Add user to group
|
|
110
|
+
${PREFIX}removeuser <userID> - Remove user from group
|
|
111
|
+
${PREFIX}groupimage - Info about changing group image
|
|
112
|
+
|
|
113
|
+
🔗 SOCIAL
|
|
114
|
+
${PREFIX}block <userID> - Block a user
|
|
115
|
+
${PREFIX}unblock <userID> - Unblock a user
|
|
116
|
+
${PREFIX}addfriend <userID> - Add friend
|
|
117
|
+
${PREFIX}removefriend <userID> - Remove friend
|
|
118
|
+
${PREFIX}follow <userID> - Follow user
|
|
119
|
+
${PREFIX}unfollow <userID> - Unfollow user
|
|
120
|
+
${PREFIX}sharecontact <userID> - Share contact
|
|
121
|
+
|
|
122
|
+
🔍 SEARCH
|
|
123
|
+
${PREFIX}searchthread <query> - Search threads
|
|
124
|
+
|
|
125
|
+
📊 STATS & ADMIN
|
|
126
|
+
${PREFIX}status - Bot status
|
|
127
|
+
${PREFIX}test - Run quick API test
|
|
128
|
+
${PREFIX}logout - Logout bot`, threadID);
|
|
129
|
+
break;
|
|
130
|
+
|
|
131
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
132
|
+
// 📌 BASIC COMMANDS
|
|
133
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
134
|
+
case 'ping':
|
|
135
|
+
const start = Date.now();
|
|
136
|
+
await api.sendMessage('🏓 Pong!', threadID, () => {
|
|
137
|
+
const latency = Date.now() - start;
|
|
138
|
+
api.sendMessage(`⏱️ Response time: ${latency}ms`, threadID);
|
|
139
|
+
});
|
|
140
|
+
break;
|
|
141
|
+
|
|
142
|
+
case 'about':
|
|
143
|
+
await api.sendMessage(`🤖 NeoKEX-FCA Test Bot
|
|
144
|
+
|
|
145
|
+
📦 Library: NeoKEX-FCA v4.4.4
|
|
146
|
+
✅ Success Rate: 98.2%
|
|
147
|
+
🔒 Security: 0 vulnerabilities
|
|
148
|
+
🎯 Tested APIs: 77 functions
|
|
149
|
+
|
|
150
|
+
Built to test and demonstrate the comprehensive API capabilities of NeoKEX-FCA.`, threadID);
|
|
151
|
+
break;
|
|
152
|
+
|
|
153
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
154
|
+
// 👤 USER INFO COMMANDS
|
|
155
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
156
|
+
case 'me':
|
|
157
|
+
const myInfo = await api.getUserInfo(senderID);
|
|
158
|
+
const user = myInfo[senderID];
|
|
159
|
+
await api.sendMessage(`👤 Your Information
|
|
160
|
+
|
|
161
|
+
Name: ${user.name}
|
|
162
|
+
ID: ${senderID}
|
|
163
|
+
Username: ${user.vanity || 'None'}
|
|
164
|
+
Profile: https://facebook.com/${senderID}`, threadID);
|
|
165
|
+
break;
|
|
166
|
+
|
|
167
|
+
case 'friends':
|
|
168
|
+
const friends = await api.getFriendsList();
|
|
169
|
+
const friendsList = friends.slice(0, 10).map((f, i) => `${i + 1}. ${f.fullName}`).join('\n');
|
|
170
|
+
await api.sendMessage(`👥 Your Friends (showing first 10/${friends.length})
|
|
171
|
+
|
|
172
|
+
${friendsList}
|
|
173
|
+
|
|
174
|
+
Total: ${friends.length} friends`, threadID);
|
|
175
|
+
break;
|
|
176
|
+
|
|
177
|
+
case 'userid':
|
|
178
|
+
if (args.length === 0) {
|
|
179
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}userid <name>`, threadID);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
const name = args.join(' ');
|
|
183
|
+
const uid = await api.getUserID(name);
|
|
184
|
+
await api.sendMessage(`🔍 User ID for "${name}": ${uid}`, threadID);
|
|
185
|
+
break;
|
|
186
|
+
|
|
187
|
+
case 'userv2':
|
|
188
|
+
if (args.length === 0) {
|
|
189
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}userv2 <userID>`, threadID);
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
const targetUserID = args[0];
|
|
193
|
+
const userInfoV2 = await api.getUserInfoV2(targetUserID);
|
|
194
|
+
const v2User = userInfoV2[targetUserID];
|
|
195
|
+
if (v2User) {
|
|
196
|
+
await api.sendMessage(`👤 Detailed User Info (v2)
|
|
197
|
+
|
|
198
|
+
Name: ${v2User.name || 'Unknown'}
|
|
199
|
+
ID: ${targetUserID}
|
|
200
|
+
Username: ${v2User.vanity || 'None'}
|
|
201
|
+
Gender: ${v2User.gender || 'Unknown'}
|
|
202
|
+
Is Friend: ${v2User.isFriend ? 'Yes' : 'No'}
|
|
203
|
+
Profile: https://facebook.com/${targetUserID}`, threadID);
|
|
204
|
+
} else {
|
|
205
|
+
await api.sendMessage(`❌ Could not fetch user info for ${targetUserID}`, threadID);
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
|
|
209
|
+
case 'bio':
|
|
210
|
+
if (args.length === 0) {
|
|
211
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}bio <text>`, threadID);
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
const bioText = args.join(' ');
|
|
215
|
+
await api.changeBio(bioText);
|
|
216
|
+
await api.sendMessage(`✅ Bio changed to: ${bioText}`, threadID);
|
|
217
|
+
break;
|
|
218
|
+
|
|
219
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
220
|
+
// 💬 THREAD COMMANDS
|
|
221
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
222
|
+
case 'info':
|
|
223
|
+
const threadInfo = await api.getThreadInfo(threadID);
|
|
224
|
+
await api.sendMessage(`💬 Thread Information
|
|
225
|
+
|
|
226
|
+
Name: ${threadInfo.threadName || 'Unnamed'}
|
|
227
|
+
ID: ${threadID}
|
|
228
|
+
Type: ${isGroup ? 'Group' : 'Direct Message'}
|
|
229
|
+
Members: ${threadInfo.participantIDs?.length || 0}
|
|
230
|
+
Messages: ${threadInfo.messageCount || 'Unknown'}
|
|
231
|
+
Emoji: ${threadInfo.emoji || '👍'}`, threadID);
|
|
232
|
+
break;
|
|
233
|
+
|
|
234
|
+
case 'history':
|
|
235
|
+
const limit = parseInt(args[0]) || 5;
|
|
236
|
+
const history = await api.getThreadHistory(threadID, limit);
|
|
237
|
+
const messages = history.map((msg, i) =>
|
|
238
|
+
`${i + 1}. ${msg.senderName}: ${msg.body?.substring(0, 50) || '[Attachment]'}`
|
|
239
|
+
).join('\n');
|
|
240
|
+
await api.sendMessage(`📜 Recent Messages (${limit}):
|
|
241
|
+
|
|
242
|
+
${messages}`, threadID);
|
|
243
|
+
break;
|
|
244
|
+
|
|
245
|
+
case 'members':
|
|
246
|
+
const info = await api.getThreadInfo(threadID);
|
|
247
|
+
const memberInfo = await api.getUserInfo(info.participantIDs);
|
|
248
|
+
const memberList = Object.values(memberInfo).map((m, i) =>
|
|
249
|
+
`${i + 1}. ${m.name}`
|
|
250
|
+
).join('\n');
|
|
251
|
+
await api.sendMessage(`👥 Thread Members:
|
|
252
|
+
|
|
253
|
+
${memberList}
|
|
254
|
+
|
|
255
|
+
Total: ${info.participantIDs.length} members`, threadID);
|
|
256
|
+
break;
|
|
257
|
+
|
|
258
|
+
case 'photo':
|
|
259
|
+
const photos = await api.getThreadPictures(threadID, 0, 1);
|
|
260
|
+
if (photos.length > 0) {
|
|
261
|
+
await api.sendMessage(`📸 Thread Photo: ${photos[0].uri}`, threadID);
|
|
262
|
+
} else {
|
|
263
|
+
await api.sendMessage(`❌ No thread photo available`, threadID);
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
|
|
267
|
+
case 'threads':
|
|
268
|
+
const threadList = await api.getThreadList(20, null);
|
|
269
|
+
const threadListFormatted = threadList.slice(0, 10).map((t, i) =>
|
|
270
|
+
`${i + 1}. ${t.name || 'Unnamed'} (${t.threadID})`
|
|
271
|
+
).join('\n');
|
|
272
|
+
await api.sendMessage(`📋 Your Threads (showing 10/${threadList.length}):
|
|
273
|
+
|
|
274
|
+
${threadListFormatted}`, threadID);
|
|
275
|
+
break;
|
|
276
|
+
|
|
277
|
+
case 'themeinfo':
|
|
278
|
+
const currentThemeInfo = await api.getThemeInfo(threadID);
|
|
279
|
+
await api.sendMessage(`🎨 Current Theme Info
|
|
280
|
+
|
|
281
|
+
Thread: ${currentThemeInfo.threadName || 'Unnamed'}
|
|
282
|
+
Color: ${currentThemeInfo.color || 'Default'}
|
|
283
|
+
Emoji: ${currentThemeInfo.emoji || '👍'}
|
|
284
|
+
Theme ID: ${currentThemeInfo.theme_id || 'Default'}`, threadID);
|
|
285
|
+
break;
|
|
286
|
+
|
|
287
|
+
case 'mute':
|
|
288
|
+
const currentInfo = await api.getThreadInfo(threadID);
|
|
289
|
+
const isMuted = currentInfo.muteUntil > Date.now();
|
|
290
|
+
await api.muteThread(threadID, isMuted ? -1 : 9999999999);
|
|
291
|
+
await api.sendMessage(`🔇 Thread ${isMuted ? 'unmuted' : 'muted'}`, threadID);
|
|
292
|
+
break;
|
|
293
|
+
|
|
294
|
+
case 'archive':
|
|
295
|
+
const archiveThreadInfo = await api.getThreadInfo(threadID);
|
|
296
|
+
const isArchived = archiveThreadInfo.isArchived;
|
|
297
|
+
await api.changeArchivedStatus(threadID, !isArchived);
|
|
298
|
+
await api.sendMessage(`📦 Thread ${isArchived ? 'unarchived' : 'archived'}`, threadID);
|
|
299
|
+
break;
|
|
300
|
+
|
|
301
|
+
case 'deletethis':
|
|
302
|
+
await api.sendMessage(`⚠️ Deleting this thread in 3 seconds...`, threadID);
|
|
303
|
+
setTimeout(async () => {
|
|
304
|
+
await api.deleteThread(threadID);
|
|
305
|
+
}, 3000);
|
|
306
|
+
break;
|
|
307
|
+
|
|
308
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
309
|
+
// 🎨 THEME COMMANDS
|
|
310
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
311
|
+
case 'themes':
|
|
312
|
+
const allThemes = await api.getTheme(threadID);
|
|
313
|
+
const themeList = allThemes.slice(0, 15).map((t, i) =>
|
|
314
|
+
`${i + 1}. ${t.name} (ID: ${t.id})`
|
|
315
|
+
).join('\n');
|
|
316
|
+
await api.sendMessage(`🎨 Available Themes (showing 15/${allThemes.length}):
|
|
317
|
+
|
|
318
|
+
${themeList}
|
|
319
|
+
|
|
320
|
+
Use ${PREFIX}theme <name> to apply`, threadID);
|
|
321
|
+
break;
|
|
322
|
+
|
|
323
|
+
case 'theme':
|
|
324
|
+
if (args.length === 0) {
|
|
325
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}theme <name or ID>`, threadID);
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
const themeName = args.join(' ');
|
|
329
|
+
const themesList = await api.getTheme(threadID);
|
|
330
|
+
const selectedTheme = themesList.find(t =>
|
|
331
|
+
t.name.toLowerCase().includes(themeName.toLowerCase()) ||
|
|
332
|
+
t.id === themeName
|
|
333
|
+
);
|
|
334
|
+
if (selectedTheme) {
|
|
335
|
+
await api.sendMessage(`🎨 Applying theme: ${selectedTheme.name}...`, threadID);
|
|
336
|
+
await api.setThreadThemeMqtt(threadID, selectedTheme.id);
|
|
337
|
+
await api.sendMessage(`✅ Theme changed to: ${selectedTheme.name}`, threadID);
|
|
338
|
+
} else {
|
|
339
|
+
await api.sendMessage(`❌ Theme not found. Use ${PREFIX}themes to see available themes`, threadID);
|
|
340
|
+
}
|
|
341
|
+
break;
|
|
342
|
+
|
|
343
|
+
case 'color':
|
|
344
|
+
if (args.length === 0) {
|
|
345
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}color <hex color>
|
|
346
|
+
Example: ${PREFIX}color #0084ff`, threadID);
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
const color = args[0];
|
|
350
|
+
await api.changeThreadColor(color, threadID);
|
|
351
|
+
await api.sendMessage(`🎨 Thread color changed to: ${color}`, threadID);
|
|
352
|
+
break;
|
|
353
|
+
|
|
354
|
+
case 'aitheme':
|
|
355
|
+
case 'changetheme':
|
|
356
|
+
if (args.length === 0) {
|
|
357
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}changetheme <AI prompt>
|
|
358
|
+
Example: ${PREFIX}changetheme ocean sunset vibes
|
|
359
|
+
Example: ${PREFIX}changetheme purple pink galaxy stars`, threadID);
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
const aiPrompt = args.join(' ');
|
|
363
|
+
await api.sendMessage(`🎨 Generating AI theme: "${aiPrompt}"...`, threadID);
|
|
364
|
+
|
|
365
|
+
try {
|
|
366
|
+
// Step 1: Generate AI theme
|
|
367
|
+
const aiThemes = await api.createAITheme(aiPrompt);
|
|
368
|
+
|
|
369
|
+
if (!aiThemes || aiThemes.length === 0) {
|
|
370
|
+
await api.sendMessage(`❌ No themes generated. AI theme feature may not be available for your account.
|
|
371
|
+
Try using ${PREFIX}themes to see standard themes.`, threadID);
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const generatedTheme = aiThemes[0];
|
|
376
|
+
await api.sendMessage(`✅ Theme generated!
|
|
377
|
+
Name: ${generatedTheme.accessibility_label || aiPrompt}
|
|
378
|
+
ID: ${generatedTheme.id}
|
|
379
|
+
|
|
380
|
+
Applying theme...`, threadID);
|
|
381
|
+
|
|
382
|
+
// Step 2: Apply the theme using MQTT
|
|
383
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
await api.setThreadThemeMqtt(threadID, generatedTheme.id);
|
|
387
|
+
await api.sendMessage(`🎉 AI theme applied successfully!`, threadID);
|
|
388
|
+
} catch (applyError) {
|
|
389
|
+
console.error('❌ Theme Application Error:', applyError.message);
|
|
390
|
+
await api.sendMessage(`⚠️ Theme generated but failed to apply: ${applyError.message}
|
|
391
|
+
|
|
392
|
+
You can try applying it manually using theme ID: ${generatedTheme.id}`, threadID);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error('❌ AI Theme Generation Error:', error.message || error);
|
|
397
|
+
await api.sendMessage(`❌ Error generating AI theme: ${error.message || 'Unknown error'}
|
|
398
|
+
|
|
399
|
+
This feature may not be available for your account.
|
|
400
|
+
Try using ${PREFIX}themes for standard themes instead.`, threadID);
|
|
401
|
+
}
|
|
402
|
+
break;
|
|
403
|
+
|
|
404
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
405
|
+
// ✏️ THREAD SETTINGS
|
|
406
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
407
|
+
case 'name':
|
|
408
|
+
if (args.length === 0) {
|
|
409
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}name <new name>`, threadID);
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
const newName = args.join(' ');
|
|
413
|
+
await api.setThreadName(newName, threadID);
|
|
414
|
+
await api.sendMessage(`✅ Thread name changed to: ${newName}`, threadID);
|
|
415
|
+
break;
|
|
416
|
+
|
|
417
|
+
case 'emoji':
|
|
418
|
+
if (args.length === 0) {
|
|
419
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}emoji <emoji>
|
|
420
|
+
Example: ${PREFIX}emoji 🔥`, threadID);
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
await api.changeThreadEmoji(args[0], threadID);
|
|
424
|
+
await api.sendMessage(`✅ Thread emoji changed to: ${args[0]}`, threadID);
|
|
425
|
+
break;
|
|
426
|
+
|
|
427
|
+
case 'nickname':
|
|
428
|
+
const mentions = event.mentions;
|
|
429
|
+
if (!mentions || mentions.length === 0 || args.length < 2) {
|
|
430
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}nickname @mention <nickname>`, threadID);
|
|
431
|
+
break;
|
|
432
|
+
}
|
|
433
|
+
const targetID = Object.keys(mentions)[0];
|
|
434
|
+
const nickname = args.slice(1).join(' ');
|
|
435
|
+
await api.changeNickname(nickname, threadID, targetID);
|
|
436
|
+
await api.sendMessage(`✅ Nickname changed to: ${nickname}`, threadID);
|
|
437
|
+
break;
|
|
438
|
+
|
|
439
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
440
|
+
// 📎 MESSAGING COMMANDS
|
|
441
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
442
|
+
case 'typing':
|
|
443
|
+
await api.sendTypingIndicator(threadID);
|
|
444
|
+
await api.sendMessage('✅ Typing indicator sent!', threadID);
|
|
445
|
+
break;
|
|
446
|
+
|
|
447
|
+
case 'react':
|
|
448
|
+
if (args.length === 0) {
|
|
449
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}react <emoji>`, threadID);
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
await api.setMessageReaction(args[0], messageID);
|
|
453
|
+
break;
|
|
454
|
+
|
|
455
|
+
case 'unsend':
|
|
456
|
+
await api.unsendMessage(messageID);
|
|
457
|
+
break;
|
|
458
|
+
|
|
459
|
+
case 'poll':
|
|
460
|
+
const pollData = args.join(' ').split('|').map(s => s.trim());
|
|
461
|
+
if (pollData.length < 3) {
|
|
462
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}poll <question> | <option1> | <option2>
|
|
463
|
+
Example: ${PREFIX}poll Pizza or Burger? | Pizza | Burger`, threadID);
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
const [question, ...options] = pollData;
|
|
467
|
+
await api.createPoll(question, threadID, { options });
|
|
468
|
+
break;
|
|
469
|
+
|
|
470
|
+
case 'edit':
|
|
471
|
+
if (args.length === 0) {
|
|
472
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}edit <new text>`, threadID);
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
const newText = args.join(' ');
|
|
476
|
+
await api.editMessage(newText, messageID);
|
|
477
|
+
await api.sendMessage(`✅ Message edited to: "${newText}"`, threadID);
|
|
478
|
+
break;
|
|
479
|
+
|
|
480
|
+
case 'forward':
|
|
481
|
+
if (args.length === 0) {
|
|
482
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}forward <threadID>`, threadID);
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
const targetThreadID = args[0];
|
|
486
|
+
await api.forwardMessage(messageID, targetThreadID);
|
|
487
|
+
await api.sendMessage(`✅ Message forwarded to thread ${targetThreadID}`, threadID);
|
|
488
|
+
break;
|
|
489
|
+
|
|
490
|
+
case 'pin':
|
|
491
|
+
await api.pin('pin', threadID, messageID);
|
|
492
|
+
await api.sendMessage(`📌 Message pinned!`, threadID);
|
|
493
|
+
break;
|
|
494
|
+
|
|
495
|
+
case 'unpin':
|
|
496
|
+
await api.pin('unpin', threadID, messageID);
|
|
497
|
+
await api.sendMessage(`📌 Message unpinned!`, threadID);
|
|
498
|
+
break;
|
|
499
|
+
|
|
500
|
+
case 'markread':
|
|
501
|
+
await api.markAsRead(threadID, true);
|
|
502
|
+
await api.sendMessage(`✅ Thread marked as read`, threadID);
|
|
503
|
+
break;
|
|
504
|
+
|
|
505
|
+
case 'markreadall':
|
|
506
|
+
await api.markAsReadAll();
|
|
507
|
+
await api.sendMessage(`✅ All threads marked as read`, threadID);
|
|
508
|
+
break;
|
|
509
|
+
|
|
510
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
511
|
+
// 👥 GROUP MANAGEMENT COMMANDS
|
|
512
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
513
|
+
case 'creategroup':
|
|
514
|
+
const groupData = args.join(' ').split('|').map(s => s.trim());
|
|
515
|
+
if (groupData.length < 2) {
|
|
516
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}creategroup <name> | <userID1> | <userID2>
|
|
517
|
+
Example: ${PREFIX}creategroup My Group | 100001 | 100002`, threadID);
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
520
|
+
const [groupName, ...userIDs] = groupData;
|
|
521
|
+
await api.createNewGroup(userIDs, groupName);
|
|
522
|
+
await api.sendMessage(`✅ Group "${groupName}" created with ${userIDs.length} members`, threadID);
|
|
523
|
+
break;
|
|
524
|
+
|
|
525
|
+
case 'adduser':
|
|
526
|
+
if (!isGroup) {
|
|
527
|
+
await api.sendMessage(`❌ This command only works in group chats`, threadID);
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
530
|
+
if (args.length === 0) {
|
|
531
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}adduser <userID>`, threadID);
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
const userToAdd = args[0];
|
|
535
|
+
await api.addUserToGroup(userToAdd, threadID);
|
|
536
|
+
await api.sendMessage(`✅ User ${userToAdd} added to group`, threadID);
|
|
537
|
+
break;
|
|
538
|
+
|
|
539
|
+
case 'removeuser':
|
|
540
|
+
if (!isGroup) {
|
|
541
|
+
await api.sendMessage(`❌ This command only works in group chats`, threadID);
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
if (args.length === 0) {
|
|
545
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}removeuser <userID>`, threadID);
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
const userToRemove = args[0];
|
|
549
|
+
await api.removeUserFromGroup(userToRemove, threadID);
|
|
550
|
+
await api.sendMessage(`✅ User ${userToRemove} removed from group`, threadID);
|
|
551
|
+
break;
|
|
552
|
+
|
|
553
|
+
case 'groupimage':
|
|
554
|
+
if (!isGroup) {
|
|
555
|
+
await api.sendMessage(`❌ This command only works in group chats`, threadID);
|
|
556
|
+
break;
|
|
557
|
+
}
|
|
558
|
+
await api.sendMessage(`ℹ️ Note: changeGroupImage requires a readable stream (file), not a URL.
|
|
559
|
+
Example: api.changeGroupImage(fs.createReadStream('image.jpg'), threadID)`, threadID);
|
|
560
|
+
break;
|
|
561
|
+
|
|
562
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
563
|
+
// 🔗 SOCIAL COMMANDS
|
|
564
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
565
|
+
case 'block':
|
|
566
|
+
if (args.length === 0) {
|
|
567
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}block <userID>`, threadID);
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
570
|
+
const userToBlock = args[0];
|
|
571
|
+
await api.changeBlockedStatus(userToBlock, true);
|
|
572
|
+
await api.sendMessage(`🚫 User ${userToBlock} has been blocked`, threadID);
|
|
573
|
+
break;
|
|
574
|
+
|
|
575
|
+
case 'unblock':
|
|
576
|
+
if (args.length === 0) {
|
|
577
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}unblock <userID>`, threadID);
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
580
|
+
const userToUnblock = args[0];
|
|
581
|
+
await api.changeBlockedStatus(userToUnblock, false);
|
|
582
|
+
await api.sendMessage(`✅ User ${userToUnblock} has been unblocked`, threadID);
|
|
583
|
+
break;
|
|
584
|
+
|
|
585
|
+
case 'addfriend':
|
|
586
|
+
if (args.length === 0) {
|
|
587
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}addfriend <userID>`, threadID);
|
|
588
|
+
break;
|
|
589
|
+
}
|
|
590
|
+
const friendToAdd = args[0];
|
|
591
|
+
await api.friend(friendToAdd, true);
|
|
592
|
+
await api.sendMessage(`✅ Friend request sent to ${friendToAdd}`, threadID);
|
|
593
|
+
break;
|
|
594
|
+
|
|
595
|
+
case 'removefriend':
|
|
596
|
+
if (args.length === 0) {
|
|
597
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}removefriend <userID>`, threadID);
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
const friendToRemove = args[0];
|
|
601
|
+
await api.unfriend(friendToRemove);
|
|
602
|
+
await api.sendMessage(`✅ Removed ${friendToRemove} from friends`, threadID);
|
|
603
|
+
break;
|
|
604
|
+
|
|
605
|
+
case 'follow':
|
|
606
|
+
if (args.length === 0) {
|
|
607
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}follow <userID>`, threadID);
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
const userToFollow = args[0];
|
|
611
|
+
await api.follow(userToFollow, true);
|
|
612
|
+
await api.sendMessage(`✅ Now following ${userToFollow}`, threadID);
|
|
613
|
+
break;
|
|
614
|
+
|
|
615
|
+
case 'unfollow':
|
|
616
|
+
if (args.length === 0) {
|
|
617
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}unfollow <userID>`, threadID);
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
const userToUnfollow = args[0];
|
|
621
|
+
await api.follow(userToUnfollow, false);
|
|
622
|
+
await api.sendMessage(`✅ Unfollowed ${userToUnfollow}`, threadID);
|
|
623
|
+
break;
|
|
624
|
+
|
|
625
|
+
case 'sharecontact':
|
|
626
|
+
if (args.length === 0) {
|
|
627
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}sharecontact <userID> [message]
|
|
628
|
+
Example: ${PREFIX}sharecontact 100001234567890 Check out this contact!`, threadID);
|
|
629
|
+
break;
|
|
630
|
+
}
|
|
631
|
+
const contactUserID = args[0];
|
|
632
|
+
const contactMessage = args.slice(1).join(' ') || '';
|
|
633
|
+
api.shareContact(contactMessage, contactUserID, threadID);
|
|
634
|
+
await api.sendMessage(`✅ Contact card for user ${contactUserID} shared in this thread`, threadID);
|
|
635
|
+
break;
|
|
636
|
+
|
|
637
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
638
|
+
// 🔍 SEARCH COMMANDS
|
|
639
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
640
|
+
case 'searchthread':
|
|
641
|
+
if (args.length === 0) {
|
|
642
|
+
await api.sendMessage(`❌ Usage: ${PREFIX}searchthread <query>`, threadID);
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
const threadQuery = args.join(' ');
|
|
646
|
+
const searchResults = await api.searchForThread(threadQuery);
|
|
647
|
+
if (searchResults.length === 0) {
|
|
648
|
+
await api.sendMessage(`❌ No threads found for "${threadQuery}"`, threadID);
|
|
649
|
+
} else {
|
|
650
|
+
const searchResultsFormatted = searchResults.slice(0, 5).map((t, i) =>
|
|
651
|
+
`${i + 1}. ${t.name} (${t.threadID})`
|
|
652
|
+
).join('\n');
|
|
653
|
+
await api.sendMessage(`🔍 Thread search results:
|
|
654
|
+
|
|
655
|
+
${searchResultsFormatted}
|
|
656
|
+
|
|
657
|
+
Found: ${searchResults.length} threads`, threadID);
|
|
658
|
+
}
|
|
659
|
+
break;
|
|
660
|
+
|
|
661
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
662
|
+
// 📊 STATUS COMMANDS
|
|
663
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
664
|
+
case 'status':
|
|
665
|
+
const status = api.getTokenRefreshStatus();
|
|
666
|
+
const uptime = process.uptime();
|
|
667
|
+
const hours = Math.floor(uptime / 3600);
|
|
668
|
+
const minutes = Math.floor((uptime % 3600) / 60);
|
|
669
|
+
await api.sendMessage(`📊 Bot Status
|
|
670
|
+
|
|
671
|
+
⏱️ Uptime: ${hours}h ${minutes}m
|
|
672
|
+
🔄 Token Refresh: ${status.isRefreshing ? 'Active' : 'Idle'}
|
|
673
|
+
📅 Last Refresh: ${status.lastRefreshTime ? new Date(status.lastRefreshTime).toLocaleString() : 'Never'}
|
|
674
|
+
📈 Refresh Count: ${status.refreshCount}
|
|
675
|
+
✅ MQTT: Connected`, threadID);
|
|
676
|
+
break;
|
|
677
|
+
|
|
678
|
+
case 'test':
|
|
679
|
+
await api.sendMessage('🧪 Running quick API test...', threadID);
|
|
680
|
+
const testResults = [];
|
|
681
|
+
|
|
682
|
+
try {
|
|
683
|
+
await api.getUserInfo(senderID);
|
|
684
|
+
testResults.push('✅ getUserInfo');
|
|
685
|
+
} catch (e) {
|
|
686
|
+
testResults.push('❌ getUserInfo');
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
try {
|
|
690
|
+
await api.getThreadInfo(threadID);
|
|
691
|
+
testResults.push('✅ getThreadInfo');
|
|
692
|
+
} catch (e) {
|
|
693
|
+
testResults.push('❌ getThreadInfo');
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
try {
|
|
697
|
+
await api.getTheme(threadID);
|
|
698
|
+
testResults.push('✅ getTheme');
|
|
699
|
+
} catch (e) {
|
|
700
|
+
testResults.push('❌ getTheme');
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
try {
|
|
704
|
+
await api.sendTypingIndicator(threadID);
|
|
705
|
+
testResults.push('✅ sendTypingIndicator');
|
|
706
|
+
} catch (e) {
|
|
707
|
+
testResults.push('❌ sendTypingIndicator');
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
await api.sendMessage(`🧪 Test Results:
|
|
711
|
+
|
|
712
|
+
${testResults.join('\n')}
|
|
713
|
+
|
|
714
|
+
${testResults.filter(r => r.startsWith('✅')).length}/${testResults.length} tests passed`, threadID);
|
|
715
|
+
break;
|
|
716
|
+
|
|
717
|
+
case 'logout':
|
|
718
|
+
await api.sendMessage('👋 Logging out bot...', threadID);
|
|
719
|
+
await api.logout();
|
|
720
|
+
console.log('Bot logged out');
|
|
721
|
+
process.exit(0);
|
|
722
|
+
break;
|
|
723
|
+
|
|
724
|
+
default:
|
|
725
|
+
await api.sendMessage(`❓ Unknown command: ${command}
|
|
726
|
+
Type ${PREFIX}help for available commands`, threadID);
|
|
727
|
+
}
|
|
728
|
+
} catch (error) {
|
|
729
|
+
console.error(`\n❌ ERROR in command /${command}:`);
|
|
730
|
+
console.error(` Message: ${error.message}`);
|
|
731
|
+
console.error(` Stack:`, error.stack);
|
|
732
|
+
console.error(` Thread ID: ${threadID}`);
|
|
733
|
+
console.error(` Sender ID: ${senderID}`);
|
|
734
|
+
console.error(` Args:`, args);
|
|
735
|
+
|
|
736
|
+
await api.sendMessage(`❌ Error executing /${command}:
|
|
737
|
+
${error.message || 'Unknown error occurred'}
|
|
738
|
+
|
|
739
|
+
If this persists, check the console logs for details.`, threadID).catch(err => {
|
|
740
|
+
console.error('Failed to send error message:', err.message);
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
746
|
+
console.error('⚠️ Unhandled Rejection:', reason);
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
process.on('SIGINT', () => {
|
|
750
|
+
console.log('\n\n👋 Bot shutting down gracefully...');
|
|
751
|
+
process.exit(0);
|
|
752
|
+
});
|