DiscordJS
Intégrer la vérification des votes dans un bot Discord (JS)
Dans cet exemple, on crée une commande /vote qui :
Envoie un message avec :
un bouton “Voter sur DiscordTop” → ouvre la page de vote,
un bouton “Vérifier mon vote” → appelle l’API DiscordTop.
Si le vote est validé par l’API, vous pouvez appliquer vos propres récompenses :
donner un rôle,
ajouter de l’XP,
ouvrir l’accès à un salon privé, etc.
1. Pré-requis
Node.js 18+ (pour avoir
fetchintégré)Un bot Discord configuré (token)
Un token API DiscordTop (
api_token) associé à votre serveur - Comment trouvé ma clé ?
Packages :
npm install discord.js dotenv2. Configuration du projet
Créez un fichier .env à la racine :
DISCORD_TOKEN=VOTRE_TOKEN_BOT
DISCORD_CLIENT_ID=ID_CLIENT_DE_VOTRE_BOT
DISCORD_GUILD_ID=ID_DU_SERVEUR_DE_TEST
DTOP_API_TOKEN=VOTRE_CLE_API_DISCORDTOP
DTOP_GUILD_ID=ID_DU_SERVEUR_SUR_DTOP
DTOP_GUILD_IDest l’ID du serveur tel qu’il apparaît sur DiscordTop (en général, c’est le même que l’ID Discord).
3. Enregistrer la commande /vote
/voteCréez un fichier deploy-commands.js :
import 'dotenv/config';
import { REST, Routes, SlashCommandBuilder } from 'discord.js';
const commands = [
new SlashCommandBuilder()
.setName('vote')
.setDescription('Obtenir le lien de vote DiscordTop et vérifier votre vote.')
.toJSON(),
];
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
async function main() {
try {
console.log('🔁 Mise à jour des commandes (guild)…');
await rest.put(
Routes.applicationGuildCommands(
process.env.DISCORD_CLIENT_ID,
process.env.DISCORD_GUILD_ID
),
{ body: commands }
);
console.log('✅ Commandes enregistrées avec succès.');
} catch (error) {
console.error('❌ Erreur lors de l’enregistrement des commandes :', error);
}
}
main();Lancer une fois :
node deploy-commands.js4. Bot de base avec /vote + boutons
/vote + boutonsCréez un fichier index.js :
import 'dotenv/config';
import {
Client,
GatewayIntentBits,
Partials,
ButtonStyle,
ActionRowBuilder,
ButtonBuilder,
Events,
} from 'discord.js';
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers],
partials: [Partials.GuildMember],
});
// URL de vote DTOP (adapter si besoin)
function getDiscordTopVoteUrl() {
const guildId = process.env.DTOP_GUILD_ID;
return `https://discordtop.net/guild/${guildId}/vote`;
}
// Appel à l’API DTOP pour vérifier le vote
async function checkVoteOnDiscordTop(userId) {
const apiToken = process.env.DTOP_API_TOKEN;
const url = new URL('https://api.discordtop.net/v7/check-vote');
url.searchParams.set('discord_id', userId);
// Vous pouvez aussi ajouter &locale=fr si vous voulez forcer la langue
// url.searchParams.set('locale', 'fr');
const res = await fetch(url.toString(), {
method: 'GET',
headers: {
'Authorization': `Bearer ${apiToken}`,
'Accept-Language': 'fr-FR',
},
});
// On retourne la réponse brute + le JSON
let body = null;
try {
body = await res.json();
} catch {
body = null;
}
return { status: res.status, body };
}
client.once(Events.ClientReady, (c) => {
console.log(`✅ Connecté en tant que ${c.user.tag}`);
});
client.on(Events.InteractionCreate, async (interaction) => {
// Commande /vote
if (interaction.isChatInputCommand() && interaction.commandName === 'vote') {
const voteUrl = getDiscordTopVoteUrl();
const row = new ActionRowBuilder().addComponents(
new ButtonBuilder()
.setLabel('Voter sur DiscordTop')
.setStyle(ButtonStyle.Link)
.setURL(voteUrl),
new ButtonBuilder()
.setCustomId('dtop-check-vote')
.setLabel('Vérifier mon vote')
.setStyle(ButtonStyle.Primary)
);
await interaction.reply({
content:
'Merci de soutenir le serveur en votant sur DiscordTop !\nCliquez sur le bouton ci-dessous pour voter, puis utilisez **“Vérifier mon vote”** pour recevoir vos récompenses.',
components: [row],
ephemeral: true,
});
return;
}
// Bouton "Vérifier mon vote"
if (interaction.isButton() && interaction.customId === 'dtop-check-vote') {
await interaction.deferReply({ ephemeral: true });
const userId = interaction.user.id;
try {
const { status, body } = await checkVoteOnDiscordTop(userId);
// Gestion des statuts principaux
if (status === 200) {
const hasVoted = body?.has_voted ?? false;
if (!hasVoted) {
return interaction.editReply(
"Il semble que vous n'ayez pas encore voté pour ce serveur. Essayez de voter puis réessayez dans quelques secondes."
);
}
// 👉 C’est ici que vous appliquez VOS récompenses :
// - donner un rôle
// - ajouter de l’XP
// - débloquer un salon, etc.
// Exemple : donner un rôle (remplacez par votre ID de rôle)
const rewardRoleId = 'ID_DU_ROLE_RECOMPENSE'; // à adapter
const member =
interaction.member ??
(await interaction.guild.members.fetch(userId).catch(() => null));
if (member && rewardRoleId !== 'ID_DU_ROLE_RECOMPENSE') {
await member.roles.add(rewardRoleId).catch(() => null);
}
return interaction.editReply(
"✅ Vote validé sur DiscordTop ! Vos récompenses ont été appliquées sur le serveur."
);
}
if (status === 404) {
return interaction.editReply(
"Aucun vote récent n'a été trouvé pour votre compte. Assurez-vous d'avoir voté sur la bonne page et réessayez dans quelques instants."
);
}
if (status === 429) {
const retryAfter = body?.retry_after ?? 60;
return interaction.editReply(
`🚫 Vous effectuez trop de vérifications de vote. Merci de patienter **${retryAfter} secondes** avant de réessayer.`
);
}
if (status === 401 || status === 403) {
return interaction.editReply(
"⚠️ La configuration de l'API DiscordTop semble incorrecte (clé invalide ou serveur non autorisé). Contactez un administrateur."
);
}
// Autres erreurs (500, 400, etc.)
console.error('Erreur API DTOP:', status, body);
return interaction.editReply(
"❌ Une erreur est survenue lors de la vérification du vote. Merci de réessayer plus tard."
);
} catch (err) {
console.error('Erreur lors de l’appel à DTOP :', err);
return interaction.editReply(
"❌ Impossible de contacter l’API DiscordTop pour le moment."
);
}
}
});
client.login(process.env.DISCORD_TOKEN);5. Où brancher votre propre logique de récompenses ?
Dans l’exemple ci-dessus, le bloc important est ici :
if (status === 200) {
const hasVoted = body?.has_voted ?? true;
if (!hasVoted) {
return interaction.editReply(
"Il semble que vous n'ayez pas encore voté pour ce serveur. Essayez de voter puis réessayez dans quelques secondes."
);
}
// 👉 VOTRE LOGIQUE DE RÉCOMPENSE
// Exemple : donner un rôle, XP, etc.
}C’est à cet endroit précis que vous pouvez :
incrémenter un champ XP dans votre base,
ajouter un rôle avec
member.roles.add(...),logger l’événement dans un salon staff,
comptabiliser les votes journaliers, etc.
6. Résumé du flux côté bot
L’utilisateur tape
/voteLe bot répond avec :
un bouton lien → page de vote DiscordTop,
un bouton “Vérifier mon vote”
L’utilisateur clique “Vérifier mon vote”
Le bot appelle :
GET https://api.discordtop.net/v7/check-vote?api_token=VOTRE_CLE_API&discord_id=USER_IDSelon la réponse :
✅ 200 → vote valide → vos récompenses sont appliquées
❌ 404 → pas de vote récent
🚫 429 → trop de requêtes, respectez
retry_after🔐 401/403 → problème de configuration API
💥 500 → erreur côté DTOP (à réessayer plus tard)
Last updated