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 danssrc/. 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
↻ 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 parimport { 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
Ouvrezsrc/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
/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.
/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.tsdéclare/diceaussi bien quesrc/commands/dice.tsle ferait. Discord ne voit jamais vos dossiers. - Un fichier qui ne déclare rien est à vous.
shared.tscontient le code que plusieurs fichiers partagent ; importez-le comme n’importe quel fichier. - Un fichier peut déclarer plusieurs choses.
warn.tspeut contenir la commande/warn, le bouton qu’elle affiche et l’événement qui l’enregistre, chacun exporté sous son propre nom.
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 syncles 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.