mirror of
https://github.com/arthur-pbty/discord-weather-bot.git
synced 2026-08-01 20:28:48 +02:00
first commit
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
'use strict';
|
||||
|
||||
require('dotenv').config();
|
||||
|
||||
const { Client, GatewayIntentBits, Collection, REST, Routes } = require('discord.js');
|
||||
const cron = require('node-cron');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
// ─── Validation des variables d'environnement ─────────────────────────────────
|
||||
const REQUIRED_ENV = ['DISCORD_TOKEN', 'CHANNEL_ID', 'LAT', 'LON'];
|
||||
for (const key of REQUIRED_ENV) {
|
||||
if (!process.env[key]) {
|
||||
console.error(`❌ Variable d'environnement manquante : ${key}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Client Discord ───────────────────────────────────────────────────────────
|
||||
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
|
||||
client.commands = new Collection();
|
||||
|
||||
// ─── Chargement des commandes ─────────────────────────────────────────────────
|
||||
const commandsDir = path.join(__dirname, 'commands');
|
||||
for (const file of fs.readdirSync(commandsDir).filter(f => f.endsWith('.js'))) {
|
||||
const cmd = require(path.join(commandsDir, file));
|
||||
if (!cmd.data || !cmd.execute) {
|
||||
console.warn(`⚠️ Commande ignorée (structure invalide) : ${file}`);
|
||||
continue;
|
||||
}
|
||||
client.commands.set(cmd.data.name, cmd);
|
||||
console.log(`✅ Commande chargée : /${cmd.data.name}`);
|
||||
}
|
||||
|
||||
// ─── Prêt ─────────────────────────────────────────────────────────────────────
|
||||
client.once('ready', async () => {
|
||||
console.log(`\n🤖 Connecté en tant que ${client.user.tag}`);
|
||||
console.log(`📍 Localisation : ${process.env.LOCATION_NAME || `${process.env.LAT}°, ${process.env.LON}°`}`);
|
||||
console.log(`⏰ Message quotidien : ${process.env.SEND_HOUR}h${String(process.env.SEND_MINUTE || 0).padStart(2,'0')}\n`);
|
||||
|
||||
// ── Enregistrement global des commandes slash ──────────────────────────────
|
||||
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
|
||||
const payload = [...client.commands.values()].map(c => c.data.toJSON());
|
||||
|
||||
try {
|
||||
console.log('📡 Enregistrement des commandes slash (global)…');
|
||||
await rest.put(Routes.applicationCommands(client.user.id), { body: payload });
|
||||
console.log(`✅ ${payload.length} commande(s) enregistrée(s)\n`);
|
||||
} catch (err) {
|
||||
console.error('❌ Erreur enregistrement commandes :', err.message);
|
||||
}
|
||||
|
||||
// ── Cron : message météo quotidien ────────────────────────────────────────
|
||||
const hour = parseInt(process.env.SEND_HOUR, 10) || 7;
|
||||
const minute = parseInt(process.env.SEND_MINUTE, 10) || 30;
|
||||
const cronExpr = `${minute} ${hour} * * *`;
|
||||
|
||||
cron.schedule(cronExpr, async () => {
|
||||
console.log(`\n⏰ [${new Date().toLocaleString('fr-FR', { timeZone: 'Europe/Paris' })}] Envoi du rapport météo quotidien…`);
|
||||
|
||||
// Invalider le cache pour forcer un rafraîchissement
|
||||
require('./services/weather').invalidateCache();
|
||||
require('./services/astronomy').invalidateAstroCache();
|
||||
|
||||
try {
|
||||
const channel = await client.channels.fetch(process.env.CHANNEL_ID);
|
||||
if (!channel?.isTextBased()) {
|
||||
console.error('❌ Channel introuvable ou non textuel :', process.env.CHANNEL_ID);
|
||||
return;
|
||||
}
|
||||
const { sendWeatherReport } = require('./commands/meteo');
|
||||
await sendWeatherReport(channel, false);
|
||||
console.log('✅ Rapport météo quotidien envoyé.');
|
||||
} catch (err) {
|
||||
console.error('❌ Erreur envoi quotidien :', err.message);
|
||||
}
|
||||
}, { timezone: 'Europe/Paris' });
|
||||
|
||||
console.log(`⏰ Cron programmé : "${cronExpr}" (Europe/Paris)`);
|
||||
});
|
||||
|
||||
// ─── Gestion des interactions ─────────────────────────────────────────────────
|
||||
client.on('interactionCreate', async interaction => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
const command = client.commands.get(interaction.commandName);
|
||||
if (!command) {
|
||||
console.warn(`⚠️ Commande inconnue reçue : ${interaction.commandName}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await command.execute(interaction);
|
||||
} catch (err) {
|
||||
console.error(`❌ Erreur commande /${interaction.commandName} :`, err);
|
||||
const errMsg = { content: `❌ Une erreur inattendue est survenue.`, ephemeral: true };
|
||||
if (interaction.replied || interaction.deferred) {
|
||||
await interaction.followUp(errMsg).catch(() => {});
|
||||
} else {
|
||||
await interaction.reply(errMsg).catch(() => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ─── Erreurs non gérées ───────────────────────────────────────────────────────
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
console.error('⚠️ UnhandledRejection :', reason);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
console.error('💥 UncaughtException :', err);
|
||||
});
|
||||
|
||||
// ─── Connexion ────────────────────────────────────────────────────────────────
|
||||
client.login(process.env.DISCORD_TOKEN).catch(err => {
|
||||
console.error('❌ Connexion Discord échouée :', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user