Push new structure / Add more features for managing minecraft server
This commit is contained in:
parent
7d6bc8e12f
commit
f7592bf0cb
6
.env
6
.env
@ -12,3 +12,9 @@ ROLE_ADMIN_ID=1164572260607205486
|
|||||||
|
|
||||||
MINECRAFT_SERVER_IP=valloic.dev:25565
|
MINECRAFT_SERVER_IP=valloic.dev:25565
|
||||||
MINECRAFT_WHITELIST_PATH=/opt/minecraft/server/whitelist.json
|
MINECRAFT_WHITELIST_PATH=/opt/minecraft/server/whitelist.json
|
||||||
|
|
||||||
|
USE_SCREEN=true
|
||||||
|
SERVER_JAR=fabric-server.jar
|
||||||
|
JAVA_ARGS=-Xmx2G -Xms1G
|
||||||
|
USE_SCREEN=true
|
||||||
|
MINECRAFT_SERVER_PATH=/opt/minecraft/server
|
||||||
32
.env.example
Normal file
32
.env.example
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Configuration du bot Discord
|
||||||
|
DISCORD_TOKEN=votre_token_discord
|
||||||
|
CLIENT_ID=votre_client_id
|
||||||
|
GUILD_ID=votre_guild_id
|
||||||
|
OWNER_ID=votre_user_id
|
||||||
|
|
||||||
|
# Configuration des rôles et channels
|
||||||
|
ROLE_WAITER_ID=id_du_role_attente
|
||||||
|
ROLE_VERIFIED_ID=id_du_role_verifie
|
||||||
|
CHANNEL_REQUEST_ACCESS_ID=id_channel_demandes
|
||||||
|
CHANNEL_LOGS_ID=id_channel_logs
|
||||||
|
|
||||||
|
# Configuration du serveur Minecraft
|
||||||
|
MINECRAFT_SERVER_HOST=votre_serveur.com
|
||||||
|
MINECRAFT_SERVER_PORT=25565
|
||||||
|
MINECRAFT_WHITELIST_PATH=/chemin/vers/whitelist.json
|
||||||
|
MINECRAFT_SERVICE_NAME=minecraft
|
||||||
|
|
||||||
|
# Configuration du mode serveur
|
||||||
|
USE_SCREEN=true
|
||||||
|
# true = utilise screen (plus flexible, commandes directes)
|
||||||
|
# false = utilise systemctl (plus robuste, redémarrage pour whitelist)
|
||||||
|
|
||||||
|
# Configuration des chemins serveur (pour VPS)
|
||||||
|
MINECRAFT_SERVER_PATH=/opt/minecraft/server
|
||||||
|
MINECRAFT_BACKUP_PATH=/opt/minecraft/backups
|
||||||
|
|
||||||
|
# Configuration Java et serveur
|
||||||
|
SERVER_JAR=fabric-server.jar
|
||||||
|
# Autres options: server.jar, paper.jar, spigot.jar, forge-server.jar
|
||||||
|
JAVA_ARGS=-Xmx2G -Xms1G
|
||||||
|
# Arguments Java personnalisés
|
||||||
322
README.md
322
README.md
@ -1,21 +1,272 @@
|
|||||||
# Bot Discord - Accès Serveur Minecraft
|
# Bot Discord - Gestion Serveur Minecraft
|
||||||
|
|
||||||
Ce bot Discord permet de gérer automatiquement les demandes d'accès à un serveur Minecraft via un système de whitelist.
|
Un bot Discord complet pour gérer la whitelist et le contrôle d'un serveur Minecraft hébergé sur VPS.
|
||||||
|
|
||||||
|
## 🚀 Fonctionnalités
|
||||||
|
|
||||||
|
### 🎯 Système de demandes d'accès automatique
|
||||||
|
- Message automatique avec bouton de demande d'accès
|
||||||
|
- Attribution automatique du rôle "En attente"
|
||||||
|
- Mise à jour du statut serveur toutes les 2 minutes
|
||||||
|
- Interface avec embeds et emojis personnalisés
|
||||||
|
|
||||||
|
### 👥 Gestion de la whitelist
|
||||||
|
- Ajout/suppression de joueurs avec récupération automatique d'UUID
|
||||||
|
- Rechargement automatique de la whitelist sur le serveur
|
||||||
|
- Liste des joueurs whitelistés
|
||||||
|
- Formatage correct des UUID pour Minecraft
|
||||||
|
|
||||||
|
### 🎮 Contrôle complet du serveur
|
||||||
|
- Démarrage/arrêt/redémarrage via systemctl
|
||||||
|
- Envoi de commandes directes au serveur
|
||||||
|
- Consultation des logs en temps réel
|
||||||
|
- Sauvegarde automatique du monde
|
||||||
|
- Vérification du statut en temps réel
|
||||||
|
|
||||||
|
### 🎨 Interface utilisateur
|
||||||
|
- Emojis personnalisés configurables
|
||||||
|
- Embeds Discord avec couleurs et formatage
|
||||||
|
- Messages d'erreur informatifs
|
||||||
|
- Gestion des permissions par propriétaire
|
||||||
|
|
||||||
|
## 📋 Prérequis
|
||||||
|
|
||||||
|
- **Node.js** v16+
|
||||||
|
- **Serveur Minecraft** configuré avec systemctl
|
||||||
|
- **Bot Discord** avec permissions appropriées
|
||||||
|
- **Accès sudo** sur le VPS (pour contrôle serveur)
|
||||||
|
|
||||||
|
## 🛠️ Installation
|
||||||
|
|
||||||
|
### 1. Sur votre VPS
|
||||||
|
```bash
|
||||||
|
# Cloner et installer (ou uploader vos fichiers)
|
||||||
|
cd /home/votre-user/bots/
|
||||||
|
# ... copier vos fichiers ici ...
|
||||||
|
cd mcgestionbot
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Configuration automatique
|
||||||
|
```bash
|
||||||
|
# Génération automatique du .env
|
||||||
|
./configure.sh
|
||||||
|
|
||||||
|
# Éditer avec vos tokens Discord
|
||||||
|
nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Lancement
|
||||||
|
```bash
|
||||||
|
# Le bot configure automatiquement tout au démarrage !
|
||||||
|
node start.js
|
||||||
|
```
|
||||||
|
|
||||||
|
**C'est tout ! 🎉** Le bot se charge de :
|
||||||
|
- ✅ Créer l'utilisateur `minecraft`
|
||||||
|
- ✅ Configurer les permissions
|
||||||
|
- ✅ Activer la whitelist dans server.properties
|
||||||
|
- ✅ Créer les dossiers nécessaires
|
||||||
|
- ✅ Configurer les sauvegardes
|
||||||
|
|
||||||
|
## 🎮 Utilisation
|
||||||
|
|
||||||
|
### Démarrage du bot
|
||||||
|
```bash
|
||||||
|
node start.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commandes disponibles
|
||||||
|
|
||||||
|
#### `/minecraft` - Gestion du serveur (Owner only)
|
||||||
|
|
||||||
|
**Gestion whitelist :**
|
||||||
|
- `/minecraft list` - Liste des joueurs whitelistés
|
||||||
|
- `/minecraft add <pseudo>` - Ajouter un joueur
|
||||||
|
- `/minecraft remove <pseudo>` - Retirer un joueur
|
||||||
|
- `/minecraft reload` - Recharger la whitelist
|
||||||
|
|
||||||
|
**Contrôle serveur :**
|
||||||
|
- `/minecraft status` - Statut du serveur
|
||||||
|
- `/minecraft start` - Démarrer le serveur
|
||||||
|
- `/minecraft stop` - Arrêter le serveur
|
||||||
|
- `/minecraft restart` - Redémarrer le serveur
|
||||||
|
- `/minecraft logs [lines]` - Afficher les logs
|
||||||
|
- `/minecraft command <cmd>` - Envoyer une commande
|
||||||
|
- `/minecraft backup` - Sauvegarder le monde
|
||||||
|
- `/minecraft setup` - Configuration automatique du serveur
|
||||||
|
|
||||||
|
### Système de demandes automatique
|
||||||
|
|
||||||
|
Le bot gère automatiquement :
|
||||||
|
1. **Message persistant** dans le channel configuré
|
||||||
|
2. **Bouton de demande** toujours disponible
|
||||||
|
3. **Attribution du rôle** "En attente" automatique
|
||||||
|
4. **Mise à jour du statut** serveur toutes les 2 minutes
|
||||||
|
|
||||||
|
## 🎨 Personnalisation
|
||||||
|
|
||||||
|
### Emojis personnalisés
|
||||||
|
Modifiez `emojis.json` pour vos emojis :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"online": "<:online:123456789>",
|
||||||
|
"offline": "<:offline:123456789>",
|
||||||
|
"addedWhitelist": "<:added:123456789>",
|
||||||
|
"removedWhitelist": "<:removed:123456789>",
|
||||||
|
"success": "✅",
|
||||||
|
"error": "❌",
|
||||||
|
"info": "ℹ️"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Dépannage
|
||||||
|
|
||||||
|
### Problèmes courants
|
||||||
|
|
||||||
|
**1. "Command not found" node**
|
||||||
|
```bash
|
||||||
|
# Installer Node.js
|
||||||
|
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||||||
|
sudo apt-get install -y nodejs
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. "Permission denied" systemctl**
|
||||||
|
```bash
|
||||||
|
# Configurer sudo
|
||||||
|
sudo ./setup-sudo.sh
|
||||||
|
./test-permissions.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. "Whitelist not enforced"**
|
||||||
|
```bash
|
||||||
|
# Vérifier server.properties
|
||||||
|
grep "enforce-whitelist" /opt/minecraft/server/server.properties
|
||||||
|
# Doit être : enforce-whitelist=true
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. "UUID format incorrect"**
|
||||||
|
- Le bot formate automatiquement les UUID
|
||||||
|
- Utilise l'API Mojang pour récupérer les UUID
|
||||||
|
|
||||||
|
### Logs et debug
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Logs du bot
|
||||||
|
node start.js
|
||||||
|
|
||||||
|
# Logs du serveur Minecraft
|
||||||
|
sudo journalctl -u minecraft -f
|
||||||
|
|
||||||
|
# Test des permissions
|
||||||
|
./test-permissions.sh
|
||||||
|
|
||||||
|
# Test de la whitelist
|
||||||
|
node test-whitelist.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 Structure du projet
|
||||||
|
|
||||||
|
```
|
||||||
|
mc-acces-bot/
|
||||||
|
├── start.js # Point d'entrée
|
||||||
|
├── package.json # Dépendances
|
||||||
|
├── .env # Configuration
|
||||||
|
├── emojis.json # Emojis personnalisés
|
||||||
|
├── setup-sudo.sh # Config permissions
|
||||||
|
├── test-permissions.sh # Test sudo
|
||||||
|
└── src/
|
||||||
|
├── commands/
|
||||||
|
│ └── minecraft.js # Commandes serveur
|
||||||
|
├── events/
|
||||||
|
│ ├── ready.js # Démarrage bot
|
||||||
|
│ └── interactionCreate.js # Gestion interactions
|
||||||
|
├── handlers/
|
||||||
|
│ └── interactionHandler.js # Boutons/modals
|
||||||
|
└── utils/
|
||||||
|
├── whitelistManager.js # Gestion whitelist
|
||||||
|
├── minecraftServer.js # Statut serveur
|
||||||
|
├── serverControlManager.js # Contrôle VPS
|
||||||
|
├── autoMessageManager.js # Messages auto
|
||||||
|
└── emojiManager.js # Gestion emojis
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Déploiement en production
|
||||||
|
|
||||||
|
### Avec PM2 (recommandé)
|
||||||
|
```bash
|
||||||
|
# Installer PM2
|
||||||
|
npm install -g pm2
|
||||||
|
|
||||||
|
# Démarrer le bot
|
||||||
|
pm2 start start.js --name "mc-bot"
|
||||||
|
|
||||||
|
# Configurer auto-start
|
||||||
|
pm2 startup
|
||||||
|
pm2 save
|
||||||
|
```
|
||||||
|
|
||||||
|
### Avec systemctl
|
||||||
|
```bash
|
||||||
|
# Créer le service
|
||||||
|
sudo nano /etc/systemd/system/mc-bot.service
|
||||||
|
|
||||||
|
# Contenu :
|
||||||
|
[Unit]
|
||||||
|
Description=Minecraft Discord Bot
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=loicv
|
||||||
|
WorkingDirectory=/home/loicv/Documents/Wors/mc-acces-bot
|
||||||
|
ExecStart=/usr/bin/node start.js
|
||||||
|
Restart=always
|
||||||
|
Environment=NODE_ENV=production
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
|
# Activer le service
|
||||||
|
sudo systemctl enable mc-bot
|
||||||
|
sudo systemctl start mc-bot
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Notes importantes
|
||||||
|
|
||||||
|
- **Sécurité :** Le bot a accès sudo - utilisez uniquement sur un serveur dédié
|
||||||
|
- **Permissions :** Seul le propriétaire (OWNER_ID) peut utiliser les commandes
|
||||||
|
- **Backup :** Les sauvegardes sont stockées dans `/opt/minecraft/backups/`
|
||||||
|
- **Logs :** Tous les logs sont visibles via `journalctl` et dans Discord
|
||||||
|
|
||||||
|
## 🤝 Support
|
||||||
|
|
||||||
|
En cas de problème :
|
||||||
|
1. Vérifiez les logs : `sudo journalctl -u minecraft -f`
|
||||||
|
2. Testez les permissions : `./test-permissions.sh`
|
||||||
|
3. Vérifiez la configuration : fichier `.env` complet
|
||||||
|
4. Validez le service : `sudo systemctl status minecraft`
|
||||||
|
|
||||||
## Fonctionnalités
|
## Fonctionnalités
|
||||||
|
|
||||||
### 🎮 Système de demande d'accès
|
### 🎮 Système de demande d'accès
|
||||||
- Message automatique avec bouton pour demander l'accès
|
- **Message simple automatique** avec bouton pour demander l'accès
|
||||||
|
- **Embed de status du serveur** mis à jour automatiquement toutes les 2 minutes
|
||||||
- Modal pour saisir le pseudo Minecraft
|
- Modal pour saisir le pseudo Minecraft
|
||||||
|
- **Attribution automatique du rôle "Waiter"** lors de la demande
|
||||||
- Vérification automatique si le joueur est déjà whitelisté
|
- Vérification automatique si le joueur est déjà whitelisté
|
||||||
- Envoi de la demande au canal staff avec boutons Accept/Refuse
|
- Envoi de la demande au canal staff avec boutons Accept/Refuse
|
||||||
|
- **Gestion automatique des rôles** : Verified (accepté) ou suppression du Waiter (refusé)
|
||||||
|
- **Emojis personnalisés** pour tous les messages
|
||||||
|
|
||||||
### ⚙️ Commandes administrateur
|
### ⚙️ Commandes administrateur
|
||||||
- `/minecraft list` - Affiche la liste des joueurs whitelistés
|
- `/minecraft list` - Affiche la liste des joueurs whitelistés
|
||||||
- `/minecraft add <pseudo>` - Ajoute un joueur à la whitelist
|
- `/minecraft add <pseudo>` - Ajoute un joueur à la whitelist
|
||||||
- `/minecraft remove <pseudo>` - Retire un joueur de la whitelist
|
- `/minecraft remove <pseudo>` - Retire un joueur de la whitelist
|
||||||
- `/minecraft status` - Affiche le statut du serveur Minecraft
|
- `/minecraft status` - Affiche le statut du serveur Minecraft
|
||||||
- `/setup-access` - Envoie le message de demande d'accès
|
- `/minecraft reload` - Instructions pour recharger la whitelist sur le serveur
|
||||||
|
- `/setup-access` - Envoie le message de demande d'accès (facultatif)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -53,10 +304,26 @@ Pour le développement :
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Pour tester le formatage UUID :
|
||||||
|
```bash
|
||||||
|
npm run test-uuid
|
||||||
|
```
|
||||||
|
|
||||||
|
Pour tester la connexion au serveur Minecraft :
|
||||||
|
```bash
|
||||||
|
npm run test-server
|
||||||
|
```
|
||||||
|
|
||||||
|
Pour tester la whitelist :
|
||||||
|
```bash
|
||||||
|
npm run test-whitelist
|
||||||
|
```
|
||||||
|
|
||||||
## Structure du projet
|
## Structure du projet
|
||||||
|
|
||||||
```
|
```
|
||||||
├── start.js # Point d'entrée principal
|
├── start.js # Point d'entrée principal
|
||||||
|
├── emojis.json # Configuration des emojis personnalisés
|
||||||
├── src/
|
├── src/
|
||||||
│ ├── commands/
|
│ ├── commands/
|
||||||
│ │ ├── minecraft.js # Commandes /minecraft
|
│ │ ├── minecraft.js # Commandes /minecraft
|
||||||
@ -69,6 +336,8 @@ npm run dev
|
|||||||
│ │ └── interactionHandler.js # Gestionnaire d'interactions
|
│ │ └── interactionHandler.js # Gestionnaire d'interactions
|
||||||
│ └── utils/
|
│ └── utils/
|
||||||
│ ├── accessRequestManager.js # Gestionnaire de demandes d'accès
|
│ ├── accessRequestManager.js # Gestionnaire de demandes d'accès
|
||||||
|
│ ├── emojiManager.js # Gestionnaire d'emojis personnalisés
|
||||||
|
│ ├── roleManager.js # Gestionnaire de rôles Discord
|
||||||
│ ├── minecraftServer.js # Utilitaires serveur Minecraft
|
│ ├── minecraftServer.js # Utilitaires serveur Minecraft
|
||||||
│ └── whitelistManager.js # Gestionnaire de whitelist
|
│ └── whitelistManager.js # Gestionnaire de whitelist
|
||||||
```
|
```
|
||||||
@ -78,17 +347,22 @@ npm run dev
|
|||||||
### Configuration initiale
|
### Configuration initiale
|
||||||
|
|
||||||
1. **Inviter le bot sur votre serveur** avec les permissions nécessaires
|
1. **Inviter le bot sur votre serveur** avec les permissions nécessaires
|
||||||
2. **Utiliser `/setup-access`** dans le canal où vous voulez le message de demande d'accès
|
2. **Le message de demande d'accès est envoyé automatiquement** au démarrage dans le canal configuré
|
||||||
3. **Configurer les rôles** dans votre serveur Discord selon les IDs dans le `.env`
|
3. **Configurer les rôles** dans votre serveur Discord selon les IDs dans le `.env`
|
||||||
|
|
||||||
|
> ⚠️ **Note :** Il n'est plus nécessaire d'utiliser `/setup-access` manuellement. Le bot gère automatiquement l'envoi et la mise à jour du message de demande d'accès.
|
||||||
|
|
||||||
### Workflow des demandes
|
### Workflow des demandes
|
||||||
|
|
||||||
1. **Utilisateur :** Clique sur le bouton "Demander l'accès"
|
1. **Utilisateur :** Clique sur le bouton "Demander l'accès"
|
||||||
2. **Utilisateur :** Remplit le modal avec son pseudo Minecraft
|
2. **Système :** Attribue automatiquement le rôle "Waiter" à l'utilisateur
|
||||||
3. **Système :** Vérifie si le joueur est déjà whitelisté
|
3. **Utilisateur :** Remplit le modal avec son pseudo Minecraft
|
||||||
4. **Système :** Envoie la demande au canal staff
|
4. **Système :** Vérifie si le joueur est déjà whitelisté
|
||||||
5. **Staff :** Clique sur "Accepter" ou "Refuser"
|
5. **Système :** Envoie la demande au canal staff avec emojis personnalisés
|
||||||
6. **Système :** Ajoute le joueur à la whitelist (si accepté) et notifie l'utilisateur
|
6. **Staff :** Clique sur "Accepter" ou "Refuser"
|
||||||
|
7. **Système (si accepté) :** Ajoute le joueur à la whitelist + donne le rôle "Verified" + retire le rôle "Waiter"
|
||||||
|
8. **Système (si refusé) :** Retire simplement le rôle "Waiter"
|
||||||
|
9. **Système :** Notifie l'utilisateur par MP avec les emojis appropriés
|
||||||
|
|
||||||
### Commandes administrateur
|
### Commandes administrateur
|
||||||
|
|
||||||
@ -107,6 +381,14 @@ Le bot a besoin des permissions Discord suivantes :
|
|||||||
- `Embed Links` - Incorporer des liens
|
- `Embed Links` - Incorporer des liens
|
||||||
- `Manage Messages` - Gérer les messages
|
- `Manage Messages` - Gérer les messages
|
||||||
- `Read Message History` - Lire l'historique des messages
|
- `Read Message History` - Lire l'historique des messages
|
||||||
|
- `Manage Roles` - Gérer les rôles (pour attribuer Waiter/Verified)
|
||||||
|
|
||||||
|
## Configuration des rôles
|
||||||
|
|
||||||
|
Assurez-vous que ces rôles existent sur votre serveur Discord :
|
||||||
|
- **Rôle Waiter** (`ROLE_WAITER_ID`) : Attribué automatiquement lors d'une demande
|
||||||
|
- **Rôle Verified** (`ROLE_VERIFIED_ID`) : Attribué quand l'accès est accepté
|
||||||
|
- **Rôle Admin** (`ROLE_ADMIN_ID`) : Requis pour traiter les demandes d'accès
|
||||||
|
|
||||||
## Notes importantes
|
## Notes importantes
|
||||||
|
|
||||||
@ -127,7 +409,27 @@ Le bot a besoin des permissions Discord suivantes :
|
|||||||
- Vérifiez les permissions de fichier
|
- Vérifiez les permissions de fichier
|
||||||
- Assurez-vous que le format JSON est valide
|
- Assurez-vous que le format JSON est valide
|
||||||
|
|
||||||
|
### Problèmes d'UUID
|
||||||
|
- Les UUIDs sont automatiquement formatés au bon format (avec tirets)
|
||||||
|
- Si un joueur n'est pas trouvé, vérifiez que le pseudo existe sur Minecraft
|
||||||
|
- Utilisez `npm run test-uuid` pour tester le formatage
|
||||||
|
- Format attendu: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
|
||||||
|
|
||||||
### Problèmes de serveur Minecraft
|
### Problèmes de serveur Minecraft
|
||||||
- Vérifiez que l'adresse IP et le port sont corrects
|
- Vérifiez que l'adresse IP et le port sont corrects
|
||||||
- Assurez-vous que le serveur est en ligne
|
- Assurez-vous que le serveur est en ligne
|
||||||
- Vérifiez les paramètres du pare-feu
|
- Vérifiez les paramètres du pare-feu
|
||||||
|
- Utilisez `npm run test-server` pour tester la connexion
|
||||||
|
- Le timeout de connexion est de 10 secondes
|
||||||
|
|
||||||
|
### Messages automatiques
|
||||||
|
- Le message de demande d'accès est envoyé automatiquement au démarrage
|
||||||
|
- Les anciens messages sont supprimés automatiquement
|
||||||
|
- Un seul message actif est maintenu par canal
|
||||||
|
- **Le status du serveur se met à jour automatiquement toutes les 2 minutes**
|
||||||
|
|
||||||
|
### Configuration serveur Minecraft
|
||||||
|
- Assurez-vous que `white-list=true` dans server.properties
|
||||||
|
- **IMPORTANT**: `enforce-whitelist=true` doit être activé pour que la whitelist soit appliquée
|
||||||
|
- Utilisez `/whitelist reload` dans la console serveur après modifications
|
||||||
|
- Ou utilisez la commande `/minecraft reload` du bot pour avoir les instructions
|
||||||
814
package-lock.json
generated
Normal file
814
package-lock.json
generated
Normal file
@ -0,0 +1,814 @@
|
|||||||
|
{
|
||||||
|
"name": "mc-access-bot",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "mc-access-bot",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"discord.js": "^14.14.1",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"minecraft-server-util": "^5.4.3",
|
||||||
|
"node-fetch": "^3.3.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/builders": {
|
||||||
|
"version": "1.12.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.12.2.tgz",
|
||||||
|
"integrity": "sha512-AugKmrgRJOHXEyMkABH/hXpAmIBKbYokCEl9VAM4Kh6FvkdobQ+Zhv7AR6K+y5hS7+VQ7gKXPYCe1JQmV07H1g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/formatters": "^0.6.1",
|
||||||
|
"@discordjs/util": "^1.1.1",
|
||||||
|
"@sapphire/shapeshift": "^4.0.0",
|
||||||
|
"discord-api-types": "^0.38.26",
|
||||||
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"ts-mixer": "^6.0.4",
|
||||||
|
"tslib": "^2.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.11.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/collection": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/formatters": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-5cnX+tASiPCqCWtFcFslxBVUaCetB0thvM/JyavhbXInP1HJIEU+Qv/zMrnuwSsX3yWH2lVXNJZeDK3EiP4HHg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"discord-api-types": "^0.38.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.11.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/rest": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-RDYrhmpB7mTvmCKcpj+pc5k7POKszS4E2O9TYc+U+Y4iaCP+r910QdO43qmpOja8LRr1RJ0b3U+CqVsnPqzf4w==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/collection": "^2.1.1",
|
||||||
|
"@discordjs/util": "^1.1.1",
|
||||||
|
"@sapphire/async-queue": "^1.5.3",
|
||||||
|
"@sapphire/snowflake": "^3.5.3",
|
||||||
|
"@vladfrangu/async_event_emitter": "^2.4.6",
|
||||||
|
"discord-api-types": "^0.38.16",
|
||||||
|
"magic-bytes.js": "^1.10.0",
|
||||||
|
"tslib": "^2.6.3",
|
||||||
|
"undici": "6.21.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/rest/node_modules/@discordjs/collection": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/util": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/ws": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/collection": "^2.1.0",
|
||||||
|
"@discordjs/rest": "^2.5.1",
|
||||||
|
"@discordjs/util": "^1.1.0",
|
||||||
|
"@sapphire/async-queue": "^1.5.2",
|
||||||
|
"@types/ws": "^8.5.10",
|
||||||
|
"@vladfrangu/async_event_emitter": "^2.2.4",
|
||||||
|
"discord-api-types": "^0.38.1",
|
||||||
|
"tslib": "^2.6.2",
|
||||||
|
"ws": "^8.17.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.11.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/ws/node_modules/@discordjs/collection": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sapphire/async-queue": {
|
||||||
|
"version": "1.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz",
|
||||||
|
"integrity": "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v14.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sapphire/shapeshift": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"lodash": "^4.17.21"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sapphire/snowflake": {
|
||||||
|
"version": "3.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz",
|
||||||
|
"integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v14.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "24.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz",
|
||||||
|
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~7.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||||
|
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vladfrangu/async_event_emitter": {
|
||||||
|
"version": "2.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.7.tgz",
|
||||||
|
"integrity": "sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v14.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/anymatch": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/binary-extensions": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chokidar": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"anymatch": "~3.1.2",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"glob-parent": "~5.1.2",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "~2.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
|
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/discord-api-types": {
|
||||||
|
"version": "0.38.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.30.tgz",
|
||||||
|
"integrity": "sha512-KhAqlBrg+rVK+Ob7INMF5o63yW4/GUzRatG/AjyVsIO8lgcLyR8qCl2HokIVzWwmzkJYG0CEPXsKMOqau3E8NA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"workspaces": [
|
||||||
|
"scripts/actions/documentation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/discord.js": {
|
||||||
|
"version": "14.23.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.23.2.tgz",
|
||||||
|
"integrity": "sha512-tU2NFr823X3TXEc8KyR/4m296KLxPai4nirN3q9kHCpY4TKj96n9lHZnyLzRNMui8EbL07jg9hgH2PWWfKMGIg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/builders": "^1.12.1",
|
||||||
|
"@discordjs/collection": "1.5.3",
|
||||||
|
"@discordjs/formatters": "^0.6.1",
|
||||||
|
"@discordjs/rest": "^2.6.0",
|
||||||
|
"@discordjs/util": "^1.1.1",
|
||||||
|
"@discordjs/ws": "^1.2.3",
|
||||||
|
"@sapphire/snowflake": "3.5.3",
|
||||||
|
"discord-api-types": "^0.38.29",
|
||||||
|
"fast-deep-equal": "3.1.3",
|
||||||
|
"lodash.snakecase": "4.1.1",
|
||||||
|
"magic-bytes.js": "^1.10.0",
|
||||||
|
"tslib": "^2.6.3",
|
||||||
|
"undici": "6.21.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dotenv": {
|
||||||
|
"version": "16.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||||
|
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://dotenvx.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fast-deep-equal": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/fetch-blob": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "paypal",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "^1.0.0",
|
||||||
|
"web-streams-polyfill": "^3.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20 || >= 14.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/formdata-polyfill": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fetch-blob": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ignore-by-default": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lodash": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.snakecase": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/magic-bytes.js": {
|
||||||
|
"version": "1.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.12.1.tgz",
|
||||||
|
"integrity": "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/minecraft-motd-util": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/minecraft-motd-util/-/minecraft-motd-util-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-5TuTRjrRupSTruea0nRC37r0FdhkS1O4wIJKAYfwJRCQd/X4Zyl/dVIs96h9UVW6N8jhIuz9pNkrDsqyN7VBdA==",
|
||||||
|
"deprecated": "no longer maintained",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/minecraft-server-util": {
|
||||||
|
"version": "5.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/minecraft-server-util/-/minecraft-server-util-5.4.4.tgz",
|
||||||
|
"integrity": "sha512-uaE0N9PHPtJudi8BlCvKDD9K30w23ZpeS1I53wEJo9nX0HSmg5qFvwj8gMG0CYCUwWH/g5hjKaGAwXXN/vhMJw==",
|
||||||
|
"deprecated": "no longer maintained, please use https://mcstatus.io",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minecraft-motd-util": "^1.1.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"deprecated": "Use your platform's native DOMException instead",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/node-fetch"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nodemon": {
|
||||||
|
"version": "3.1.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz",
|
||||||
|
"integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": "^3.5.2",
|
||||||
|
"debug": "^4",
|
||||||
|
"ignore-by-default": "^1.0.1",
|
||||||
|
"minimatch": "^3.1.2",
|
||||||
|
"pstree.remy": "^1.1.8",
|
||||||
|
"semver": "^7.5.3",
|
||||||
|
"simple-update-notifier": "^2.0.0",
|
||||||
|
"supports-color": "^5.5.0",
|
||||||
|
"touch": "^3.1.0",
|
||||||
|
"undefsafe": "^2.0.5"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"nodemon": "bin/nodemon.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/nodemon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pstree.remy": {
|
||||||
|
"version": "1.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||||
|
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/readdirp": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/semver": {
|
||||||
|
"version": "7.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||||
|
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/simple-update-notifier": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^7.5.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/touch": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"nodetouch": "bin/nodetouch.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ts-mixer": {
|
||||||
|
"version": "6.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
|
||||||
|
"integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
|
"license": "0BSD"
|
||||||
|
},
|
||||||
|
"node_modules/undefsafe": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "6.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
|
||||||
|
"integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "7.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||||
|
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "3.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||||
|
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.18.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||||
|
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,7 +5,10 @@
|
|||||||
"main": "start.js",
|
"main": "start.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node start.js",
|
"start": "node start.js",
|
||||||
"dev": "nodemon start.js"
|
"dev": "nodemon start.js",
|
||||||
|
"test-uuid": "node test-uuid.js",
|
||||||
|
"test-server": "node test-server.js",
|
||||||
|
"test-whitelist": "node test-whitelist.js"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"discord",
|
"discord",
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require('discord.js');
|
const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require('discord.js');
|
||||||
const WhitelistManager = require('../utils/whitelistManager');
|
const WhitelistManager = require('../utils/whitelistManager');
|
||||||
const MinecraftServerUtil = require('../utils/minecraftServer');
|
const MinecraftServerUtil = require('../utils/minecraftServer');
|
||||||
|
const ServerControlManager = require('../utils/serverControlManager');
|
||||||
|
const emojiManager = require('../utils/emojiManager');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
@ -37,13 +39,66 @@ module.exports = {
|
|||||||
subcommand
|
subcommand
|
||||||
.setName('status')
|
.setName('status')
|
||||||
.setDescription('Affiche le status du serveur Minecraft')
|
.setDescription('Affiche le status du serveur Minecraft')
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('reload')
|
||||||
|
.setDescription('Recharge la whitelist du serveur')
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('start')
|
||||||
|
.setDescription('Démarre le serveur Minecraft')
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('stop')
|
||||||
|
.setDescription('Arrête le serveur Minecraft')
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('restart')
|
||||||
|
.setDescription('Redémarre le serveur Minecraft')
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('logs')
|
||||||
|
.setDescription('Affiche les logs du serveur')
|
||||||
|
.addIntegerOption(option =>
|
||||||
|
option
|
||||||
|
.setName('lines')
|
||||||
|
.setDescription('Nombre de lignes à afficher (défaut: 20)')
|
||||||
|
.setMinValue(1)
|
||||||
|
.setMaxValue(100)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('command')
|
||||||
|
.setDescription('Envoie une commande au serveur')
|
||||||
|
.addStringOption(option =>
|
||||||
|
option
|
||||||
|
.setName('cmd')
|
||||||
|
.setDescription('La commande à envoyer')
|
||||||
|
.setRequired(true)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('backup')
|
||||||
|
.setDescription('Sauvegarde le monde du serveur')
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('setup')
|
||||||
|
.setDescription('Configure automatiquement le serveur pour le bot')
|
||||||
),
|
),
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
// Vérifier si l'utilisateur est le propriétaire
|
// Vérifier si l'utilisateur est le propriétaire
|
||||||
if (interaction.user.id !== process.env.OWNER_ID) {
|
if (interaction.user.id !== process.env.OWNER_ID) {
|
||||||
return await interaction.reply({
|
return await interaction.reply({
|
||||||
content: '❌ Vous n\'avez pas la permission d\'utiliser cette commande.',
|
content: `${emojiManager.error} Vous n'avez pas la permission d'utiliser cette commande.`,
|
||||||
ephemeral: true
|
ephemeral: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -51,6 +106,7 @@ module.exports = {
|
|||||||
const subcommand = interaction.options.getSubcommand();
|
const subcommand = interaction.options.getSubcommand();
|
||||||
const whitelistManager = new WhitelistManager();
|
const whitelistManager = new WhitelistManager();
|
||||||
const serverUtil = new MinecraftServerUtil();
|
const serverUtil = new MinecraftServerUtil();
|
||||||
|
const serverControl = new ServerControlManager();
|
||||||
|
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
|
||||||
@ -60,7 +116,7 @@ module.exports = {
|
|||||||
const players = await whitelistManager.getWhitelistPlayers();
|
const players = await whitelistManager.getWhitelistPlayers();
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle('📋 Liste des joueurs whitelistés')
|
.setTitle(`${emojiManager.info} Liste des joueurs whitelistés`)
|
||||||
.setColor('#0099FF')
|
.setColor('#0099FF')
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
@ -73,14 +129,12 @@ module.exports = {
|
|||||||
|
|
||||||
await interaction.editReply({ embeds: [embed] });
|
await interaction.editReply({ embeds: [embed] });
|
||||||
break;
|
break;
|
||||||
}
|
} case 'add': {
|
||||||
|
|
||||||
case 'add': {
|
|
||||||
const pseudo = interaction.options.getString('pseudo');
|
const pseudo = interaction.options.getString('pseudo');
|
||||||
const result = await whitelistManager.addPlayer(pseudo);
|
const result = await whitelistManager.addPlayer(pseudo);
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle(result.success ? '✅ Joueur ajouté' : '❌ Erreur')
|
.setTitle(result.success ? `${emojiManager.addedWhitelist} Joueur ajouté` : `${emojiManager.error} Erreur`)
|
||||||
.setDescription(result.message)
|
.setDescription(result.message)
|
||||||
.setColor(result.success ? '#00FF00' : '#FF0000')
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
@ -94,7 +148,7 @@ module.exports = {
|
|||||||
const result = await whitelistManager.removePlayer(pseudo);
|
const result = await whitelistManager.removePlayer(pseudo);
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle(result.success ? '✅ Joueur retiré' : '❌ Erreur')
|
.setTitle(result.success ? `${emojiManager.removedWhitelist} Joueur retiré` : `${emojiManager.error} Erreur`)
|
||||||
.setDescription(result.message)
|
.setDescription(result.message)
|
||||||
.setColor(result.success ? '#00FF00' : '#FF0000')
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
@ -110,12 +164,149 @@ module.exports = {
|
|||||||
await interaction.editReply({ embeds: [embed] });
|
await interaction.editReply({ embeds: [embed] });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'reload': {
|
||||||
|
const result = await serverControl.reloadWhitelist();
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(result.success ? `${emojiManager.success} Whitelist rechargée` : `${emojiManager.error} Erreur`)
|
||||||
|
.setDescription(result.message)
|
||||||
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'start': {
|
||||||
|
const result = await serverControl.startServer();
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(result.success ? `${emojiManager.success} Serveur démarré` : `${emojiManager.error} Erreur`)
|
||||||
|
.setDescription(result.message)
|
||||||
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'stop': {
|
||||||
|
const result = await serverControl.stopServer();
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(result.success ? `${emojiManager.success} Serveur arrêté` : `${emojiManager.error} Erreur`)
|
||||||
|
.setDescription(result.message)
|
||||||
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'restart': {
|
||||||
|
const result = await serverControl.restartServer();
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(result.success ? `${emojiManager.success} Serveur redémarré` : `${emojiManager.error} Erreur`)
|
||||||
|
.setDescription(result.message)
|
||||||
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'logs': {
|
||||||
|
const lines = interaction.options.getInteger('lines') || 20;
|
||||||
|
const result = await serverControl.getServerLogs(lines);
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(`${emojiManager.error} Erreur`)
|
||||||
|
.setDescription(`Impossible de récupérer les logs: ${result.error}`)
|
||||||
|
.setColor('#FF0000')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limiter la taille des logs pour Discord
|
||||||
|
let logs = result.logs;
|
||||||
|
if (logs.length > 4000) {
|
||||||
|
logs = logs.substring(logs.length - 4000);
|
||||||
|
logs = '...\n' + logs.substring(logs.indexOf('\n') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(`${emojiManager.info} Logs du serveur (${lines} lignes)`)
|
||||||
|
.setDescription(`\`\`\`\n${logs}\n\`\`\``)
|
||||||
|
.setColor('#0099FF')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'command': {
|
||||||
|
const cmd = interaction.options.getString('cmd');
|
||||||
|
const result = await serverControl.sendServerCommand(cmd);
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(result.success ? `${emojiManager.success} Commande envoyée` : `${emojiManager.error} Erreur`)
|
||||||
|
.setDescription(result.message)
|
||||||
|
.addFields({ name: 'Commande', value: `\`${cmd}\``, inline: false })
|
||||||
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'backup': {
|
||||||
|
const result = await serverControl.backupWorld();
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(result.success ? `${emojiManager.success} Sauvegarde créée` : `${emojiManager.error} Erreur`)
|
||||||
|
.setDescription(result.message)
|
||||||
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
if (result.backupPath) {
|
||||||
|
embed.addFields({ name: 'Fichier', value: `\`${result.backupPath}\``, inline: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'setup': {
|
||||||
|
const result = await serverControl.setupServerForBot();
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle(result.success ? `${emojiManager.success} Configuration terminée` : `${emojiManager.error} Erreur`)
|
||||||
|
.setDescription(result.message)
|
||||||
|
.setColor(result.success ? '#00FF00' : '#FF0000')
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
if (result.details && result.details.length > 0) {
|
||||||
|
embed.addFields({
|
||||||
|
name: 'Détails de la configuration',
|
||||||
|
value: result.details.join('\n'),
|
||||||
|
inline: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur dans la commande minecraft:', error);
|
console.error('Erreur dans la commande minecraft:', error);
|
||||||
|
|
||||||
const errorEmbed = new EmbedBuilder()
|
const errorEmbed = new EmbedBuilder()
|
||||||
.setTitle('❌ Erreur')
|
.setTitle(`${emojiManager.error} Erreur`)
|
||||||
.setDescription('Une erreur est survenue lors de l\'exécution de la commande.')
|
.setDescription('Une erreur est survenue lors de l\'exécution de la commande.')
|
||||||
.setColor('#FF0000')
|
.setColor('#FF0000')
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
const { SlashCommandBuilder } = require('discord.js');
|
|
||||||
const AccessRequestManager = require('../utils/accessRequestManager');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('setup-access')
|
|
||||||
.setDescription('Envoie le message de demande d\'accès dans le canal actuel'),
|
|
||||||
|
|
||||||
async execute(interaction) {
|
|
||||||
// Vérifier si l'utilisateur est le propriétaire
|
|
||||||
if (interaction.user.id !== process.env.OWNER_ID) {
|
|
||||||
return await interaction.reply({
|
|
||||||
content: '❌ Vous n\'avez pas la permission d\'utiliser cette commande.',
|
|
||||||
ephemeral: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const embed = AccessRequestManager.createRequestEmbed();
|
|
||||||
const button = AccessRequestManager.createRequestButton();
|
|
||||||
|
|
||||||
await interaction.reply({
|
|
||||||
content: '✅ Message de demande d\'accès envoyé !',
|
|
||||||
ephemeral: true
|
|
||||||
});
|
|
||||||
|
|
||||||
await interaction.followUp({
|
|
||||||
embeds: [embed],
|
|
||||||
components: [button]
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erreur lors de l\'envoi du message de demande d\'accès:', error);
|
|
||||||
await interaction.reply({
|
|
||||||
content: '❌ Erreur lors de l\'envoi du message.',
|
|
||||||
ephemeral: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,4 +1,5 @@
|
|||||||
const { REST, Routes } = require('discord.js');
|
const { REST, Routes } = require('discord.js');
|
||||||
|
const AutoMessageManager = require('../utils/autoMessageManager');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'ready',
|
name: 'ready',
|
||||||
@ -41,7 +42,24 @@ module.exports = {
|
|||||||
console.error('❌ Erreur lors de l\'enregistrement des commandes slash:', error);
|
console.error('❌ Erreur lors de l\'enregistrement des commandes slash:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialiser le gestionnaire de messages automatiques
|
||||||
|
try {
|
||||||
|
// Configuration automatique du serveur au démarrage
|
||||||
|
console.log('🔧 Configuration automatique du serveur...');
|
||||||
|
const ServerControlManager = require('../utils/serverControlManager');
|
||||||
|
const serverControl = new ServerControlManager();
|
||||||
|
await serverControl.setupServerForBot();
|
||||||
|
console.log('✅ Configuration du serveur terminée');
|
||||||
|
|
||||||
|
const autoMessageManager = new AutoMessageManager(client);
|
||||||
|
await autoMessageManager.initialize();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erreur lors de l\'initialisation:', error);
|
||||||
|
}
|
||||||
|
|
||||||
// Définir le statut du bot
|
// Définir le statut du bot
|
||||||
client.user.setActivity(`${process.env.MINECRAFT_SERVER_IP}`, { type: 'WATCHING' });
|
client.user.setActivity(`${process.env.MINECRAFT_SERVER_IP}`, { type: 'WATCHING' });
|
||||||
|
|
||||||
|
console.log('🎮 Bot prêt et opérationnel !');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -1,6 +1,8 @@
|
|||||||
const { ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder } = require('discord.js');
|
const { ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder } = require('discord.js');
|
||||||
const AccessRequestManager = require('../utils/accessRequestManager');
|
const AccessRequestManager = require('../utils/accessRequestManager');
|
||||||
const WhitelistManager = require('../utils/whitelistManager');
|
const WhitelistManager = require('../utils/whitelistManager');
|
||||||
|
const RoleManager = require('../utils/roleManager');
|
||||||
|
const emojiManager = require('../utils/emojiManager');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'interactionCreate',
|
name: 'interactionCreate',
|
||||||
@ -67,6 +69,10 @@ async function handleModalSubmit(interaction) {
|
|||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({ ephemeral: true });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Donner le rôle waiter à l'utilisateur
|
||||||
|
const guildMember = interaction.member;
|
||||||
|
await RoleManager.addWaiterRole(guildMember);
|
||||||
|
|
||||||
// Vérifier si le joueur est déjà whitelisté
|
// Vérifier si le joueur est déjà whitelisté
|
||||||
const whitelistManager = new WhitelistManager();
|
const whitelistManager = new WhitelistManager();
|
||||||
const isAlreadyWhitelisted = await whitelistManager.isPlayerWhitelisted(username);
|
const isAlreadyWhitelisted = await whitelistManager.isPlayerWhitelisted(username);
|
||||||
@ -76,7 +82,7 @@ async function handleModalSubmit(interaction) {
|
|||||||
|
|
||||||
if (!staffChannel) {
|
if (!staffChannel) {
|
||||||
return await interaction.editReply({
|
return await interaction.editReply({
|
||||||
content: '❌ Erreur : Canal du staff introuvable. Contactez un administrateur.'
|
content: `${emojiManager.error} Erreur : Canal du staff introuvable. Contactez un administrateur.`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,10 +95,10 @@ async function handleModalSubmit(interaction) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Répondre à l'utilisateur
|
// Répondre à l'utilisateur
|
||||||
let responseMessage = '✅ Votre demande d\'accès a été envoyée à l\'équipe administrative !';
|
let responseMessage = `${emojiManager.success} Votre demande d'accès a été envoyée à l'équipe administrative !`;
|
||||||
|
|
||||||
if (isAlreadyWhitelisted) {
|
if (isAlreadyWhitelisted) {
|
||||||
responseMessage += '\n\n⚠️ **Note :** Vous êtes déjà dans la whitelist du serveur.';
|
responseMessage += `\n\n${emojiManager.error} **Note :** Vous êtes déjà dans la whitelist du serveur.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
@ -102,7 +108,7 @@ async function handleModalSubmit(interaction) {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors du traitement de la demande d\'accès:', error);
|
console.error('Erreur lors du traitement de la demande d\'accès:', error);
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: '❌ Une erreur est survenue lors du traitement de votre demande. Veuillez réessayer.'
|
content: `${emojiManager.error} Une erreur est survenue lors du traitement de votre demande. Veuillez réessayer.`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
|
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
|
||||||
|
const emojiManager = require('./emojiManager');
|
||||||
|
|
||||||
class AccessRequestManager {
|
class AccessRequestManager {
|
||||||
static createRequestEmbed() {
|
static createRequestEmbed() {
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
.setTitle('🎮 Accès au serveur Minecraft')
|
.setTitle(`${emojiManager.info} Accès au serveur Minecraft`)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
'Bienvenue ! Pour rejoindre notre serveur Minecraft, vous devez être ajouté à la whitelist.\n\n' +
|
'Bienvenue ! Pour rejoindre notre serveur Minecraft, vous devez être ajouté à la whitelist.\n\n' +
|
||||||
'**Comment procéder :**\n' +
|
'**Comment procéder :**\n' +
|
||||||
@ -17,7 +18,7 @@ class AccessRequestManager {
|
|||||||
`**Adresse du serveur :** \`${process.env.MINECRAFT_SERVER_IP}\``
|
`**Adresse du serveur :** \`${process.env.MINECRAFT_SERVER_IP}\``
|
||||||
)
|
)
|
||||||
.setColor('#00FF00')
|
.setColor('#00FF00')
|
||||||
.setThumbnail('https://i.imgur.com/YSO5z0H.png') // Image Minecraft
|
.setThumbnail("https://cdn.discordapp.com/avatars/870707972215550014/b8e97150ca7e455c7f112d37daf1a9ab.webp?size=128")
|
||||||
.setFooter({ text: 'Serveur Minecraft • Demande d\'accès' })
|
.setFooter({ text: 'Serveur Minecraft • Demande d\'accès' })
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
}
|
}
|
||||||
@ -35,7 +36,7 @@ class AccessRequestManager {
|
|||||||
|
|
||||||
static createStaffEmbed(user, username, isAlreadyWhitelisted = false) {
|
static createStaffEmbed(user, username, isAlreadyWhitelisted = false) {
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle('📋 Nouvelle demande d\'accès Minecraft')
|
.setTitle(`${emojiManager.pending} Nouvelle demande d'accès Minecraft`)
|
||||||
.setDescription(`${user} souhaite rejoindre le serveur Minecraft.`)
|
.setDescription(`${user} souhaite rejoindre le serveur Minecraft.`)
|
||||||
.addFields(
|
.addFields(
|
||||||
{ name: '👤 Utilisateur Discord', value: `${user.tag} (${user.id})`, inline: true },
|
{ name: '👤 Utilisateur Discord', value: `${user.tag} (${user.id})`, inline: true },
|
||||||
@ -47,7 +48,7 @@ class AccessRequestManager {
|
|||||||
|
|
||||||
if (isAlreadyWhitelisted) {
|
if (isAlreadyWhitelisted) {
|
||||||
embed.setColor('#FFA500')
|
embed.setColor('#FFA500')
|
||||||
.addFields({ name: '⚠️ Avertissement', value: 'Ce joueur est déjà dans la whitelist !', inline: false });
|
.addFields({ name: `${emojiManager.error} Avertissement`, value: 'Ce joueur est déjà dans la whitelist !', inline: false });
|
||||||
} else {
|
} else {
|
||||||
embed.setColor('#0099FF');
|
embed.setColor('#0099FF');
|
||||||
}
|
}
|
||||||
@ -84,7 +85,7 @@ class AccessRequestManager {
|
|||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
if (accepted) {
|
if (accepted) {
|
||||||
embed.setTitle('✅ Demande acceptée !')
|
embed.setTitle(`${emojiManager.addedWhitelist} Demande acceptée !`)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
`Félicitations ! Votre demande d'accès au serveur Minecraft a été **acceptée**.\n\n` +
|
`Félicitations ! Votre demande d'accès au serveur Minecraft a été **acceptée**.\n\n` +
|
||||||
`**Pseudo ajouté :** \`${username}\`\n` +
|
`**Pseudo ajouté :** \`${username}\`\n` +
|
||||||
@ -93,7 +94,7 @@ class AccessRequestManager {
|
|||||||
)
|
)
|
||||||
.setColor('#00FF00');
|
.setColor('#00FF00');
|
||||||
} else {
|
} else {
|
||||||
embed.setTitle('❌ Demande refusée')
|
embed.setTitle(`${emojiManager.refusedWhitelist} Demande refusée`)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
`Votre demande d'accès au serveur Minecraft a été **refusée**.\n\n` +
|
`Votre demande d'accès au serveur Minecraft a été **refusée**.\n\n` +
|
||||||
`**Pseudo demandé :** \`${username}\`\n` +
|
`**Pseudo demandé :** \`${username}\`\n` +
|
||||||
|
|||||||
198
src/utils/autoMessageManager.js
Normal file
198
src/utils/autoMessageManager.js
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
const AccessRequestManager = require('./accessRequestManager');
|
||||||
|
const MinecraftServerUtil = require('./minecraftServer');
|
||||||
|
const emojiManager = require('./emojiManager');
|
||||||
|
|
||||||
|
class AutoMessageManager {
|
||||||
|
constructor(client) {
|
||||||
|
this.client = client;
|
||||||
|
this.statusUpdateInterval = null;
|
||||||
|
this.lastMessageId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async setupAccessRequestMessage() {
|
||||||
|
try {
|
||||||
|
const channelId = process.env.CHANNEL_REQUEST_ACCESS_ID;
|
||||||
|
if (!channelId) {
|
||||||
|
console.error('❌ CHANNEL_REQUEST_ACCESS_ID non défini dans .env');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = this.client.channels.cache.get(channelId);
|
||||||
|
if (!channel) {
|
||||||
|
console.error(`❌ Canal non trouvé: ${channelId}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`🔍 Vérification du canal ${channel.name}...`);
|
||||||
|
|
||||||
|
// Récupérer les messages récents du canal
|
||||||
|
const messages = await channel.messages.fetch({ limit: 50 });
|
||||||
|
|
||||||
|
// Chercher un message existant du bot avec le bouton de demande d'accès
|
||||||
|
const existingMessage = messages.find(msg =>
|
||||||
|
msg.author.id === this.client.user.id &&
|
||||||
|
msg.content?.includes('Cliquez sur le bouton ci-dessous pour demander l\'accès') &&
|
||||||
|
msg.components.length > 0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingMessage) {
|
||||||
|
console.log(`✅ Message de demande d'accès déjà présent (ID: ${existingMessage.id})`);
|
||||||
|
this.lastMessageId = existingMessage.id;
|
||||||
|
// Mettre à jour le message avec le status actuel
|
||||||
|
await this.updateServerStatus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si aucun message existant, en créer un nouveau
|
||||||
|
console.log('📝 Création d\'un nouveau message de demande d\'accès...');
|
||||||
|
|
||||||
|
const content = `${emojiManager.info} **Demande d'accès au serveur Minecraft**\n\nCliquez sur le bouton ci-dessous pour demander l'accès au serveur Minecraft. Vous devrez fournir votre pseudo Minecraft exact.`;
|
||||||
|
const button = AccessRequestManager.createRequestButton();
|
||||||
|
const statusEmbed = await this.createServerStatusEmbed();
|
||||||
|
|
||||||
|
const sentMessage = await channel.send({
|
||||||
|
content: content,
|
||||||
|
embeds: [statusEmbed],
|
||||||
|
components: [button]
|
||||||
|
});
|
||||||
|
|
||||||
|
this.lastMessageId = sentMessage.id;
|
||||||
|
console.log(`${emojiManager.success} Message de demande d'accès créé avec succès (ID: ${sentMessage.id})`);
|
||||||
|
|
||||||
|
// Démarrer la mise à jour automatique du status
|
||||||
|
this.startStatusUpdates();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Erreur lors de la configuration du message de demande d\'accès:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanOldAccessMessages() {
|
||||||
|
try {
|
||||||
|
const channelId = process.env.CHANNEL_REQUEST_ACCESS_ID;
|
||||||
|
if (!channelId) return;
|
||||||
|
|
||||||
|
const channel = this.client.channels.cache.get(channelId);
|
||||||
|
if (!channel) return;
|
||||||
|
|
||||||
|
// Récupérer les messages récents
|
||||||
|
const messages = await channel.messages.fetch({ limit: 100 });
|
||||||
|
|
||||||
|
// Trouver tous les messages du bot avec des embeds de demande d'accès
|
||||||
|
const botAccessMessages = messages.filter(msg =>
|
||||||
|
msg.author.id === this.client.user.id &&
|
||||||
|
msg.embeds.length > 0 &&
|
||||||
|
msg.embeds[0].title?.includes('Accès au serveur Minecraft')
|
||||||
|
).sort((a, b) => b.createdTimestamp - a.createdTimestamp);
|
||||||
|
|
||||||
|
// Garder seulement le plus récent, supprimer les autres
|
||||||
|
if (botAccessMessages.size > 1) {
|
||||||
|
console.log(`🧹 Suppression de ${botAccessMessages.size - 1} ancien(s) message(s) de demande d'accès...`);
|
||||||
|
|
||||||
|
const messagesToDelete = botAccessMessages.slice(1);
|
||||||
|
for (const message of messagesToDelete.values()) {
|
||||||
|
try {
|
||||||
|
await message.delete();
|
||||||
|
console.log(`🗑️ Message supprimé: ${message.id}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Erreur lors de la suppression du message ${message.id}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du nettoyage des anciens messages:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
console.log('🚀 Initialisation du gestionnaire de messages automatiques...');
|
||||||
|
|
||||||
|
// Nettoyer les anciens messages d'abord
|
||||||
|
await this.cleanOldAccessMessages();
|
||||||
|
|
||||||
|
// Puis configurer le message actuel
|
||||||
|
await this.setupAccessRequestMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
async createServerStatusEmbed() {
|
||||||
|
const serverUtil = new MinecraftServerUtil();
|
||||||
|
const statusData = await serverUtil.getServerStatus();
|
||||||
|
|
||||||
|
const { EmbedBuilder } = require('discord.js');
|
||||||
|
|
||||||
|
if (!statusData.online) {
|
||||||
|
return new EmbedBuilder()
|
||||||
|
.setTitle(`${emojiManager.error} Serveur Hors ligne`)
|
||||||
|
.setDescription(`Le serveur \`${process.env.MINECRAFT_SERVER_IP}\` est actuellement inaccessible.`)
|
||||||
|
.setColor('#FF0000')
|
||||||
|
.setFooter({ text: 'Dernière mise à jour' })
|
||||||
|
.setTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EmbedBuilder()
|
||||||
|
.setTitle(`${emojiManager.success} Serveur En ligne`)
|
||||||
|
.setDescription(`**${process.env.MINECRAFT_SERVER_IP}**`)
|
||||||
|
.addFields(
|
||||||
|
{ name: '👥 Joueurs connectés', value: `${statusData.players.online}/${statusData.players.max}`, inline: true },
|
||||||
|
{ name: '📋 Version', value: statusData.version, inline: true },
|
||||||
|
{ name: '📡 Latence', value: `${statusData.latency}ms`, inline: true }
|
||||||
|
)
|
||||||
|
.setColor('#00FF00')
|
||||||
|
.setFooter({ text: 'Mise à jour automatique toutes les 2 minutes' })
|
||||||
|
.setTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateServerStatus() {
|
||||||
|
try {
|
||||||
|
if (!this.lastMessageId) return;
|
||||||
|
|
||||||
|
const channelId = process.env.CHANNEL_REQUEST_ACCESS_ID;
|
||||||
|
const channel = this.client.channels.cache.get(channelId);
|
||||||
|
if (!channel) return;
|
||||||
|
|
||||||
|
const message = await channel.messages.fetch(this.lastMessageId);
|
||||||
|
if (!message) return;
|
||||||
|
|
||||||
|
const statusEmbed = await this.createServerStatusEmbed();
|
||||||
|
|
||||||
|
await message.edit({
|
||||||
|
content: message.content,
|
||||||
|
embeds: [statusEmbed],
|
||||||
|
components: message.components
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('🔄 Status du serveur mis à jour');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la mise à jour du status:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startStatusUpdates() {
|
||||||
|
// Nettoyer l'ancien interval si il existe
|
||||||
|
if (this.statusUpdateInterval) {
|
||||||
|
clearInterval(this.statusUpdateInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Démarrer la mise à jour toutes les 2 minutes (120000 ms)
|
||||||
|
this.statusUpdateInterval = setInterval(() => {
|
||||||
|
this.updateServerStatus();
|
||||||
|
}, 120000);
|
||||||
|
|
||||||
|
console.log('🕐 Mise à jour automatique du status démarrée (toutes les 2 minutes)');
|
||||||
|
}
|
||||||
|
|
||||||
|
stopStatusUpdates() {
|
||||||
|
if (this.statusUpdateInterval) {
|
||||||
|
clearInterval(this.statusUpdateInterval);
|
||||||
|
this.statusUpdateInterval = null;
|
||||||
|
console.log('⏹️ Mise à jour automatique du status arrêtée');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AutoMessageManager;
|
||||||
46
src/utils/emojiManager.js
Normal file
46
src/utils/emojiManager.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
class EmojiManager {
|
||||||
|
constructor() {
|
||||||
|
this.emojis = this.loadEmojis();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadEmojis() {
|
||||||
|
try {
|
||||||
|
const emojiPath = path.join(__dirname, '../../emojis.json');
|
||||||
|
const data = fs.readFileSync(emojiPath, 'utf8');
|
||||||
|
return JSON.parse(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du chargement des emojis:', error);
|
||||||
|
// Emojis de fallback si le fichier n'est pas trouvé
|
||||||
|
return {
|
||||||
|
added_whitelist_emoji: "✅",
|
||||||
|
removed_whitelist_emoji: "❌",
|
||||||
|
refused_whitelist_emoji: "❌",
|
||||||
|
pending_whitelist_emoji: "⏳",
|
||||||
|
error_emoji: "❌",
|
||||||
|
info_emoji: "ℹ️",
|
||||||
|
success_emoji: "✅"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get(emojiName) {
|
||||||
|
return this.emojis[emojiName] || "❓";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthodes de raccourci pour les emojis fréquemment utilisés
|
||||||
|
get success() { return this.get('success_emoji'); }
|
||||||
|
get error() { return this.get('error_emoji'); }
|
||||||
|
get info() { return this.get('info_emoji'); }
|
||||||
|
get pending() { return this.get('pending_whitelist_emoji'); }
|
||||||
|
get addedWhitelist() { return this.get('added_whitelist_emoji'); }
|
||||||
|
get removedWhitelist() { return this.get('removed_whitelist_emoji'); }
|
||||||
|
get refusedWhitelist() { return this.get('refused_whitelist_emoji'); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instance singleton
|
||||||
|
const emojiManager = new EmojiManager();
|
||||||
|
|
||||||
|
module.exports = emojiManager;
|
||||||
@ -9,23 +9,39 @@ class MinecraftServerUtil {
|
|||||||
|
|
||||||
async getServerStatus() {
|
async getServerStatus() {
|
||||||
try {
|
try {
|
||||||
const result = await status(this.host, this.port);
|
console.log(`🔍 Vérification du serveur ${this.host}:${this.port}...`);
|
||||||
|
const result = await status(this.host, this.port, { timeout: 10000 });
|
||||||
|
console.log('✅ Réponse du serveur reçue');
|
||||||
|
|
||||||
|
// Gérer la description qui peut être un objet complexe
|
||||||
|
let description = 'Serveur Minecraft';
|
||||||
|
if (result.description) {
|
||||||
|
if (typeof result.description === 'string') {
|
||||||
|
description = result.description;
|
||||||
|
} else if (result.description.text) {
|
||||||
|
description = result.description.text;
|
||||||
|
} else if (result.description.extra) {
|
||||||
|
description = result.description.extra.map(part => part.text || '').join('');
|
||||||
|
} else {
|
||||||
|
description = JSON.stringify(result.description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
online: true,
|
online: true,
|
||||||
version: result.version.name,
|
version: result.version?.name || 'Inconnu',
|
||||||
protocol: result.version.protocol,
|
protocol: result.version?.protocol || 0,
|
||||||
players: {
|
players: {
|
||||||
online: result.players.online,
|
online: result.players?.online || 0,
|
||||||
max: result.players.max,
|
max: result.players?.max || 0,
|
||||||
list: result.players.sample || []
|
list: result.players?.sample || []
|
||||||
},
|
},
|
||||||
description: result.description.text || result.description,
|
description: description,
|
||||||
latency: result.roundTripLatency,
|
latency: result.roundTripLatency || 0,
|
||||||
favicon: result.favicon
|
favicon: result.favicon
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la vérification du serveur:', error);
|
console.error('❌ Erreur lors de la vérification du serveur:', error);
|
||||||
return {
|
return {
|
||||||
online: false,
|
online: false,
|
||||||
error: error.message
|
error: error.message
|
||||||
@ -40,10 +56,11 @@ class MinecraftServerUtil {
|
|||||||
|
|
||||||
formatStatusEmbed(statusData) {
|
formatStatusEmbed(statusData) {
|
||||||
const { EmbedBuilder } = require('discord.js');
|
const { EmbedBuilder } = require('discord.js');
|
||||||
|
const emojiManager = require('./emojiManager');
|
||||||
|
|
||||||
if (!statusData.online) {
|
if (!statusData.online) {
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
.setTitle('🔴 Serveur Minecraft - Hors ligne')
|
.setTitle(`${emojiManager.error} Serveur Minecraft - Hors ligne`)
|
||||||
.setDescription(`Le serveur \`${this.serverIP}\` est actuellement hors ligne.`)
|
.setDescription(`Le serveur \`${this.serverIP}\` est actuellement hors ligne.`)
|
||||||
.addFields(
|
.addFields(
|
||||||
{ name: 'Erreur', value: statusData.error || 'Serveur inaccessible', inline: true }
|
{ name: 'Erreur', value: statusData.error || 'Serveur inaccessible', inline: true }
|
||||||
@ -53,7 +70,7 @@ class MinecraftServerUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle('🟢 Serveur Minecraft - En ligne')
|
.setTitle(`${emojiManager.success} Serveur Minecraft - En ligne`)
|
||||||
.setDescription(`Le serveur \`${this.serverIP}\` est en ligne !`)
|
.setDescription(`Le serveur \`${this.serverIP}\` est en ligne !`)
|
||||||
.addFields(
|
.addFields(
|
||||||
{ name: '👥 Joueurs', value: `${statusData.players.online}/${statusData.players.max}`, inline: true },
|
{ name: '👥 Joueurs', value: `${statusData.players.online}/${statusData.players.max}`, inline: true },
|
||||||
@ -63,8 +80,12 @@ class MinecraftServerUtil {
|
|||||||
.setColor('#00FF00')
|
.setColor('#00FF00')
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
if (statusData.description) {
|
if (statusData.description && statusData.description !== 'Serveur Minecraft') {
|
||||||
embed.addFields({ name: '📝 Description', value: statusData.description, inline: false });
|
// Limiter la taille de la description pour éviter les erreurs Discord
|
||||||
|
const description = statusData.description.length > 1024
|
||||||
|
? statusData.description.substring(0, 1021) + '...'
|
||||||
|
: statusData.description;
|
||||||
|
embed.addFields({ name: '📝 Description', value: description, inline: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (statusData.players.list && statusData.players.list.length > 0) {
|
if (statusData.players.list && statusData.players.list.length > 0) {
|
||||||
|
|||||||
103
src/utils/roleManager.js
Normal file
103
src/utils/roleManager.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
class RoleManager {
|
||||||
|
static async addWaiterRole(member) {
|
||||||
|
try {
|
||||||
|
const waiterRoleId = process.env.ROLE_WAITER_ID;
|
||||||
|
if (!waiterRoleId) {
|
||||||
|
console.error('ROLE_WAITER_ID non défini dans .env');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const waiterRole = member.guild.roles.cache.get(waiterRoleId);
|
||||||
|
if (!waiterRole) {
|
||||||
|
console.error(`Rôle waiter non trouvé: ${waiterRoleId}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!member.roles.cache.has(waiterRoleId)) {
|
||||||
|
await member.roles.add(waiterRole);
|
||||||
|
console.log(`✅ Rôle waiter ajouté à ${member.user.tag}`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de l\'ajout du rôle waiter:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async addVerifiedRole(member) {
|
||||||
|
try {
|
||||||
|
const verifiedRoleId = process.env.ROLE_VERIFIED_ID;
|
||||||
|
if (!verifiedRoleId) {
|
||||||
|
console.error('ROLE_VERIFIED_ID non défini dans .env');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifiedRole = member.guild.roles.cache.get(verifiedRoleId);
|
||||||
|
if (!verifiedRole) {
|
||||||
|
console.error(`Rôle verified non trouvé: ${verifiedRoleId}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!member.roles.cache.has(verifiedRoleId)) {
|
||||||
|
await member.roles.add(verifiedRole);
|
||||||
|
console.log(`✅ Rôle verified ajouté à ${member.user.tag}`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de l\'ajout du rôle verified:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async removeWaiterRole(member) {
|
||||||
|
try {
|
||||||
|
const waiterRoleId = process.env.ROLE_WAITER_ID;
|
||||||
|
if (!waiterRoleId) {
|
||||||
|
console.error('ROLE_WAITER_ID non défini dans .env');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (member.roles.cache.has(waiterRoleId)) {
|
||||||
|
await member.roles.remove(waiterRoleId);
|
||||||
|
console.log(`🗑️ Rôle waiter retiré de ${member.user.tag}`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la suppression du rôle waiter:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async removeVerifiedRole(member) {
|
||||||
|
try {
|
||||||
|
const verifiedRoleId = process.env.ROLE_VERIFIED_ID;
|
||||||
|
if (!verifiedRoleId) {
|
||||||
|
console.error('ROLE_VERIFIED_ID non défini dans .env');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (member.roles.cache.has(verifiedRoleId)) {
|
||||||
|
await member.roles.remove(verifiedRoleId);
|
||||||
|
console.log(`🗑️ Rôle verified retiré de ${member.user.tag}`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la suppression du rôle verified:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async handleAccessAccepted(member) {
|
||||||
|
// Ajouter le rôle verified et retirer le rôle waiter
|
||||||
|
const addedVerified = await this.addVerifiedRole(member);
|
||||||
|
const removedWaiter = await this.removeWaiterRole(member);
|
||||||
|
return addedVerified && removedWaiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async handleAccessDenied(member) {
|
||||||
|
// Retirer seulement le rôle waiter
|
||||||
|
return await this.removeWaiterRole(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = RoleManager;
|
||||||
426
src/utils/serverControlManager.js
Normal file
426
src/utils/serverControlManager.js
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
const { exec } = require('child_process');
|
||||||
|
const { promisify } = require('util');
|
||||||
|
const execAsync = promisify(exec);
|
||||||
|
const fs = require('fs').promises;
|
||||||
|
|
||||||
|
class ServerControlManager {
|
||||||
|
constructor() {
|
||||||
|
this.serverPath = process.env.MINECRAFT_SERVER_PATH || '/opt/minecraft/server';
|
||||||
|
this.serviceName = process.env.MINECRAFT_SERVICE_NAME || 'minecraft';
|
||||||
|
this.screenName = 'minecraft'; // Nom de la session screen
|
||||||
|
this.serverUser = 'minecraft'; // Utilisateur qui lance le serveur
|
||||||
|
this.whitelistPath = process.env.MINECRAFT_WHITELIST_PATH;
|
||||||
|
this.useScreen = process.env.USE_SCREEN === 'true'; // true pour screen, false pour systemctl
|
||||||
|
|
||||||
|
// Détecter le type de serveur et le fichier JAR
|
||||||
|
this.serverJar = this.detectServerJar();
|
||||||
|
this.javaArgs = process.env.JAVA_ARGS || '-Xmx2G -Xms1G';
|
||||||
|
}
|
||||||
|
|
||||||
|
detectServerJar() {
|
||||||
|
// Ordre de priorité pour détecter le fichier JAR
|
||||||
|
const possibleJars = [
|
||||||
|
'fabric-server.jar',
|
||||||
|
'fabric-server-launch.jar',
|
||||||
|
'server.jar',
|
||||||
|
'forge-server.jar',
|
||||||
|
'paper.jar',
|
||||||
|
'spigot.jar'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Pour l'instant, on retourne fabric-server.jar puisque c'est ce que vous utilisez
|
||||||
|
// Plus tard, on pourrait faire une détection automatique
|
||||||
|
return process.env.SERVER_JAR || 'fabric-server.jar';
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeCommand(command, description = '') {
|
||||||
|
try {
|
||||||
|
console.log(`🔧 Exécution: ${description || command}`);
|
||||||
|
const { stdout, stderr } = await execAsync(command);
|
||||||
|
|
||||||
|
// Log des détails pour debug
|
||||||
|
if (stdout) console.log(`📤 Sortie: ${stdout.trim()}`);
|
||||||
|
if (stderr && !stderr.includes('Warning')) {
|
||||||
|
console.warn(`⚠️ Erreur stderr: ${stderr.trim()}`);
|
||||||
|
return { success: false, error: stderr.trim(), output: stdout };
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`✅ Succès: ${description || command}`);
|
||||||
|
return { success: true, output: stdout, error: stderr };
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Erreur: ${description || command} - ${error.message}`);
|
||||||
|
return { success: false, error: error.message, output: '' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async reloadWhitelist() {
|
||||||
|
console.log('🔄 Rechargement de la whitelist...');
|
||||||
|
|
||||||
|
if (this.useScreen) {
|
||||||
|
// Méthode screen : commande directe
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo -u ${this.serverUser} screen -S ${this.screenName} -p 0 -X stuff "whitelist reload\n"`,
|
||||||
|
'Rechargement whitelist via commande'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
return { success: true, message: 'Whitelist rechargée via commande serveur' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback systemctl : redémarrage
|
||||||
|
const restartResult = await this.executeCommand(
|
||||||
|
`sudo systemctl restart ${this.serviceName}`,
|
||||||
|
'Redémarrage pour appliquer la whitelist'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (restartResult.success) {
|
||||||
|
return { success: true, message: 'Whitelist rechargée (serveur redémarré)' };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: false, message: 'Impossible de recharger la whitelist' };
|
||||||
|
}
|
||||||
|
|
||||||
|
async getServerStatus() {
|
||||||
|
if (this.useScreen) {
|
||||||
|
// Vérifier si la session screen existe (nom exact ou suffixé)
|
||||||
|
const screenResult = await this.executeCommand(
|
||||||
|
`screen -ls | grep -w "${this.screenName}"`,
|
||||||
|
'Vérification session screen'
|
||||||
|
);
|
||||||
|
const screenRunning = screenResult.success && screenResult.output.trim() !== '';
|
||||||
|
|
||||||
|
// Double vérification : chercher le processus Java avec le bon jar
|
||||||
|
const javaResult = await this.executeCommand(
|
||||||
|
`pgrep -f "${this.serverJar}" | wc -l`,
|
||||||
|
'Vérification processus Java Fabric'
|
||||||
|
);
|
||||||
|
const javaRunning = javaResult.success && parseInt(javaResult.output.trim()) > 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
running: screenRunning && javaRunning,
|
||||||
|
enabled: true,
|
||||||
|
status: screenRunning ?
|
||||||
|
(javaRunning ? 'Running in screen with Java process' : 'Screen session exists but no Java process') :
|
||||||
|
'No screen session found',
|
||||||
|
details: {
|
||||||
|
screen: screenRunning,
|
||||||
|
java: javaRunning,
|
||||||
|
screenOutput: screenResult.output.trim(),
|
||||||
|
javaOutput: javaResult.output.trim()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthode systemctl avec vérification plus précise
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo systemctl is-active ${this.serviceName}`,
|
||||||
|
'Vérification active systemctl'
|
||||||
|
);
|
||||||
|
|
||||||
|
const isActive = result.success && result.output.trim() === 'active';
|
||||||
|
|
||||||
|
const enabledResult = await this.executeCommand(
|
||||||
|
`sudo systemctl is-enabled ${this.serviceName}`,
|
||||||
|
'Vérification enabled systemctl'
|
||||||
|
);
|
||||||
|
const isEnabled = enabledResult.success && enabledResult.output.trim() === 'enabled';
|
||||||
|
|
||||||
|
return {
|
||||||
|
running: isActive,
|
||||||
|
enabled: isEnabled,
|
||||||
|
status: `Active: ${isActive ? 'active' : result.output.trim()}, Enabled: ${isEnabled ? 'enabled' : enabledResult.output.trim()}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async startServer() {
|
||||||
|
if (this.useScreen) {
|
||||||
|
// Vérifier d'abord si le serveur n'est pas déjà lancé
|
||||||
|
const status = await this.getServerStatus();
|
||||||
|
if (status.running) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: 'Le serveur est déjà en cours d\'exécution'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forcer le nom de la session screen à "minecraft"
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo -u ${this.serverUser} screen -dmS ${this.screenName} bash -c "cd ${this.serverPath} && java ${this.javaArgs} -jar ${this.serverJar} nogui"`,
|
||||||
|
'Démarrage du serveur avec screen (nom forcé)'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
// Attendre un peu et vérifier que ça a vraiment démarré
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||||
|
const newStatus = await this.getServerStatus();
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: newStatus.running,
|
||||||
|
message: newStatus.running ? 'Serveur démarré avec screen' : `Échec démarrage: ${result.error || 'Processus non trouvé'}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Erreur: ${result.error}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthode systemctl avec vérification
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo systemctl start ${this.serviceName}`,
|
||||||
|
'Démarrage du serveur'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
// Vérifier que ça a vraiment démarré
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
|
const status = await this.getServerStatus();
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: status.running,
|
||||||
|
message: status.running ? 'Serveur démarré avec succès' : `Échec: ${status.status}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: `Erreur: ${result.error}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async stopServer() {
|
||||||
|
if (this.useScreen) {
|
||||||
|
// Arrêter proprement avec la commande stop
|
||||||
|
const stopResult = await this.executeCommand(
|
||||||
|
`sudo -u ${this.serverUser} screen -S ${this.screenName} -p 0 -X stuff "stop\n"`,
|
||||||
|
'Arrêt propre du serveur'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Attendre un peu puis forcer si nécessaire
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||||
|
|
||||||
|
const killResult = await this.executeCommand(
|
||||||
|
`sudo -u ${this.serverUser} screen -S ${this.screenName} -X quit`,
|
||||||
|
'Fermeture session screen'
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: 'Serveur arrêté'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthode systemctl
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo systemctl stop ${this.serviceName}`,
|
||||||
|
'Arrêt du serveur'
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: result.success,
|
||||||
|
message: result.success ? 'Serveur arrêté avec succès' : `Erreur: ${result.error}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async restartServer() {
|
||||||
|
if (this.useScreen) {
|
||||||
|
// Arrêter puis redémarrer avec screen
|
||||||
|
console.log('🔄 Arrêt du serveur...');
|
||||||
|
await this.stopServer();
|
||||||
|
|
||||||
|
// Attendre un peu
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||||
|
|
||||||
|
console.log('🔄 Redémarrage du serveur...');
|
||||||
|
return await this.startServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthode systemctl
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo systemctl restart ${this.serviceName}`,
|
||||||
|
'Redémarrage du serveur'
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: result.success,
|
||||||
|
message: result.success ? 'Serveur redémarré avec succès' : `Erreur: ${result.error}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getServerLogs(lines = 50) {
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo journalctl -u ${this.serviceName} -n ${lines} --no-pager`,
|
||||||
|
`Récupération des ${lines} dernières lignes de logs`
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: result.success,
|
||||||
|
logs: result.output,
|
||||||
|
error: result.error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendServerCommand(command) {
|
||||||
|
if (this.useScreen) {
|
||||||
|
// Envoyer directement via screen
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo -u ${this.serverUser} screen -S ${this.screenName} -p 0 -X stuff "${command}\n"`,
|
||||||
|
`Envoi commande: ${command}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: result.success,
|
||||||
|
message: result.success ? `Commande "${command}" envoyée` : `Erreur: ${result.error}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pour systemctl, impossible d'envoyer des commandes directes
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: 'Envoi de commandes non supporté avec systemctl (utilisez screen)'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async backupWorld() {
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||||
|
const backupPath = `/opt/minecraft/backups/world_${timestamp}.tar.gz`;
|
||||||
|
|
||||||
|
const result = await this.executeCommand(
|
||||||
|
`sudo mkdir -p /opt/minecraft/backups && sudo tar -czf ${backupPath} -C ${this.serverPath} world`,
|
||||||
|
'Sauvegarde du monde'
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: result.success,
|
||||||
|
message: result.success ? `Monde sauvegardé: ${backupPath}` : `Erreur: ${result.error}`,
|
||||||
|
backupPath: result.success ? backupPath : null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getWhitelistFromFile() {
|
||||||
|
try {
|
||||||
|
const data = await fs.readFile(this.whitelistPath, 'utf8');
|
||||||
|
return JSON.parse(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lecture whitelist:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveWhitelistToFile(whitelist) {
|
||||||
|
try {
|
||||||
|
await fs.writeFile(this.whitelistPath, JSON.stringify(whitelist, null, 2));
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur écriture whitelist:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getServerProperties() {
|
||||||
|
try {
|
||||||
|
const propsPath = `${this.serverPath}/server.properties`;
|
||||||
|
const data = await fs.readFile(propsPath, 'utf8');
|
||||||
|
|
||||||
|
const properties = {};
|
||||||
|
data.split('\n').forEach(line => {
|
||||||
|
if (line.trim() && !line.startsWith('#')) {
|
||||||
|
const [key, value] = line.split('=');
|
||||||
|
if (key && value !== undefined) {
|
||||||
|
properties[key.trim()] = value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { success: true, properties };
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateServerProperty(key, value) {
|
||||||
|
try {
|
||||||
|
const propsPath = `${this.serverPath}/server.properties`;
|
||||||
|
let data = await fs.readFile(propsPath, 'utf8');
|
||||||
|
|
||||||
|
// Remplacer ou ajouter la propriété
|
||||||
|
const regex = new RegExp(`^${key}=.*$`, 'm');
|
||||||
|
if (regex.test(data)) {
|
||||||
|
data = data.replace(regex, `${key}=${value}`);
|
||||||
|
} else {
|
||||||
|
data += `\n${key}=${value}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(propsPath, data);
|
||||||
|
return { success: true, message: `Propriété ${key} mise à jour: ${value}` };
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async setupServerForBot() {
|
||||||
|
console.log('🔧 Configuration automatique du serveur pour le bot...');
|
||||||
|
const results = [];
|
||||||
|
|
||||||
|
// Vérifier si l'utilisateur minecraft existe déjà
|
||||||
|
const userCheck = await this.executeCommand(
|
||||||
|
'id minecraft 2>/dev/null',
|
||||||
|
'Vérification utilisateur minecraft'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!userCheck.success && this.useScreen) {
|
||||||
|
const userResult = await this.executeCommand(
|
||||||
|
'sudo useradd -r -s /bin/bash minecraft',
|
||||||
|
'Création utilisateur minecraft'
|
||||||
|
);
|
||||||
|
results.push(userResult.success ? '✅ Utilisateur minecraft créé' : '❌ Échec création utilisateur');
|
||||||
|
} else if (this.useScreen) {
|
||||||
|
results.push('✅ Utilisateur minecraft existe déjà');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier et créer les dossiers
|
||||||
|
try {
|
||||||
|
await fs.access(this.serverPath);
|
||||||
|
results.push('✅ Dossier serveur existe');
|
||||||
|
} catch (error) {
|
||||||
|
const dirResult = await this.executeCommand(
|
||||||
|
`sudo mkdir -p ${this.serverPath}`,
|
||||||
|
'Création dossier serveur'
|
||||||
|
);
|
||||||
|
results.push(dirResult.success ? '✅ Dossier serveur créé' : '❌ Échec création dossier');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuration permissions si screen
|
||||||
|
if (this.useScreen) {
|
||||||
|
const permResult = await this.executeCommand(
|
||||||
|
`sudo chown -R minecraft:minecraft /opt/minecraft`,
|
||||||
|
'Configuration permissions'
|
||||||
|
);
|
||||||
|
results.push(permResult.success ? '✅ Permissions configurées' : '⚠️ Échec permissions');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuration server.properties
|
||||||
|
const whitelistResult = await this.updateServerProperty('white-list', 'true');
|
||||||
|
const enforceResult = await this.updateServerProperty('enforce-whitelist', 'true');
|
||||||
|
|
||||||
|
results.push(whitelistResult.success ? '✅ Whitelist activée' : '⚠️ Échec whitelist');
|
||||||
|
results.push(enforceResult.success ? '✅ Enforce-whitelist activé' : '⚠️ Échec enforce-whitelist');
|
||||||
|
|
||||||
|
// Création dossier backups
|
||||||
|
const backupResult = await this.executeCommand(
|
||||||
|
'sudo mkdir -p /opt/minecraft/backups',
|
||||||
|
'Création dossier backups'
|
||||||
|
);
|
||||||
|
results.push(backupResult.success ? '✅ Dossier backups créé' : '⚠️ Échec dossier backups');
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: 'Configuration terminée',
|
||||||
|
details: results
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ServerControlManager;
|
||||||
@ -4,6 +4,26 @@ const path = require('path');
|
|||||||
class WhitelistManager {
|
class WhitelistManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.whitelistPath = process.env.MINECRAFT_WHITELIST_PATH;
|
this.whitelistPath = process.env.MINECRAFT_WHITELIST_PATH;
|
||||||
|
// Import dynamique pour éviter les dépendances circulaires
|
||||||
|
this.ServerControlManager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getServerControlManager() {
|
||||||
|
if (!this.ServerControlManager) {
|
||||||
|
const ServerControlManager = require('./serverControlManager');
|
||||||
|
this.ServerControlManager = new ServerControlManager();
|
||||||
|
}
|
||||||
|
return this.ServerControlManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
async reloadMinecraftWhitelist() {
|
||||||
|
try {
|
||||||
|
const serverControl = await this.getServerControlManager();
|
||||||
|
return await serverControl.reloadWhitelist();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors du rechargement de la whitelist:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async readWhitelist() {
|
async readWhitelist() {
|
||||||
@ -44,20 +64,36 @@ class WhitelistManager {
|
|||||||
|
|
||||||
// Si pas d'UUID fourni, essayer de le récupérer via l'API Mojang
|
// Si pas d'UUID fourni, essayer de le récupérer via l'API Mojang
|
||||||
if (!uuid) {
|
if (!uuid) {
|
||||||
|
console.log(`🔍 Récupération de l'UUID pour ${username}...`);
|
||||||
uuid = await this.getUUIDFromUsername(username);
|
uuid = await this.getUUIDFromUsername(username);
|
||||||
if (!uuid) {
|
if (!uuid) {
|
||||||
return { success: false, message: 'Impossible de trouver l\'UUID pour ce joueur.' };
|
return { success: false, message: 'Impossible de trouver l\'UUID pour ce joueur. Vérifiez que le pseudo existe.' };
|
||||||
}
|
}
|
||||||
|
console.log(`✅ UUID trouvé pour ${username}: ${uuid}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajouter le joueur
|
// Ajouter le joueur
|
||||||
whitelist.push({
|
const newPlayer = {
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
name: username
|
name: username
|
||||||
});
|
};
|
||||||
|
|
||||||
|
whitelist.push(newPlayer);
|
||||||
|
console.log(`📝 Ajout du joueur à la whitelist:`, newPlayer);
|
||||||
|
|
||||||
const success = await this.writeWhitelist(whitelist);
|
const success = await this.writeWhitelist(whitelist);
|
||||||
if (success) {
|
if (success) {
|
||||||
|
console.log(`✅ ${username} ajouté avec succès à la whitelist`);
|
||||||
|
|
||||||
|
// Recharger automatiquement la whitelist sur le serveur
|
||||||
|
console.log('🔄 Rechargement de la whitelist sur le serveur...');
|
||||||
|
const reloadSuccess = await this.reloadMinecraftWhitelist();
|
||||||
|
if (reloadSuccess) {
|
||||||
|
console.log('✅ Whitelist rechargée avec succès sur le serveur');
|
||||||
|
} else {
|
||||||
|
console.log('⚠️ Impossible de recharger la whitelist automatiquement');
|
||||||
|
}
|
||||||
|
|
||||||
return { success: true, message: `${username} a été ajouté à la whitelist.` };
|
return { success: true, message: `${username} a été ajouté à la whitelist.` };
|
||||||
} else {
|
} else {
|
||||||
return { success: false, message: 'Erreur lors de l\'ajout du joueur.' };
|
return { success: false, message: 'Erreur lors de l\'ajout du joueur.' };
|
||||||
@ -66,9 +102,7 @@ class WhitelistManager {
|
|||||||
console.error('Erreur lors de l\'ajout du joueur:', error);
|
console.error('Erreur lors de l\'ajout du joueur:', error);
|
||||||
return { success: false, message: 'Erreur interne lors de l\'ajout du joueur.' };
|
return { success: false, message: 'Erreur interne lors de l\'ajout du joueur.' };
|
||||||
}
|
}
|
||||||
}
|
} async removePlayer(username) {
|
||||||
|
|
||||||
async removePlayer(username) {
|
|
||||||
try {
|
try {
|
||||||
const whitelist = await this.readWhitelist();
|
const whitelist = await this.readWhitelist();
|
||||||
const initialLength = whitelist.length;
|
const initialLength = whitelist.length;
|
||||||
@ -83,6 +117,17 @@ class WhitelistManager {
|
|||||||
|
|
||||||
const success = await this.writeWhitelist(newWhitelist);
|
const success = await this.writeWhitelist(newWhitelist);
|
||||||
if (success) {
|
if (success) {
|
||||||
|
console.log(`✅ ${username} retiré avec succès de la whitelist`);
|
||||||
|
|
||||||
|
// Recharger automatiquement la whitelist sur le serveur
|
||||||
|
console.log('🔄 Rechargement de la whitelist sur le serveur...');
|
||||||
|
const reloadSuccess = await this.reloadMinecraftWhitelist();
|
||||||
|
if (reloadSuccess) {
|
||||||
|
console.log('✅ Whitelist rechargée avec succès sur le serveur');
|
||||||
|
} else {
|
||||||
|
console.log('⚠️ Impossible de recharger la whitelist automatiquement');
|
||||||
|
}
|
||||||
|
|
||||||
return { success: true, message: `${username} a été retiré de la whitelist.` };
|
return { success: true, message: `${username} a été retiré de la whitelist.` };
|
||||||
} else {
|
} else {
|
||||||
return { success: false, message: 'Erreur lors de la suppression du joueur.' };
|
return { success: false, message: 'Erreur lors de la suppression du joueur.' };
|
||||||
@ -108,12 +153,29 @@ class WhitelistManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data.id;
|
// Convertir l'UUID compact en UUID avec tirets
|
||||||
|
return this.formatUUID(data.id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la récupération de l\'UUID:', error);
|
console.error('Erreur lors de la récupération de l\'UUID:', error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Formate un UUID compact (32 caractères) en UUID avec tirets (36 caractères)
|
||||||
|
formatUUID(compactUUID) {
|
||||||
|
if (!compactUUID || compactUUID.length !== 32) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
return [
|
||||||
|
compactUUID.substring(0, 8),
|
||||||
|
compactUUID.substring(8, 12),
|
||||||
|
compactUUID.substring(12, 16),
|
||||||
|
compactUUID.substring(16, 20),
|
||||||
|
compactUUID.substring(20, 32)
|
||||||
|
].join('-');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = WhitelistManager;
|
module.exports = WhitelistManager;
|
||||||
Loading…
Reference in New Issue
Block a user