A fine Luglio è stata pubblicata la nuovissima versione di discord.js, la famosa libreria JavaScript per creare Discord bot.
Con questa versione è possibile creare più facilmente slash commands per i nostri bot e in questa guida affronteremo tutti i passi per creare un bot con slash commands basilari e alla fine sarete pronti per crearne anche di nuovi!
Vi ricordo che potete entrare nel nostro server Discord per qualsiasi domanda e per tanto divertimento!
Sommario
- Sommario
- Preparazione
- Errori comuni
- Slash Commands
- Comando ping
- Importare i comandi
- Registrare i comandi
- Rispondere alle interazioni
- Risultato finale
- Aggiungere altri comandi
- Comandi globali
- Conclusione
Preparazione
Prima di tutto dobbiamo configurare il nostro spazio di lavoro.
Abbiamo già pubblicato una guida su questo che potete consultare qui.
Se ricevete degli errori potete consultare il prossimo paragrafo per risolverli.
Errori comuni
In questa sezione vi aiuteremo a risolvere gli errori più comuni che vi potrebbero capitare.
Vi ricordo che discord.js ha una guida ufficiale (in inglese) minimale che può comunque aiutarvi.
Termine ‘npm’ non riconosciuto come nome di cmdlet
Se, eseguendo comandi come npm init
, npm i
o npm run
ricevete un errore del tipo Termine \'npm\' non riconosciuto come nome di cmdlet, funzione, programma eseguibile o file script
, probabilmente Node.js non è stato installato correttamente. Reinstallatelo dalla pagina ufficiale. Al momento discord.js supporta sia la versione LTS che quella attuale perciò non fa molta differenza quale scegliate.
Dopo aver scaricato il file d’installazione assicuratevi di eseguirlo senza modificare alcuna opzione.
Dopo di che, riavviate qualsiasi terminal aperto e riprovate il comando desiderato.
Nel caso riceviate un errore del tipo Termine \'node\' non riconosciuto come nome di cmdlet, funzione, programma eseguibile o file script
, il problema potrebbe essere lo stesso e vi consigliamo la medesima soluzione.
AbortController is not defined / No such built-in module: node:timers/promises / Unexpected token ‘?’
Se ricevete un errore del genere è probabile che la vostra versione di Node.js non sia aggiornata e non supporta quindi discord.js v14.
Per risolvere questo problema, vi basterà aggiornare Node.js installando l’installer della versione più recente dal sito ufficiale. Vi ricordiamo che sia la versione LTS che l’ultima sono supportate.
TypeError: Cannot read properties of undefined (reading ‘FLAGS’)
In quest’ultima versione tutte le costanti sono state trasformate da SNAKE_CASE (es. BAN_MEMBERS
) in PascalCase (es. BanMembers
). Inoltre la costante Intents
è stata rinominata in IntentsBitField
.
Questo significa che il nostro vecchio codice dovrà essere modificato nel seguente modo:
const {
Client,
- Intents: { FLAGS },
+ IntentsBitField: { Flags },
} = require(\"discord.js\");
- const client = new Client({ intents: [FLAGS.GUILDS] });
+ const client = new Client({ intents: [Flags.Guilds] });
An invalid token was provided
Questo errore si presenta quando non abbiamo fornito un token valido per il login.
Assicuratevi di averlo quindi salvato correttamente nel vostro file .env
nel seguente modo:
DISCORD_TOKEN=il-tuo-token-va-qui
Slash Commands
Gli slash commands sono il nuovo modo per gli utenti di interagire con i bot. Questo metodo è ormai lo standard e i bot non potranno essere verificati (quindi essere aggiunti a più di 100 server) se utilizzano ancora comandi testuali.
In questa sezione vedremo come creare il nostro primo slash command e come registrarlo su Discord.
Prerequisiti
Innanzitutto è richiesto il modulo @discordjs/rest
per effettuare richieste attraverso l’API di Discord e, quindi, registrare i nostri comandi.
Installiamolo con il seguente comando:
npm i @discordjs/rest
Ci servirà poi una cartella dove salveremo tutti i nostri comandi, perciò creiamone una nel nostro progetto e chiamiamola commands
.
Comando ping
Iniziamo creando il nostro primo comando: /ping
.
Si tratterà semplicemente di un comando al quale il bot risponderà con \”Pong!\”.
Creiamo innanzitutto un file chiamato ping.js
nella cartella commands
.
Da questo file esporteremo due cose principalmente:
data
: i dati del nostro comando, creati grazie all’aiuto di discord.js;execute
: la funzione che sarà eseguita quando questo comando viene invocato.
Esportare i dati del comando
Procediamo, quindi, esportando i dati del comando. Per farlo avremo bisogno della funzione di discord.js SlashCommandBuilder
, dunque la importeremo all’inizio di questo nostro nuovo file:
const { SlashCommandBuilder } = require(\"discord.js\");
Ora abbiamo bisogno di esportare dei dati dal nostro file. Per farlo ci basterà specificare la proprietà module.exports
.
Aggiungiamo perciò la seguente linea al nostro codice:
module.exports = {};
A questo punto possiamo specificare la nostra proprietà data
all’interno dell’object che abbiamo creato.
Facciamolo creando una nuova istanza di SlashCommandBuilder
:
- module.exports = {};
+ module.exports = {
+ data: new SlashCommandBuilder(),
+ };
Non ricordi come funzionano le classi? Puoi consultare il nostro articolo a riguardo!
Ora dobbiamo impostare il nome e la descrizione del nostro comando.
Per farlo usiamo i metodi setName(name)
e setDescription(description)
:
module.exports = {
- data: new SlashCommandBuilder(),
+ data: new SlashCommandBuilder()
+ .setName(\"ping\")
+ .setDescription(\"Pong!\"),
}
Funzione del comando
Ora non ci resta altro che creare la funzione da eseguire quando il comando verrà invocato.
Per farlo aggiungiamo il metodo execute
al nostro object esportato, specificando come parametro l’interazione ricevuta e rispondendo con \”Pong!\”:
module.exports = {
data: new SlashCommandBuilder()
.setName(\"ping\")
.setDescription(\"Pong!\"),
+ async execute(interaction) {
+ await interaction.reply(\"Pong!\");
+ },
}
Importare i comandi
Ora abbiamo bisogno di importare il comando creato, assicurandoci che il codice sia in grado di importare automaticamente anche altri eventuali comandi che creeremo in futuro.
Questo può essere fatto nel file principale del nostro bot: index.js
.
Per salvare i comandi tutti i comandi creati useremo una Collezione, una classe creata da discord.js che estende le mappe, prendendone, di conseguenza, tutte le proprietà e i metodi, ma contenente anche altre prese dagli array. Se non sei familiare con le mappe, non preoccuparti, ti sarà tutto più chiaro andando avanti!
Salveremo questa collezione come proprietà del client
chiamandola commands
:
const {
Client,
IntentsBitField: { Flags },
+ Collection,
} = require(\"discord.js\");
const client = new Client({ intents: [Flags.Guilds] });
+ client.commands = new Collection();
Se ricevete un errore su Visual Studio Code del tipo Property ‘commands’ does not exist on type \’Client\’ è perché questa proprietà non è ufficialmente specificata da discord.js ma la stiamo aggiungendo noi.
Per risolvere questo problema basta modificare la linea dove dichiariamo il nostro client aggiungendo un type casting:
- const client = new Client({ intents: [Flags.Guilds] });
+ const client = /** @type {Client & { commands: Collection<string, any> }} */ (
+ new Client({ intents: [Flags.Guilds] })
+ );
Ora dobbiamo importare tutti file presenti nella cartella commands
(al momento solo uno, ma in futuro ovviamente ne aggiungeremo altri) e salvarli nella collezione appena creata. Per farlo dovremo leggere la cartella commands
per ricevere una lista dei file presenti e, per ogni file, importare i dati presenti e salvarli nella collezione.
Ad aiutarci ci sono i moduli built-in di Node.js fs
e path
che ci permetteranno, rispettivamente, di leggere i file presenti nella nostra cartella e di generare il percorso file completo ad essa:
const { readdirSync } = require(\"node:fs\");
const { join } = require(\"node:path\");
client.commands = new Collection();
+ const commandsPath = join(__dirname, \"commands\");
+
+ for (const file of readdirSync(commandsPath).filter((f) => f.endsWith(\".js\"))) {
+ const command = require(join(commandsPath, file));
+
+ client.commands.set(command.data.name, command);
+ }
Registrare i comandi
Per essere utilizzati, i comandi dovranno essere registrati tramite l’API di Discord. Farlo è molto semplice, infatti basterà creare un file a parte (che chiameremo deploy-commands.js
) nella directory principale del nostro bot.
Eseguiremo questo file ogni volta che vorremo registrare nuovamente i comandi su Discord, ossia ogni volta che modifichiamo qualche dato di un comando, ne aggiungiamo o rimuoviamo altri.
Ecco come si mostrerà questo script speciale (i commenti sono puramente esplicativi e possono essere rimossi tranquillamente):
// Importiamo le variabili d\'ambiente
const { env } = require(\"node:process\");
// Importiamo le funzioni necessarie a caricare i comandi
const { readdirSync } = require(\"node:fs\");
const { join } = require(\"node:path\");
// Importiamo il necessario da discord.js
const { REST } = require(\"@discordjs/rest\");
const { Routes } = require(\"discord.js\");
// Leggiamo i file presenti nella cartella dei comandi
const commands = [];
const commandsPath = join(__dirname, \"commands\");
const commandFiles = readdirSync(commandsPath).filter((file) => file.endsWith(\".js\"));
// Importiamo ogni comando, trasformiamolo in JSON (il formato in cui vengono inviati dati a Discord) e aggiungiamolo nell\'array `commands`
for (const file of commandFiles) {
const filePath = join(commandsPath, file);
const command = require(filePath);
commands.push(command.data.toJSON());
}
// Il REST ci permette di effettuare richieste verso l\'API di Discord
const rest = new REST({ version: \"10\" }).setToken(env.DISCORD_TOKEN);
// Registriamo i comandi nel nostro server
rest
.put(Routes.applicationGuildCommands(env.CLIENT_ID, env.GUILD_ID), { body: commands })
.then(() => console.log(\"Successfully registered application commands.\"))
.catch(console.error);
A questo punto abbiamo bisogno di creare delle variabili d’ambiente per salvare gli id del bot e del server dove registrare i comandi, perciò modifichiamo il file .env
aggiungendo due valori:
CLIENT_ID=idDelBot
GUILD_ID=idDelServer
Qualsiasi errore visualizzato nell’editor riguardo le variabili d’ambiente nel file deploy-commands.js
può essere tranquillamente ignorato.
Rispondere alle interazioni
L’ultima cosa che ci è rimasta da fare è di rispondere alle interazioni ricevute da discord. Per fare ciò, useremo l’evento interactionCreate
del client:
client.once(\"ready\", (onlineClient) =>
console.log(`Connesso con successo come ${onlineClient.user.tag}!`)
);
+ client.on(\"interactionCreate\", async (interaction) => {});
In questa funzione dovremo eseguire la funzione del comando utilizzato dall’utente. Per farlo ci basterà controllare la proprietà commandName
dell’interazione:
client.on(\"interactionCreate\", async (interaction) => {
+ if (!interaction.isChatInputCommand()) return;
+ const command = client.commands.get(interaction.commandName);
+
+ if (!command) return;
});
Adesso non ci resta altro che eseguire il comando e bloccare eventuali errori.
Questo può essere fatto facilmente con un try/catch
:
client.on(\"interactionCreate\", async (interaction) => {
if (!interaction.isChatInputCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
+ try {
+ await command.execute(interaction);
+ } catch (error) {
+ console.error(error);
+ }
});
Risultato finale
Se avete seguito attentamente l’articolo ora dovreste essere in grado di eseguire facilmente il vostro bot.
Per prima cosa registrate i comandi con il seguente comando:
node deploy-commands
Ora, se non avete ricevuto nessun errore e il messaggio “Successfully registered application commands.” è apparso nel terminal, i vostri comandi sono stati registrati con successo e siete pronti ad eseguire ufficialmente il bot:
node .
Provate nel vostro server ad eseguire il comando /ping
e controllate se la risposta è quella attesa.
Se ricevete degli errori sconosciuti o avete qualsiasi altro tipo di problema, potete chiedere direttamente a noi nel nostro server Discord!
Aggiungere altri comandi
Se volete aggiungere altri comandi la procedura è facilissima: vi basterà creare un nuovo file nella cartella commands
e seguire la stessa procedura del comando ping, modificando nome e descrizione, nonché la funzione execute
.
Inoltre, è possibile aggiungere opzioni ai comandi tramite i metodi .addStringOption()
, .addNumberOption()
, etc, della classe SlashCommandBuilder
.
Per più informazioni consulta il paragrafo dedicato sulla guida ufficiale di discord.js che contiene molti esempi, spiegando nel dettaglio anche come aggiungere scelte e subcommands.
Comandi globali
Attualmente abbiamo visto come registrare comandi per un server, ma è possibile anche registrare comandi globalmente, disponibili in tutti i server in cui è presente il bot.
Per farlo basta modificare solamente una riga nel file deploy-commands.js
:
rest
- .put(Routes.applicationGuildCommands(env.CLIENT_ID, env.GUILD_ID), { body: commands })
+ .put(Routes.applicationCommands(env.CLIENT_ID), { body: commands })
.then(() => console.log(\"Successfully registered application commands.\"))
.catch(console.error);
Non vi dimenticate di eseguire nuovamente il file per registrare i comandi.
Inoltre, questo metodo è molto più lento dei comandi per server in quanto può occorrere fino a un’ora prima che le nuove modifiche abbiano effetto su tutti i server, mentre i comandi per server hanno effetto immediato.
Conclusione
In questo articolo abbiamo creato il nostro primo slash commands e imparato a registrare automaticamente tutti i comandi.
Per qualsiasi ulteriore domanda o informazione potete entrare nel nostro server Discord!
Lascia un commento