ajouter une section pour personnaliser l'apparence du bot avec prévisualisation et options de sauvegarde

This commit is contained in:
Arthur Puechberty
2026-01-18 14:03:44 +01:00
parent a3ebe47c24
commit 27bf9750d1
4 changed files with 293 additions and 0 deletions
+71
View File
@@ -964,3 +964,74 @@ body {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
/* ===== Bot Appearance ===== */
.bot-preview-card {
display: flex;
align-items: center;
gap: var(--spacing-md);
background: var(--bg-dark);
padding: var(--spacing-md);
border-radius: var(--radius-md);
max-width: 300px;
}
.bot-preview-card img {
width: 64px;
height: 64px;
border-radius: 50%;
}
.bot-preview-info {
display: flex;
align-items: center;
gap: var(--spacing-sm);
}
.bot-preview-name {
font-weight: 600;
color: var(--text-primary);
font-size: 1.1rem;
}
.bot-preview-tag {
background: var(--primary-color);
color: white;
font-size: 0.65rem;
padding: 2px 5px;
border-radius: 3px;
font-weight: 600;
}
.alert {
padding: var(--spacing-md);
border-radius: var(--radius-sm);
margin-bottom: var(--spacing-md);
}
.alert-warning {
background: rgba(240, 178, 50, 0.15);
border: 1px solid rgba(240, 178, 50, 0.3);
color: #F0B232;
}
.alert-warning strong {
color: #F0B232;
}
.avatar-preview-container {
display: flex;
align-items: center;
gap: var(--spacing-md);
background: var(--bg-dark);
padding: var(--spacing-md);
border-radius: var(--radius-md);
}
.avatar-preview {
width: 80px;
height: 80px;
border-radius: 50%;
object-fit: cover;
display: none;
}
+52
View File
@@ -70,6 +70,10 @@
<span class="nav-item-icon">✉️</span> <span class="nav-item-icon">✉️</span>
Envoyer un message Envoyer un message
</a> </a>
<a class="nav-item" data-section="botappearance">
<span class="nav-item-icon">🤖</span>
Apparence du bot
</a>
</div> </div>
</nav> </nav>
@@ -1062,6 +1066,53 @@
</div> </div>
</section> </section>
<!-- Section: Apparence du bot -->
<section class="config-section" id="section-botappearance">
<div class="config-card">
<div class="config-card-header">
<div>
<h2 class="config-card-title">🤖 Apparence du bot</h2>
<p class="config-card-subtitle">Personnalisez le pseudo du bot sur ce serveur</p>
</div>
</div>
<div class="config-card-body">
<!-- Aperçu actuel -->
<div class="form-group">
<label class="form-label">👁️ Aperçu actuel</label>
<div class="bot-preview-card" id="bot-preview">
<img id="bot-preview-avatar" src="https://cdn.discordapp.com/embed/avatars/0.png" alt="Avatar">
<div class="bot-preview-info">
<div class="bot-preview-name" id="bot-preview-name">Chargement...</div>
<div class="bot-preview-tag">BOT</div>
</div>
</div>
</div>
<!-- Pseudo sur le serveur -->
<div class="sub-section">
<h4 class="sub-section-title">📝 Pseudo sur ce serveur</h4>
<p class="text-muted" style="margin-bottom: 1rem;">Le pseudo du bot sera visible uniquement sur ce serveur.</p>
<div class="form-group">
<label class="form-label">Nouveau pseudo</label>
<input type="text" class="form-input" id="bot-nickname" placeholder="Laissez vide pour utiliser le nom par défaut" maxlength="32">
</div>
<div class="form-actions">
<button type="button" class="btn btn-primary" id="bot-nickname-save">
💾 Sauvegarder le pseudo
</button>
<button type="button" class="btn btn-secondary" id="bot-nickname-reset">
🔄 Réinitialiser
</button>
</div>
</div>
</div>
</div>
</section>
</div> </div>
</main> </main>
@@ -1081,5 +1132,6 @@
<script src="/guild/statsChannelsForm.js"></script> <script src="/guild/statsChannelsForm.js"></script>
<script src="/guild/scheduledMessagesForm.js"></script> <script src="/guild/scheduledMessagesForm.js"></script>
<script src="/guild/sendMessageForm.js"></script> <script src="/guild/sendMessageForm.js"></script>
<script src="/guild/botAppearanceForm.js"></script>
</body> </body>
</html> </html>
+104
View File
@@ -0,0 +1,104 @@
// ===== BOT APPEARANCE FORM =====
(async function () {
const previewAvatar = document.getElementById("bot-preview-avatar");
const previewName = document.getElementById("bot-preview-name");
const nicknameInput = document.getElementById("bot-nickname");
const nicknameSaveBtn = document.getElementById("bot-nickname-save");
const nicknameResetBtn = document.getElementById("bot-nickname-reset");
let botData = null;
// Charger les infos du bot
async function loadBotInfo() {
try {
const res = await fetch(`/api/bot/get-bot-appearance/${window.guildId}`);
const data = await res.json();
if (data.success) {
botData = data;
// Mettre à jour l'aperçu
if (data.avatarUrl) {
previewAvatar.src = data.avatarUrl;
}
previewName.textContent = data.nickname || data.username;
// Remplir les champs
nicknameInput.value = data.nickname || "";
nicknameInput.placeholder = data.username + " (par défaut)";
}
} catch (err) {
console.error("Erreur chargement bot info:", err);
}
}
// Sauvegarder le pseudo
nicknameSaveBtn.addEventListener("click", async () => {
const nickname = nicknameInput.value.trim();
nicknameSaveBtn.disabled = true;
nicknameSaveBtn.textContent = "⏳ Sauvegarde...";
try {
const res = await fetch("/api/bot/set-nickname", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
guildId: window.guildId,
nickname: nickname || null
})
});
const data = await res.json();
if (data.success) {
alert("✅ Pseudo mis à jour avec succès !");
previewName.textContent = nickname || botData.username;
} else {
alert("❌ Erreur: " + (data.error || "Erreur inconnue"));
}
} catch (err) {
console.error(err);
alert("❌ Erreur lors de la mise à jour du pseudo.");
}
nicknameSaveBtn.disabled = false;
nicknameSaveBtn.textContent = "💾 Sauvegarder le pseudo";
});
// Réinitialiser le pseudo
nicknameResetBtn.addEventListener("click", async () => {
nicknameResetBtn.disabled = true;
nicknameResetBtn.textContent = "⏳ Réinitialisation...";
try {
const res = await fetch("/api/bot/set-nickname", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
guildId: window.guildId,
nickname: null
})
});
const data = await res.json();
if (data.success) {
alert("✅ Pseudo réinitialisé !");
nicknameInput.value = "";
previewName.textContent = botData.username;
} else {
alert("❌ Erreur: " + (data.error || "Erreur inconnue"));
}
} catch (err) {
console.error(err);
alert("❌ Erreur lors de la réinitialisation.");
}
nicknameResetBtn.disabled = false;
nicknameResetBtn.textContent = "🔄 Réinitialiser";
});
// Initialiser
loadBotInfo();
})();
+66
View File
@@ -1215,5 +1215,71 @@ module.exports = (app, db, client) => {
} }
}); });
// ===== BOT APPEARANCE =====
// Obtenir les infos d'apparence du bot
router.get("/bot/get-bot-appearance/:guildId", async (req, res) => {
const { guildId } = req.params;
if (!req.session.guilds) {
return res.status(401).json({ success: false, error: "Non connecté" });
}
try {
const guild = client.guilds.cache.get(guildId);
if (!guild) {
return res.status(404).json({ success: false, error: "Serveur non trouvé" });
}
const botMember = guild.members.me;
const bot = client.user;
res.json({
success: true,
username: bot.username,
nickname: botMember?.nickname || null,
avatarUrl: bot.displayAvatarURL({ size: 256 }),
discriminator: bot.discriminator
});
} catch (err) {
console.error("Erreur get bot appearance:", err);
res.status(500).json({ success: false, error: err.message });
}
});
// Changer le pseudo du bot sur un serveur
router.post("/bot/set-nickname", express.json(), async (req, res) => {
const { guildId, nickname } = req.body;
if (!req.session.guilds) {
return res.status(401).json({ success: false, error: "Non connecté" });
}
const isAdmin = req.session.guilds.find(
g => g.id === guildId && (BigInt(g.permissions) & 0x8n) === 0x8n
);
if (!isAdmin) {
return res.status(403).json({ success: false, error: "Permission refusée" });
}
try {
const guild = client.guilds.cache.get(guildId);
if (!guild) {
return res.status(404).json({ success: false, error: "Serveur non trouvé" });
}
const botMember = guild.members.me;
await botMember.setNickname(nickname || null);
res.json({ success: true });
} catch (err) {
console.error("Erreur set nickname:", err);
res.status(500).json({ success: false, error: err.message });
}
});
app.use("/api", router); app.use("/api", router);
}; };