Botanique/CONTRIBUTING.md
Mylloon a790ddf377
All checks were successful
Publish latest version / build (push) Successful in 2m11s
tests: use node:test (#210)
Close #201

Tests run much faster and we don't need as much as libs

Reviewed-on: #210
Co-authored-by: Mylloon <kennel.anri@tutanota.com>
Co-committed-by: Mylloon <kennel.anri@tutanota.com>
2024-12-14 11:43:09 +01:00

11 KiB

Comment contribuer ?

Ce guide contient méthodes et conseils sur comment aider le projet. Lisez attentivement si vous êtes un nouveau contributeur.

Ce guide n'est pas fixe et est mis à jour régulièrement. Si vous trouvez un problème quelconque, n'hésitez pas à le signaler par le biais d'un ticket ou à le corriger directement en soumettant une Pull Request.

Sommaire

Recevoir de l'aide

Si tu as besoin d'aide, tu peux poser ta question sur le Discord.

Langues

La langue par défaut est définie dans src/utils/client.ts dans client.config.default_lang.

La langue par défaut fait office de solution de secours dans le cas où une traduction est incomplète. On part donc du postulat que la langue par défaut contient toujours toutes les chaînes de caractère dont le bot a besoin.

La norme pour les nom dans les fichiers est la suivante :

  • Chaîne de charactère des commandes : c est utilisé pour Commande.

    • c_NOM-COMMANDE_name : Nom de la commande
    • c_NOM-COMMANDE_desc : Description de la commande
    • c_NOM-COMMANDE_optX_name : Nom de l'option X
    • c_NOM-COMMANDE_optX_desc : Description de l'option X
    • c_NOM-COMMANDE_subX_name : Nom de la sous-commande X
    • c_NOM-COMMANDE_subX_desc : Description de la sous-commande X
    • c_NOM-COMMANDEX : X le numéro de la chaîne de caractère

    Évidemment ça peut s'additionner, par exemple : c_NOM-COMMANDE_subX_optX_desc.

  • Chaîne de caractère des évènements : e est utilisé pour Evènements.

    • e_NOM-EVENEMENT_N : N le nom de la chaîne de caractère
  • Chaîne de caractère des utils : u est utilisé pour Utilitaires.

    • u_NOM-FICHIER-UTILS_N : N le nom de la chaîne de caractère

Ajouter une langue

  1. Créer un nouveau fichier dans src/locales/, le fichier doit être nommé langue.json avec langue suivant cette liste.
  2. Le contenu du fichier peut être copié du fichier de la langue par défaut, cf. au-dessus.
  3. Ce sont les valeurs des clés (le texte à gauche des :) qui doivent être traduits. Merci par avance !

    Ne vous forcez pas à tout traduire. Même une contribution avec une seule variable de modifiée compte !

  4. Une fois terminée, ouvrez une Pull Request.

Mettre à jour une langue

  1. Rechercher la langue dans le dossier src/locales/.
  2. Modifier/Ajouter des traductions comme expliquer au-dessus (à partir du 3.).

    Pensez à vérifier si de nouvelles valeurs n'ont pas été ajouté dans le fichier langue par défaut, cf. au-dessus.

Projet

Le code se trouve dans le dossier src/. Dans ce dossier il y a :

  • commands/ qui contient toutes les commandes, rangés par catégories
  • events/ qui contient tous les évènements, rangés par catégories
  • locales/ qui contient tous les fichiers de langue
  • modules/ qui contient les extensions utilisées, par exemple, pour utiliser la fonction capitalize() d'un string, il faut importer le fichier string.ts qui se trouve dans le dossier
  • utils/ qui contient toutes les fonctions utilitaires, rangés par fichiers

Les dossiers commands/ et events/ contiennent chacun un fichier loader.js qui charge respectivement les commandes et les évènements dans le bot.

Ajouter une commande

Pour ajouter une commande au bot, créez un fichier nom-de-la-commande.ts dans un sous dossier de src/commands/. Vous pouvez créer une nouvelle catégorie si votre commande n'entre dans aucune qui existe déjà.

Le contenu du fichier doit commencer comme suit :

import { SlashCommandBuilder } from "@discordjs/builders";
import { Client, ChatInputCommandInteraction } from "discord.js";
import { getLocale, getLocalizations } from "../../utils/locales";
import { getFilename } from "../../utils/misc";

export default {
  scope: () => [],

  data: (client: Client) => {
    const filename = getFilename(__filename);
    return new SlashCommandBuilder()
      .setName(filename.toLowerCase())
      .setDescription(client.locales.get(client.config.default_lang)!.get(`c_${filename}_desc`)!)
      .setNameLocalizations(getLocalizations(client, `c_${filename}_name`, true))
      .setDescriptionLocalizations(getLocalizations(client, `c_${filename}_desc`));
  },

  interaction: async (interaction: ChatInputCommandInteraction, client: Client) => {
    const loc = getLocale(client, interaction.locale);

    /* Votre code ici */
  },
};

Rapidement, cette structure comporte 3 éléments :

  • scope : une liste de guildId où la commande est disponible, si la liste est vide, la commande est disponible partout
  • data : représente les données envoyées à l'API de Discord
  • interaction : représente le comportement de la commande

Ce modèle vous permet de commencer rapidement votre commande, car il contient déjà tout ce qu'il faut pour le support des langues. Pensez bien à ne pas écrire directement vos chaînes de caractères ici, mais bien dans les fichiers de langues, c'est à ça que la variable loc sert.

Vous devez aussi ajouter obligatoirement :

  • "c_COMMANDE_name": "NOM" au fichier de langue, avec COMMANDE le nom de la commande et NOM le nom de votre commande.
  • "c_COMMANDE_desc": "DESCRIPTION" au fichier de langue, avec COMMANDE le nom de la commande et DESCRIPTION la description de votre commande.

Note : Il est possible d'ajouter de l'autocomplétion via un 4ᵉ élément : autocomplete.

Ajouter un évènement

Pour ajouter le support d'un évènement au bot, créez un fichier nom-evenement.ts dans un sous dossier de src/events/. Vous pouvez créer une nouvelle catégorie si votre commande n'entre dans aucune qui existe déjà.

Vous pouvez préciser que l'évènement ne sera déclenché qu'une seule fois avec

export const once = true;

De préférence, merci de mettre un lien en commentaire vers la documentation de discord.js de l'évènement (exemple ici pour l'évènement ready)

