Messages & salons
Cette page couvre Channel (salons texte/vocal), DMChannel (messages privés), Message, et EmbedBuilder.
Channel
Représente un salon texte ou vocal appartenant à un serveur (ou un canal DM/groupe — voir DMChannel plus bas, qui étend cette classe).
Propriétés
| Propriété | Type | Description |
|---|---|---|
id | string | publicId (Snowflake) du salon. |
name | string | Nom du salon. |
type | string | "TEXT", "VOICE", "DM", "GROUP_DM", "ANNOUNCEMENT"… |
serverId | string | null | ID du serveur parent — null pour un DM ou un groupe. |
webhooks | WebhookManager | (1.5.0+) Manager de webhooks scopé à ce salon — voir WebhookManager. |
Messagerie
send(content, embeds?): Promise<Message>
| Paramètre | Type | Requis | Description |
|---|---|---|---|
content | string | { content?: string; embeds?: Array<EmbedBuilder | EmbedPayload | Record<string, unknown>>; replyToId?: string } | Oui | Texte brut, ou un objet payload complet. |
embeds | Array<EmbedBuilder | EmbedPayload | Record<string, unknown>> | Non | Utilisé uniquement si content est une string — sinon ignoré (mettez embeds dans l'objet payload à la place). |
Envoie un message dans ce salon via le socket temps réel (délègue à client.sendMessage). Rejette si content est vide et qu'aucun embed n'est fourni, ou si le socket n'est pas connecté. La promesse résout avec l'objet Message créé, une fois l'accusé de réception du serveur reçu (timeout 10s — voir sendMessage).
await channel.send("Bonjour !");
await channel.send({ content: "Avec embed", embeds: [{ title: "Titre" }] });
await channel.send({ content: "En réponse", replyToId: someMessage.id });await channel.send("Bonjour !");
await channel.send({ content: "Avec embed", embeds: [{ title: "Titre" }] });
await channel.send({ content: "En réponse", replyToId: someMessage.id });fetchMessages(limit?, before?): Promise<Message[]>
| Paramètre | Type | Requis | Défaut | Description |
|---|---|---|---|---|
limit | number | Non | 50 | Nombre de messages à récupérer (le serveur plafonne généralement à 100). |
before | string | Non | — | Récupère les messages envoyés avant ce messagePublicId — utile pour paginer en remontant l'historique. |
Retourne les messages les plus récents en premier (ordre antéchronologique typique d'une API de chat). Un tableau vide si le salon n'a aucun message.
const recent = await channel.fetchMessages(20);
const older = await channel.fetchMessages(20, recent[recent.length - 1].publicId);const recent = await channel.fetchMessages(20);
const older = await channel.fetchMessages(20, recent[recent.length - 1].publicId);bulkDelete(messageIds): Promise<void>
Supprime plusieurs messages en un seul appel. Requiert la permission MANAGE_MESSAGES — sinon la requête rejette avec une erreur 403 côté API.
const spam = await channel.fetchMessages(50);
const toDelete = spam.filter(m => m.author.publicId === spammerId).map(m => m.publicId);
await channel.bulkDelete(toDelete);const spam = await channel.fetchMessages(50);
const toDelete = spam.filter(m => m.author.publicId === spammerId).map(m => m.publicId);
await channel.bulkDelete(toDelete);search(query, options?): Promise<Message[]>
| Paramètre | Type | Requis | Description |
|---|---|---|---|
query | string | Oui | Termes de recherche. |
options.limit | number | Non | Nombre maximum de résultats. |
options.before / options.after | string | Non | Bornes temporelles par messagePublicId. |
Équivalent scoped à ce salon de client.searchMessages(channel.id, query, options).
const results = await channel.search("roadmap", { limit: 10 });const results = await channel.search("roadmap", { limit: 10 });fetchPins(): Promise<Message[]>
Retourne la liste des messages épinglés dans ce salon, tableau vide si aucun. Ces trois méthodes (fetchMessages, search, fetchPins) enveloppent désormais leurs résultats dans de vraies instances Message (depuis la 1.5.0 — c'était auparavant du JSON brut).
Typing (indicateur de frappe)
sendTyping(): void
stopTyping(): voidÉmettent respectivement typing:start et typing:stop sur le socket. Synchrones (pas de Promise) — lèvent immédiatement une BloumeChatAuthError si le socket n'est pas établi, plutôt que de rejeter une promesse. L'indicateur de frappe expire automatiquement côté serveur après quelques secondes ; appelez sendTyping() en boucle si une opération longue est en cours.
channel.sendTyping();
const answer = await generateSlowAnswer(); // ex: appel à une IA externe
channel.stopTyping();
await channel.send(answer);channel.sendTyping();
const answer = await generateSlowAnswer(); // ex: appel à une IA externe
channel.stopTyping();
await channel.send(answer);Gestion du salon
edit(data: { name?: string; description?: string | null }): Promise<void>
setName(name: string): Promise<void>
delete(): Promise<void>
duplicate(): Promise<Channel>edit() ne modifie que les champs fournis. setName() est un raccourci vers edit({ name }). delete() supprime définitivement le salon et son historique — irréversible, aucune confirmation supplémentaire n'est demandée côté SDK. duplicate() crée une copie du salon avec les mêmes permissions et paramètres, et retourne le nouvel objet Channel.
delete() est irréversible
Il n'existe pas de corbeille — un salon supprimé et son historique de messages sont perdus définitivement. Confirmez toujours l'action côté utilisateur avant d'appeler channel.delete() dans un bot.
await channel.setName("annonces-2026");
const copy = await channel.duplicate();
console.log(`Copie créée : ${copy.name} (${copy.id})`);await channel.setName("annonces-2026");
const copy = await channel.duplicate();
console.log(`Copie créée : ${copy.name} (${copy.id})`);Invitations
createInvite(options?: { maxAge?: number; maxUses?: number }): Promise<GuildInviteDTO>Crée une invitation pointant vers ce salon spécifique. maxAge (secondes) et maxUses sont optionnels — omis, l'invitation n'expire pas et n'a pas de limite d'utilisation.
Permissions
fetchPermissionOverrides(): Promise<PermissionOverrideDTO[]>
editPermissions(targetId: string, type: "ROLE" | "MEMBER", options: { allow: bigint | string; deny: bigint | string }): Promise<void>
deletePermissionOverride(overrideId: string): Promise<void>
syncPermissions(): Promise<void>| Méthode | Description |
|---|---|
fetchPermissionOverrides() | Liste tous les overrides de permission (rôle ou membre) définis sur ce salon. |
editPermissions(targetId, type, options) | Crée ou met à jour un override pour un rôle ou un membre. allow/deny sont des bitmasks bigint (voir Permissions) — sérialisés automatiquement en string pour le transport JSON. |
deletePermissionOverride(overrideId) | Supprime un override par son ID (pas par targetId — récupérez l'ID de l'override via fetchPermissionOverrides() d'abord). |
syncPermissions() | Réinitialise les overrides de ce salon pour qu'ils héritent de ceux de sa catégorie parente. |
import { PermissionFlags } from "bloumechat";
await channel.editPermissions(roleId, "ROLE", {
allow: PermissionFlags.SEND_MESSAGES,
deny: PermissionFlags.MENTION_EVERYONE,
});const { PermissionFlags } = require("bloumechat");
await channel.editPermissions(roleId, "ROLE", {
allow: PermissionFlags.SEND_MESSAGES,
deny: PermissionFlags.MENTION_EVERYONE,
});Voir aussi
Pour la hiérarchie catégorie → salon et le bitmask complet, voir le guide Permissions et Category.
Webhooks
Depuis la 1.5.0 : channel.webhooks
Ces raccourcis délèguent maintenant à WebhookManager (channel.webhooks), qui expose aussi cache et delete(id).
fetchWebhooks(): Promise<Webhook[]>
createWebhook(options: { name: string; avatarUrl?: string }): Promise<Webhook>Voir la page dédiée Webhooks, emojis & invitations pour l'API complète de Webhook, y compris la gestion du token.
DMChannel extends Channel
Représente un canal de messages privés entre deux utilisateurs. Hérite de toutes les méthodes de Channel (send, fetchMessages, search, fetchPins…) — un DM se manipule exactement comme un salon de serveur pour l'envoi/lecture de messages. Les méthodes propres aux serveurs (permissions, webhooks, invitations) n'ont pas de sens sur un DM et échoueront côté API si appelées.
Propriétés
| Propriété | Type | Description |
|---|---|---|
recipientId | string | publicId du destinataire. Chaîne vide si la donnée recipient n'était pas présente à la construction. |
recipient | User | null | Objet User du destinataire, null s'il n'a pas encore été chargé. |
friendshipStatus | "ACCEPTED" | "PENDING" | "NONE" | État de la relation d'amitié avec ce destinataire au moment de la création de l'objet. |
friendshipId | string | undefined | ID de l'enregistrement d'amitié, si une relation existe. |
fetchRecipient(): Promise<User>
Recharge le profil complet du destinataire depuis l'API et met à jour this.recipient ainsi que le cache global client.users.cache. Utile quand le DMChannel a été construit avec des données partielles (par ex. reçu via l'event dmNew).
const dm = await client.createDM(userId);
await dm.send("Salut !");const dm = await client.createDM(userId);
await dm.send("Salut !");client.on("dmNew", async (data) => {
const dm = new DMChannel(client, data);
const recipient = await dm.fetchRecipient();
console.log(`Nouveau DM de ${recipient.tagString}`);
});client.on("dmNew", async (data) => {
const dm = new DMChannel(client, data);
const recipient = await dm.fetchRecipient();
console.log(`Nouveau DM de ${recipient.tagString}`);
});Message
Représente un message envoyé dans un salon ou un DM. Instancié automatiquement par le SDK sur messageCreate et fourni comme argument aux callbacks correspondants.
Propriétés
| Propriété | Type | Description |
|---|---|---|
id | string | publicId du message. |
content | string | Contenu texte, automatiquement décodé des entités HTML (<, >, &) que le serveur échappe à l'écriture pour se protéger du XSS — vous récupérez donc les caractères <, >, & d'origine, pas leur forme échappée. |
author | User | Auteur du message. |
channelId | string | ID du salon d'envoi. |
serverId | string | undefined | ID du serveur, absent pour un message envoyé en DM. |
createdAt | Date | Date d'envoi. |
embeds | Array<EmbedPayload | Record<string, unknown>> | Embeds attachés au message. |
fileUrl | string | null | URL d'une pièce jointe unique, null si aucune. |
channel | Channel (getter) | Résout depuis le cache si disponible, sinon construit un Channel minimal (id/serverId seulement — pas de name fiable) à la volée. |
guild | Guild | null (getter) | null si le message n'a pas de serverId (DM) ou si le serveur n'est pas en cache. |
member | Member | null (getter) | Résolu uniquement depuis le cache — recherche par (serverId, user.id), pas par ID de membership. Retourne null si le membre n'a pas déjà été chargé via client.members.fetch() ou guild.fetchChannels()/équivalent ; ce getter ne fait jamais d'appel réseau. |
message.member ne déclenche jamais de fetch
Si le membre n'est pas encore en cache, message.member renvoie null même si l'auteur est bel et bien membre du serveur. Appelez client.members.fetch(message.serverId, message.author.id) explicitement avant de lire message.member si vous avez besoin d'une garantie de fraîcheur.
Répondre, éditer, supprimer
reply(content, embeds?): Promise<Message>
Identique à channel.send() mais définit automatiquement replyToId sur this.id.
client.on("messageCreate", async (message) => {
if (message.content === "!ping") await message.reply("🏓 Pong !");
});client.on("messageCreate", async (message) => {
if (message.content === "!ping") await message.reply("🏓 Pong !");
});edit(options): Promise<Message>
| Paramètre | Type | Description |
|---|---|---|
options | string | EmbedBuilder | { content?: string; embeds?: Array<EmbedBuilder | EmbedPayload | Record<string, unknown>> } | Nouveau contenu et/ou embeds. |
Émet message:edit sur le socket (nécessite d'être connecté — sinon lève une BloumeChatAuthError). Met à jour this.content/this.embeds de façon optimiste (avant confirmation serveur) et retourne this. Il n'existe pas de mécanisme d'annulation si le serveur rejette l'édition (par ex. permissions insuffisantes) — dans ce cas l'état local reste désynchronisé jusqu'au prochain messageUpdate.
const sent = await channel.send("Chargement…");
await sent.edit("Terminé ✅");const sent = await channel.send("Chargement…");
await sent.edit("Terminé ✅");delete(): Promise<void>
Émet message:delete sur le socket. Lève une BloumeChatAuthError si le socket n'est pas établi.
Réactions
react(emoji: string): Promise<void>
clearReactions(): Promise<void>
fetchReactions(emoji: string): Promise<ReactionUserDTO[]>
awaitReactions(options?: { max?: number; time?: number }): Promise<MessageReactionEventData | null>| Méthode | Description |
|---|---|
react(emoji) | Ajoute une réaction. Accepte un emoji unicode ("👍") ou le nom d'un emoji personnalisé du serveur. |
clearReactions() | Retire toutes les réactions du message (nécessite généralement MANAGE_MESSAGES côté serveur). |
fetchReactions(emoji) | Retourne le détail des utilisateurs ayant réagi avec un emoji précis : { userPublicId, userName, userImage }[]. L'emoji est URL-encodé automatiquement. |
awaitReactions(options) | Attend un lot de réactions en temps réel, résout une seule fois (voir ci-dessous). |
createReactionCollector(options) | (4.2.0+) Collecte en continu les réactions sur le message via un ReactionCollector (on('collect', ...)), jusqu'à time/max ou .stop(). |
awaitReactions — attendre une réaction en direct
const msg = await channel.send("Réagissez avec 👍 dans les 30s !");
const result = await msg.awaitReactions({ max: 1, time: 30_000 });
if (result) console.log("Quelqu'un a réagi !");
else console.log("Personne n'a réagi à temps.");options.max arrête l'attente dès que ce nombre de réactions est atteint (compte tous les events messageReactionAdd reçus pour ce message, sans distinguer par emoji ni dédupliquer par utilisateur). options.time (ms) est un timeout — sans lui, la promesse peut rester en attente indéfiniment si max n'est jamais atteint. Sans aucune des deux options, résout immédiatement undefined (aucune attente réelle configurée). Résout avec null en cas de timeout, ou avec { messagePublicId, emoji, userPublicId } de la dernière réaction reçue.
Identique en JavaScript, sans annotation de type — channel.send, awaitReactions fonctionnent à l'exécution exactement de la même façon.
createReactionCollector — collecter plusieurs réactions dans la durée
const collector = msg.createReactionCollector({ time: 60_000 });
collector.on("collect", (reaction, user) => {
console.log(`${user.tagString} a réagi ${reaction.emoji}`);
});
collector.on("end", (reason) => console.log(`Terminé : ${reason}`));Contrairement à awaitReactions() (une seule résolution), le collector reste actif et émet collect pour chaque réaction correspondante jusqu'à ce que options.time s'écoule, que options.max collectes soient atteintes, ou que .stop() soit appelé manuellement. options.filter?: (reaction, user) => boolean permet de ne garder que certaines réactions (ex. un utilisateur précis).
Épingler
pin(): Promise<void>
unpin(): Promise<void>Appels REST (pas socket) vers /chat/:channelId/pin/:messageId.
EmbedBuilder
API fluent pour construire un embed riche, convertie en EmbedPayload via .toJSON() — appelé automatiquement quand un EmbedBuilder est passé à send()/reply()/edit(), donc vous n'avez normalement jamais besoin d'appeler .toJSON() vous-même.
Méthodes
| Méthode | Description |
|---|---|
setTitle(title: string | null) | Titre de l'embed. null le retire. |
setDescription(description: string | null) | Corps du texte. null le retire. |
setURL(url: string | null) | Rend le titre cliquable. null le retire. |
setTimestamp(timestamp?: Date | number | null) | Sans argument (ou undefined), utilise l'heure actuelle. null retire le timestamp. |
setColor(color: number | string | null) | Accepte un nombre décimal ou une chaîne hex ("#5e72e4", convertie automatiquement). null le retire. |
setFooter(options: EmbedFooter | null) | { text: string; iconUrl?: string }. null le retire. |
setImage(url: string | null) | Image principale, pleine largeur. |
setThumbnail(url: string | null) | Petite image en coin. |
setAuthor(options: EmbedAuthor | null) | { name: string; url?: string; iconUrl?: string }. |
addFields(...fields: EmbedField[]) | Ajoute un ou plusieurs champs à la suite des existants. |
setFields(...fields: EmbedField[]) | Remplace tous les champs existants. |
spliceFields(index, deleteCount, ...fields) | Insertion/suppression chirurgicale de champs, comme Array.prototype.splice. |
toJSON(): EmbedPayload | Sérialise en objet brut — appelé automatiquement par le SDK. |
EmbedField : { name: string; value: string; inline?: boolean }.
Toutes les méthodes setX retournent this, permettant le chaînage complet.
new EmbedBuilder()
.setTitle("Titre")
.setDescription("Description")
.setURL("https://bloumechat.com")
.setColor("#5e72e4") // hex string ou number
.setTimestamp() // maintenant, par défaut
.setAuthor({ name: "Auteur", iconUrl: "..." })
.setFooter({ text: "Pied de page" })
.setImage("https://...")
.setThumbnail("https://...")
.addFields({ name: "Champ", value: "Valeur", inline: true });new EmbedBuilder()
.setTitle("Titre")
.setDescription("Description")
.setURL("https://bloumechat.com")
.setColor("#5e72e4") // hex string ou number
.setTimestamp() // maintenant, par défaut
.setAuthor({ name: "Auteur", iconUrl: "..." })
.setFooter({ text: "Pied de page" })
.setImage("https://...")
.setThumbnail("https://...")
.addFields({ name: "Champ", value: "Valeur", inline: true });// Remplacer entièrement les champs d'un embed déjà construit
const embed = new EmbedBuilder().setTitle("Statut du build");
embed.setFields(
{ name: "Étape", value: "Tests", inline: true },
{ name: "Résultat", value: "✅ Réussi", inline: true },
);
await channel.send(embed);// Remplacer entièrement les champs d'un embed déjà construit
const embed = new EmbedBuilder().setTitle("Statut du build");
embed.setFields(
{ name: "Étape", value: "Tests", inline: true },
{ name: "Résultat", value: "✅ Réussi", inline: true },
);
await channel.send(embed);Voir aussi
ChannelManager— cache etfetch()des salons.WebhookManager—channel.webhooks, la forme complète (1.5.0+).- Webhooks, emojis & invitations — envoyer des messages sans compte bot connecté.
- Permissions — bitmask utilisé par
editPermissions(). - Gestion des erreurs —
BloumeChatAuthErroret les autres classes d'erreur. - Exemple : bot ping-pong — usage combiné de
reply,editetEmbedBuilder.
