-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
379 lines (332 loc) · 13 KB
/
index.js
File metadata and controls
379 lines (332 loc) · 13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
// Load environment variables from .env (no suppression)
require('dotenv').config();
const { Client } = require('fnbr');
const fetch = require('node-fetch');
const OWNER_USERNAME = process.env.OWNER_USERNAME;
const DEFAULTS = {
skin: 'CID_452_Athena_Commando_F_CyberFu',
backpack: 'BID_270_StreetDemon',
pickaxe: 'HalloweenScythe',
glider: 'Umbrella_Season_09',
emote: 'EID_TakeTheL',
level: 9999
};
const client = new Client({
auth: {
deviceAuth: {
accountId: process.env.DEVICE_AUTH_ACCOUNT_ID,
deviceId: process.env.DEVICE_AUTH_DEVICE_ID,
secret: process.env.DEVICE_AUTH_SECRET,
}
}
});
let lastMessageTime = Date.now();
const MOTIVATIONAL_INTERVAL = 10 * 60 * 1000; // 10 minutos
let isDancingEnabled = true;
let danceInterval = null;
const DANCE_REPEAT_TIME = 20000; // 20 segundos entre bailes
async function startContinuousDancing() {
if (danceInterval) {
clearInterval(danceInterval);
}
if (!isDancingEnabled) return;
console.log(`🕺 Starting continuous dance with emote: ${DEFAULTS.emote}`);
danceInterval = setInterval(async () => {
try {
if (client.party && client.party.me && isDancingEnabled) {
await client.party.me.setEmote(DEFAULTS.emote);
console.log(`💃 Dancing: ${DEFAULTS.emote}`);
}
} catch (error) {
handleError(error, 'Error while dancing');
}
}, DANCE_REPEAT_TIME);
}
function stopContinuousDancing() {
if (danceInterval) {
clearInterval(danceInterval);
danceInterval = null;
console.log('🛑 Dance stopped');
}
}
async function restoreDefaults(party) {
try {
console.log('🔄 Restoring default configuration...');
if (!party || !party.me) {
handleError(new Error('No party or party.me'), 'Error restoring defaults');
return;
}
await party.me.setLevel(DEFAULTS.level);
try { await party.me.setOutfit(DEFAULTS.skin); } catch (e) { handleError(e, 'Error setting skin'); }
try { await party.me.setBackpack(DEFAULTS.backpack); } catch (e) { handleError(e, 'Error setting backpack'); }
try { await party.me.setPickaxe(DEFAULTS.pickaxe); } catch (e) { handleError(e, 'Error setting pickaxe'); }
try { await party.me.setBanner(DEFAULTS.banner); } catch (e) { handleError(e, 'Error setting banner'); }
// The following features are not supported by fnbr.js and will be skipped:
// setContrail, setMusic, setLoadingScreen, setWrap, setSpray, setVehicle
// Only supported: setOutfit, setBackpack, setPickaxe, setBanner, setPet, setEmoji, setEmote, setLevel
try { await party.me.setPet(DEFAULTS.pet); } catch (e) { handleError(e, 'Error setting pet'); }
try { await party.me.setEmoji(DEFAULTS.emoji); } catch (e) { handleError(e, 'Error setting emoji'); }
try { await party.me.setEmote(DEFAULTS.emote); } catch (e) { handleError(e, 'Error setting emote'); }
setTimeout(() => { startContinuousDancing(); }, 3000);
} catch (generalError) {
handleError(generalError, 'General error restoring defaults');
}
}
// Improved error handler for user notification and logging
function handleError(error, context, msg) {
const contactMsg = '\n⚠️ Please contact Rocky (remplasoopcional@gmail.com) about this error so it can be fixed!';
const logMsg = `❌ [ERROR] ${context ? context + ': ' : ''}${error && error.message ? error.message : error}`;
console.error(logMsg);
if (error && error.stack) console.error('Stack:', error.stack);
const emojiMsg = `🚨 Oops! An error occurred.\n${logMsg}${contactMsg}`;
if (msg && typeof msg.reply === 'function') {
msg.reply(emojiMsg).catch(e => console.error('Error sending error notification:', e));
}
}
client.on('friend:request', async (friendRequest) => {
try {
await friendRequest.accept();
console.log(`🤝 Friend request accepted from: ${friendRequest.displayName}`);
} catch (error) {
handleError(error, friendRequest);
}
});
client.on('party:invite', async (invite) => {
try {
await invite.accept();
console.log(`🎉 Party invite accepted from: ${invite.sender.displayName}`);
} catch (error) {
handleError(error, invite.sender);
}
});
client.on('party:member:joined', async (member) => {
try {
console.log(`👤 ${member.displayName} joined the party`);
if (client.party && client.party.me && client.party.me.isLeader) {
console.log('👑 I am leader, restoring defaults...');
await restoreDefaults(client.party);
} else {
if (!client.party) console.warn('⚠️ No party available in party:member:joined');
if (!client.party?.me) console.warn('⚠️ No party.me available in party:member:joined');
}
} catch (error) {
handleError(error, member);
}
});
client.on('party:updated', async (party) => {
console.log('🔔 Party updated');
});
client.on('friend:message', async (msg) => {
try {
console.log(`✉️ Private message from ${msg.author.displayName}: "${msg.content}"`);
if (msg.author.displayName !== OWNER_USERNAME) {
console.log(`🚫 Message ignored (not from owner: ${OWNER_USERNAME})`);
return;
}
lastMessageTime = Date.now();
const content = msg.content.trim();
const party = msg.client.party;
const me = party && party.me;
console.log(`⚙️ Processing command: "${content}"`);
if (!me) {
console.log('⚠️ No party or party.me');
await msg.reply('I am not in a party or cannot change appearance now.');
return;
}
// PROCESAR COMANDOS
if (content.startsWith('/skin ')) {
const skin = content.replace('/skin ', '').trim();
console.log(`🎨 Changing skin to: ${skin}`);
try {
await me.setOutfit(skin);
await msg.reply(`Skin changed to ${skin}.`);
console.log('✅ Skin changed successfully');
} catch (error) {
handleError(error, msg);
await msg.reply(`Error changing skin: ${error.message}`);
}
} else if (content.startsWith('/backpack ')) {
const backpack = content.replace('/backpack ', '').trim();
console.log(`🎒 Changing backpack to: ${backpack}`);
try {
await me.setBackpack(backpack);
await msg.reply(`Backpack changed to ${backpack}.`);
console.log('✅ Backpack changed successfully');
} catch (error) {
handleError(error, msg);
await msg.reply(`Error changing backpack: ${error.message}`);
}
} else if (content.startsWith('/pickaxe ')) {
const pickaxe = content.replace('/pickaxe ', '').trim();
console.log(`⛏️ Changing pickaxe to: ${pickaxe}`);
try {
await me.setPickaxe(pickaxe);
await msg.reply(`Pickaxe changed to ${pickaxe}.`);
console.log('✅ Pickaxe changed successfully');
} catch (error) {
handleError(error, msg);
await msg.reply(`Error changing pickaxe: ${error.message}`);
}
} else if (content.startsWith('/glider ')) {
console.log('🪂 Glider command not supported');
await msg.reply('Sorry, I cannot change the glider in this version.');
} else if (content.startsWith('/emote ')) {
const emote = content.replace('/emote ', '').trim();
console.log(`😄 Doing temporary emote: ${emote}`);
// Desactivar baile automático temporalmente
const prevDancing = isDancingEnabled;
isDancingEnabled = false;
stopContinuousDancing();
try {
await me.setEmote(emote);
await msg.reply(`Emote performed: ${emote} (continuous dance will resume after)`);
console.log('✅ Emote performed successfully');
// Esperar duración típica de un emote (6s) y reanudar baile automático si estaba activo
setTimeout(() => {
if (prevDancing) {
isDancingEnabled = true;
startContinuousDancing();
console.log('🕺 Continuous dance resumed after temporary emote');
}
}, 6000);
} catch (error) {
handleError(error, msg);
await msg.reply(`Error with emote: ${error.message}`);
// Si falla, reanudar baile automático si estaba activo
if (prevDancing) {
isDancingEnabled = true;
startContinuousDancing();
}
}
} else if (content.startsWith('/level ')) {
const lvl = parseInt(content.replace('/level ', '').trim());
console.log(`🏆 Changing level to: ${lvl}`);
if (!isNaN(lvl)) {
try {
await me.setLevel(lvl);
await msg.reply(`Level changed to ${lvl}`);
console.log('✅ Level changed successfully');
} catch (error) {
handleError(error, msg);
await msg.reply(`Error changing level: ${error.message}`);
}
} else {
await msg.reply('Invalid level. Use a number.');
}
} else if (content === '/sync') {
await msg.reply('The /sync command has been disabled.');
} else if (content === '/dance') {
console.log('💃 Dance command received');
if (isDancingEnabled) {
isDancingEnabled = false;
stopContinuousDancing();
await msg.reply('Continuous dance DISABLED');
console.log('🛑 Dance disabled');
} else {
isDancingEnabled = true;
startContinuousDancing();
await msg.reply('Continuous dance ENABLED');
console.log('🟢 Dance enabled');
}
} else if (content === '/help') {
console.log('📜 Sending command list');
const helpMessage = `AVAILABLE COMMANDS:
/skin name → Change skin
/backpack name → Change backpack
/pickaxe name → Change pickaxe
/glider name → Change glider
/emote name → Perform emote
/level number → Change level
/dance → Enable/disable continuous dance
/default → Restore default configuration`;
await msg.reply(helpMessage);
console.log('✅ Command list sent');
} else if (content === '/default') {
console.log('🔄 Default command received');
await msg.reply('Restoring default configuration...');
await restoreDefaults(party);
await msg.reply('Default configuration restored!');
console.log('✅ Configuration restored');
} else {
await msg.reply('Unrecognized command. Use /help to see available commands.');
console.log('❓ Unrecognized command received');
}
} catch (err) {
handleError(err, msg);
try {
await msg.reply('An error occurred while processing your command.');
} catch (replyError) {
handleError(replyError, msg);
}
}
});
client.on('party:message', async (msg) => {
try {
console.log(`💬 Party chat message: ${msg.author.displayName}: "${msg.content}"`);
// Procesar comandos del owner desde el chat también
if (msg.author.displayName === OWNER_USERNAME && msg.content.startsWith('/')) {
console.log(`🛠️ Owner command in chat: "${msg.content}"`);
}
} catch (err) {
handleError(err, msg);
}
});
client.on('ready', async () => {
console.log(`✅ Bot connected successfully!`);
console.log(`👤 User: ${client.user.self._displayName}`);
console.log(`👑 Owner: ${OWNER_USERNAME}`);
console.log(`💃 Favorite dance: BOOGIE DOWN`);
// Esperar antes de configurar
setTimeout(async () => {
console.log('⏳ Applying initial configuration in 5 seconds...');
if (client.party && client.party.me) {
try {
await restoreDefaults(client.party);
} catch (error) {
handleError(error, client.party.me);
}
} else {
console.warn('⚠️ Party not ready, retrying...');
setTimeout(async () => {
if (client.party && client.party.me) {
try {
await restoreDefaults(client.party);
} catch (error) {
handleError(error, client.party.me);
}
}
}, 5000);
}
}, 5000);
// Aceptar solicitudes pendientes
if (client.friends && client.friends.requests) {
for (const req of client.friends.requests.values()) {
try {
await req.accept();
console.log(`🤝 Pending friend request accepted: ${req.displayName}`);
} catch (error) {
handleError(error, req);
}
}
}
});
client.on('error', (err) => {
handleError(err, null);
});
process.on('SIGINT', () => {
console.log('🛑 Shutting down bot...');
stopContinuousDancing();
process.exit(0);
});
process.on('SIGTERM', () => {
console.log('Shutting down bot...');
stopContinuousDancing();
process.exit(0);
});
console.log('==============================');
console.log('🤖 TryBotX for Fortnite');
console.log('©️ 2025 Rockyhubdev');
console.log('🌐 https://github.com/Rockyhubdev/TryBotX');
console.log('==============================');
console.log('🚀 Starting Fortnite bot...');
client.login();