Player

Les évènements du player ont la même logique les autres, mais sont placés dans le dossier player.

Pour déboguer le player, il est possible d'ajouter un évènement debug, en voici un exemple :

import { GuildQueue } from "discord-player";

/** https://discord-player.js.org/docs/types/discord-player/GuildQueueEvents */
export default (_: GuildQueue, message: string) => {
  console.info(message);
};

Modèles

Les modèles sont gérés en dehors séparément du reste.

Boutons

Les boutons sont gérés en dehors séparément du reste

Chaque bouton à une implémentation séparée des autres, même s'ils sont dans le même message.

Contrairement aux autres éléments, les boutons doivent se faire collecter via la fonction collect juste après leur déclaration.

Autocomplétion

La réponse qu'attend Discord doit se faire obligatoirement sous 3 secondes. Pour se faire on peut utiliser un timeout avec une race.

let timeoutId: NodeJS.Timeout;
const delay = new Promise(function (_, reject) {
  timeoutId = setTimeout(function () {
    reject(new Error());
  }, 2900); // correspond au temps du timeout en ms
});

const resultat = await Promise.race([delay, commandeQuiRenvoieUnPromise])
  .then((res) => {
    clearTimeout(timeoutId);
    return resultatVoulu;
  })
  .catch(() => {
    return resultatErreur; // correspond à temps écoulé ou erreur de notre commande
  });

Modifier du code

Quand vous modifiez quelque chose, pensez à mettre-à-jour les langues. Si vous ne savez pas traduire dans une langue, ne vous forcez pas, supprimer simplement la traduction.

Pour commencer, vous pouvez jeter un œil aux tickets facilement résolvable.

  • De préférences, les fonctions, méthodes et variables seront écrites en anglais, ainsi que les commits afin que chacun puisse contribuer.

Soumettre ses modifications

  1. Pensez à bien commenter votre code (en anglais) pour que n'importe qui comprennent vos modifications. Vérifier bien dans tous les fichiers si ce que vous avez modifié n'est pas référencer ailleurs (exemple : si vous modifier une variable d'environnement, il faut penser à mettre à jour le README).

  2. N'oubliez pas d'utiliser les fichiers de langues pour vos chaînes de caractère, cf. cette partie pour plus de précisions.

  3. Veuillez tester vos modifications avant de les soumettre. Attention, ce n'est pas parce que vos modifications fonctionnent avec npm run debug qu'elles fonctionneront avec npm run main, ainsi que dans l'image Docker.

  4. Lorsque vous vous sentez confiant dans vos modifications, ouvrez une Pull Request afin que votre code puisse être revu et fusionné. Vous pouvez suivre cette condition de nommage, ça aide à s'y retrouver plus rapidement.

Explication

npm run debug exécute le code depuis le dossier src tandis que npm run main et l'image Docker le fait depuis le dossier dist.

Docker est cependant différent, car dans l'image, le dossier src est supprimé.

Gestion du dépôt

  • On ne push jamais directement sur la branche main.
  • Quand on merge des modifications vers main, on fait un squash, l'historique des modifications reste disponible dans le graphe.
  • De préférences, suivre ces conventions (cf. cette partie précédente).

Tester son code

Il est souhaité d'écrire des tests quand cela est possible.

import { fnReturnsTrue } from "../src/utils/file";

import { describe, it } from "node:test";
import assert from "node:assert/strict";

describe("test name", () => {
  {
    const name = "to be tested";
    it(name, () => {
      assert.strictEqual(fnReturnsTrue() /* function to test */, true /* expected result */);
    });
  }
});