Passer au contenu principal
Votre projet tourne. Avant de le modifier, faites-en le tour : un projet ChapterJS est petit, et une fois que vous savez à quoi sert chaque fichier, vous savez où va chaque chose pour le reste du tutoriel.
buddy
.chapterjs
node_modules
public
src
presence.ts
.env
.env.example
.gitignore
package.json
tsconfig.json

La règle unique : ce qu’un fichier exporte dit ce qu’il est

Tout ce que fait votre bot vit dans src/. ChapterJS ne vous demande jamais d’enregistrer quoi que ce soit : il charge chaque fichier de src/, et ce que les fichiers exportent, fabriqué avec l’une de ses fonctions, est ce que le bot fait tourner. Le modèle a un fichier, src/presence.ts : ce que Discord affiche sous le nom de votre bot, « Getting ready ». Ajoutez-en un second, une commande, dans src/commands/ping.ts :
src/commands/ping.ts
Enregistrez : le terminal dit ↻ Reloaded in 12 ms, 1 command, a presence loaded, puis ↻ Commands updated on My Server, et /ping est sur votre serveur de test. Rien d’autre ne dit « ceci est une commande » : command() le dit. Son name est ce que les gens tapent après le /, et le fichier dit seulement ce que la commande fait. Changez name en 'hello', et la commande devient /hello ; déplacez le fichier vers src/fun/ping.ts, et rien ne change. C’est la règle pour tout ce que le framework fait tourner : Un fichier peut en déclarer plusieurs, et un fichier qui n’en déclare aucun n’est que du code : src/lib/, src/db/, tout ce que vous importez depuis les autres. Les modèles de create chapterjs font les deux : votre projet garde un dossier par sorte (src/commands/, et plus tard src/events/), et tickets met tout ce qui touche aux tickets dans src/tickets/ : la commande, le formulaire, les boutons, et leurs textes dans les deux langues. Un dossier n’est qu’un dossier. Pourquoi ce choix ? Parce que l’alternative, une liste quelque part qui dit « la commande /ping est dans ce fichier, l’événement de bienvenue dans celui-là », est une liste que vous devez tenir à jour à la main. Ici, il n’y a pas de liste. Ajouter une commande, c’est ajouter une déclaration ; en retirer une, c’est la supprimer.

Le même import partout

Chaque fichier commence par import { command } from 'chapterjs', ou event, button… Tous viennent du même paquet, chapterjs. Il n’y a rien d’autre à importer : pas de client, pas de configuration, pas de fichier du framework. Et chaque fonction sait à quoi s’attendre d’après ce que vous lui donnez : event({ name: 'memberJoin' }) donne un membre à votre fonction, event({ name: 'messageCreate' }) un message, avec la même ligne d’import.

.chapterjs/ : généré, ignoré, supprimable

Ce dossier est écrit par le framework, et git l’ignore. Il contient ce que votre projet ajoute aux types de chapterjs : les fichiers de public/ que asset() propose, vos langues, qui typent t, et vos commandes. Votre éditeur le lit pour compléter ce que vous tapez et souligner une erreur. Il garde aussi un petit cache (ce qui a été enregistré en dernier auprès de Discord, pour que relancer ne coûte rien) et, plus tard, le bot compilé. Il est écrit quand vous installez le projet (postinstall lance chapterjs sync) et à chaque démarrage de chapterjs dev. Si votre éditeur dit un jour qu’il ne connaît pas les fichiers de public/ ou vos textes, lancez chapterjs sync (pnpm chapterjs sync, ou l’équivalent) et rechargez l’éditeur. Vous pouvez aussi supprimer le dossier : il est reconstruit.

Essayer l’éditeur

Ouvrez src/commands/ping.ts dans votre éditeur, et dans run, tapez interaction. avec le point. L’éditeur liste tout ce qu’une interaction sait faire : reply, defer, edit, followUp, delete… Tapez maintenant interaction.replu('Pong !') avec une faute de frappe : c’est souligné avant même d’enregistrer, avec la méthode qu’il ne connaît pas. Voilà ce que veut dire « aucun type à écrire ». Vos fichiers sont en TypeScript, pour que l’éditeur puisse faire cela, mais chaque type vient du framework. Vous n’en écrivez jamais.
Si rien n’est souligné et rien n’est complété, votre éditeur ne lit pas les types. Dans Visual Studio Code, vérifiez que le dossier ouvert est bien le projet lui-même (celui qui contient package.json), pas un dossier au-dessus, et lancez chapterjs sync une fois.

Essayer le rechargement à chaud

Lancez le bot (pnpm dev) et laissez-le tourner. Changez la réponse dans src/commands/ping.ts :
src/commands/ping.ts
Enregistrez. Le terminal dit :
Utilisez à nouveau /ping dans Discord : la nouvelle réponse. Vous ne redémarrez jamais le bot pendant que vous l’écrivez : chaque fichier de src/ est surveillé, et un enregistrement le recharge, avec chaque fichier qui l’importe. Cassez maintenant le fichier exprès : supprimez 'Pong ! 🏓') pour que la ligne devienne await interaction.reply(;, et enregistrez.
Le bot est toujours en ligne, et /ping répond toujours avec la dernière version qui fonctionnait. Corrigez le fichier, enregistrez, et il se recharge. Une erreur ne fait jamais tomber le bot : vous pouvez essayer librement.

Les autres fichiers

chapterjs est la seule dépendance de votre bot. typescript et @types/node sont des dépendances de développement : elles vérifient votre code dans l’éditeur et avant une compilation, et ne sont pas nécessaires pour faire tourner le bot.

Vos fichiers, votre ordre

À mesure qu’un projet grandit, src/commands/ se remplit. Comme le framework lit ce que les fichiers exportent et non l’endroit où ils sont, rangez-les à votre façon :
src
fun
dice.ts
ping.ts
moderation
shared.ts
warn.ts
  • Un dossier n’est qu’un dossier. src/fun/dice.ts déclare /dice aussi bien que src/commands/dice.ts le ferait. Discord ne voit jamais vos dossiers.
  • Un fichier qui ne déclare rien est à vous. shared.ts contient le code que plusieurs fichiers partagent ; importez-le comme n’importe quel fichier.
  • Un fichier peut déclarer plusieurs choses. warn.ts peut contenir la commande /warn, le bouton qu’elle affiche et l’événement qui l’enregistre, chacun exporté sous son propre nom.
Une sous-commande est une affaire de name, pas de dossier : name: 'mod warn' est /mod warn, où que soit le fichier. C’est utilisé plus tard pour des commandes comme /mod ban.

Récapitulatif

  • Ce qu’un fichier exporte dit ce qu’il est : command({ name: 'ping' }) est /ping, et rien ne l’enregistre.
  • Chaque fichier importe ses fonctions de chapterjs, et chacune sait à quoi s’attendre d’après ce que vous lui donnez.
  • .chapterjs/ contient les types générés ; votre éditeur les lit ; chapterjs sync les réécrit.
  • Enregistrez un fichier et le bot l’utilise ; un fichier cassé garde sa dernière version qui fonctionnait.
  • Les dossiers et les noms de fichiers vous servent à ranger : le framework lit ce que les fichiers exportent.

Votre première commande

Écrire /dice de zéro, et voir ce que le framework vérifie pour vous.

Guide : Structure du projet

Chaque fichier et dossier, en bref.