forked from AlmostEfficient/FaucetBot
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
131 lines (110 loc) · 3.71 KB
/
index.js
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
const { Client, Collection, Intents } = require('discord.js');
const { token, approvedRoles, CHAIN_COOLDOWN } = require('./config.json');
const fs = require('fs');
const isAddress = require('./utils/address');
const Keyv = require('keyv');
const { KeyvFile } = require('keyv-file');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MEMBERS] });
// Create Keyv instances for each supported chain
const keyvArb = new Keyv({
store: new KeyvFile({
filename: `keyv-data.json`, // File for Arbitrum Sepolia
})
});
const keyvMove = new Keyv({
store: new KeyvFile({
filename: `keyv-data-move.json`, // File for Move chain
})
});
const keyvBera = new Keyv({
store: new KeyvFile({
filename: `keyv-data-bera.json`, // File for Bera chain
})
});
// Command and event handling
client.commands = new Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
const eventFiles = fs.readdirSync('./events').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.data.name, command);
}
for (const file of eventFiles) {
const event = require(`./events/${file}`);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
let keyv;
let address;
let cooldown;
// Rate limiting and cooldowns for faucet requests
if (command.data.name === 'faucet') {
address = interaction.options.getString('address').trim();
const chain = interaction.options.getString('chain').trim().toLowerCase();
switch (chain) {
case 'arb':
keyv = keyvArb;
cooldown = CHAIN_COOLDOWN.arb
break;
case 'move':
keyv = keyvMove;
cooldown = CHAIN_COOLDOWN.move
break;
case 'bera':
keyv = keyvBera;
cooldown = CHAIN_COOLDOWN.bera
break;
default:
return interaction.reply('Unsupported chain specified. Use `arb`, `move`, or `bera`.');
}
if (!isAddress(address)) {
return interaction.reply('Please enter a valid Ethereum Address');
}
// Check if user has requested before
if (!approvedRoles.some(role => interaction.member.roles.cache.has(role))) {
const lastRequested = await keyv.get(interaction.user.id);
if (lastRequested) {
return interaction.reply(`You can only request funds once.`);
}
}
if (chain === 'move') {
// Check last transaction timestamp
const currentlyFauceting = await keyv.get('currentlyFauceting');
if (currentlyFauceting) {
return interaction.reply('Please wait until the current withdraw is finished.');
}
} else {
// Check last transaction timestamp
const lastTx = await keyv.get('lastTx');
if (lastTx + cooldown > Date.now()) {
const timeLeft = cooldown - (Date.now() - lastTx);
return interaction.reply(`Please wait ${cooldown / 1000} seconds between requests to prevent nonce issues. Try again in ${timeLeft / 1000}s.`);
}
}
}
try {
if (command.data.name === 'faucet') {
await keyv.set('currentlyFauceting', true);
await keyv.set('lastTx', Date.now());
}
await command.execute(interaction);
if (command.data.name === 'faucet') {
await keyv.set('currentlyFauceting', false);
if (!approvedRoles.some(role => interaction.member.roles.cache.has(role))) {
await keyv.set(interaction.user.id, address);
}
}
} catch (error) {
console.error(error);
await keyv.set('currentlyFauceting', false);
await interaction.followUp({ content: error.message });
}
});
client.login(token);