mirror of
https://github.com/arthur-pbty/LazyBot.git
synced 2026-06-03 15:07:29 +02:00
add auto role for new member and member in vocal
This commit is contained in:
+48
@@ -42,6 +42,18 @@ client.on(Events.GuildMemberAdd, member => {
|
||||
}
|
||||
}
|
||||
);
|
||||
db.get(
|
||||
"SELECT enabled, role_id FROM autorole_newuser_config WHERE guild_id = ?",
|
||||
[member.guild.id],
|
||||
(err, row) => {
|
||||
if (err || !row || !row.enabled) return;
|
||||
|
||||
const role = member.guild.roles.cache.get(row.role_id);
|
||||
if (role) {
|
||||
member.roles.add(role);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -67,6 +79,42 @@ client.on(Events.GuildMemberRemove, member => {
|
||||
});
|
||||
|
||||
|
||||
client.on(Events.VoiceStateUpdate, (oldState, newState) => {
|
||||
if (newState.member.user.bot) return;
|
||||
|
||||
const guildId = newState.guild.id;
|
||||
|
||||
db.get(
|
||||
"SELECT enabled, role_id, exclude_channel_ids FROM autorole_vocal_config WHERE guild_id = ?",
|
||||
[guildId],
|
||||
(err, row) => {
|
||||
if (err || !row || !row.enabled) return;
|
||||
|
||||
let excludeChannelIds = [];
|
||||
try {
|
||||
excludeChannelIds = row.exclude_channel_ids
|
||||
? JSON.parse(row.exclude_channel_ids)
|
||||
: [];
|
||||
} catch (err) {
|
||||
console.error("Erreur parsing exclude_channel_ids", err);
|
||||
excludeChannelIds = [];
|
||||
}
|
||||
|
||||
const role = newState.guild.roles.cache.get(row.role_id);
|
||||
if (!role) return;
|
||||
|
||||
// User joins a voice channel and it's not excluded et a pas déjà le rôle
|
||||
if (newState.channelId && !excludeChannelIds.includes(newState.channelId) && !newState.member.roles.cache.has(role.id)) {
|
||||
newState.member.roles.add(role);
|
||||
}
|
||||
// User leaves a voice channel or joins an excluded one
|
||||
else if (!newState.channelId || excludeChannelIds.includes(newState.channelId)) {
|
||||
newState.member.roles.remove(role);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
client.login(process.env.BOT_TOKEN);
|
||||
|
||||
module.exports = client;
|
||||
|
||||
@@ -24,6 +24,19 @@ db.exec(`
|
||||
enabled INTEGER NOT NULL,
|
||||
message TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS autorole_newuser_config (
|
||||
guild_id TEXT PRIMARY KEY,
|
||||
role_id TEXT,
|
||||
enabled INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS autorole_vocal_config (
|
||||
guild_id TEXT PRIMARY KEY,
|
||||
role_id TEXT,
|
||||
exclude_channel_ids TEXT,
|
||||
enabled INTEGER NOT NULL
|
||||
);
|
||||
`);
|
||||
|
||||
module.exports = db;
|
||||
|
||||
@@ -140,3 +140,60 @@ small code {
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
#autorole-vocal-exclude-channel {
|
||||
background-color: #0f1115;
|
||||
color: #e5e7eb;
|
||||
|
||||
border: 1px solid #2a2f3a;
|
||||
border-radius: 8px;
|
||||
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
|
||||
min-width: 240px;
|
||||
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* options */
|
||||
#autorole-vocal-exclude-channel option {
|
||||
background-color: #0f1115;
|
||||
color: #e5e7eb;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
/* hover */
|
||||
#autorole-vocal-exclude-channel option:hover {
|
||||
background-color: #1f2937;
|
||||
}
|
||||
|
||||
/* sélection */
|
||||
#autorole-vocal-exclude-channel option:checked {
|
||||
background-color: #2563eb; /* bleu */
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* focus */
|
||||
#autorole-vocal-exclude-channel:focus {
|
||||
border-color: #2563eb;
|
||||
box-shadow: 0 0 0 1px #2563eb;
|
||||
}
|
||||
|
||||
/* scrollbar (Chrome / Edge) */
|
||||
#autorole-vocal-exclude-channel::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
#autorole-vocal-exclude-channel::-webkit-scrollbar-track {
|
||||
background: #0f1115;
|
||||
}
|
||||
|
||||
#autorole-vocal-exclude-channel::-webkit-scrollbar-thumb {
|
||||
background: #2a2f3a;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#autorole-vocal-exclude-channel::-webkit-scrollbar-thumb:hover {
|
||||
background: #3b4252;
|
||||
}
|
||||
|
||||
+159
-11
@@ -90,6 +90,49 @@
|
||||
</form>
|
||||
|
||||
|
||||
<form id="autorole-newuser-form">
|
||||
<label>
|
||||
<input type="checkbox" id="autorole-enabled" />
|
||||
Activer le rôle automatique pour les nouveaux membres
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Rôle à attribuer :
|
||||
<br />
|
||||
<select id="autorole-role">
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<button type="submit">Sauvegarder</button>
|
||||
<div id="status-autorole-form"></div>
|
||||
</form>
|
||||
|
||||
|
||||
<form id="autorole-vocal-form">
|
||||
<label>
|
||||
<input type="checkbox" id="autorole-vocal-enabled" />
|
||||
Activer le rôle automatique pour les membres en vocal
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Rôle à attribuer :
|
||||
<br />
|
||||
<select id="autorole-vocal-role">
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Salon à éviter :
|
||||
<br />
|
||||
<select id="autorole-vocal-exclude-channel" multiple size="5">
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<button type="submit">Sauvegarder</button>
|
||||
<div id="status-autorole-vocal-form"></div>
|
||||
</form>
|
||||
|
||||
|
||||
<script>
|
||||
const guildId = window.location.pathname.split("/")[2]; // récupère l'ID du serveur
|
||||
|
||||
@@ -109,6 +152,68 @@
|
||||
});
|
||||
|
||||
|
||||
fetch(`/api/bot/get-text-channels/${guildId}`)
|
||||
.then(res => res.json())
|
||||
.then(channels => {
|
||||
const selectWelcome = document.getElementById("welcome-channel");
|
||||
const selectGoodbye = document.getElementById("goodbye-channel");
|
||||
channels.forEach(channel => {
|
||||
const option = document.createElement("option");
|
||||
option.value = channel.id;
|
||||
option.textContent = `#${channel.name}`;
|
||||
selectWelcome.appendChild(option);
|
||||
selectGoodbye.appendChild(option.cloneNode(true));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
const selectExclude = document.getElementById("autorole-vocal-exclude-channel");
|
||||
selectExclude.innerHTML = ""; // reset
|
||||
|
||||
fetch(`/api/bot/get-voice-channels/${guildId}`)
|
||||
.then(res => res.json())
|
||||
.then(channels => {
|
||||
channels.forEach(channel => {
|
||||
const option = document.createElement("option");
|
||||
option.value = channel.id;
|
||||
option.textContent = `#${channel.name}`;
|
||||
selectExclude.appendChild(option);
|
||||
});
|
||||
return fetch(`/api/bot/get-autorole-vocal-config/${guildId}`);
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(cfg => {
|
||||
document.getElementById("autorole-vocal-enabled").checked = !!cfg.enabled;
|
||||
document.getElementById("autorole-vocal-role").value = cfg.roleId ?? "";
|
||||
|
||||
const excluded = Array.isArray(cfg.excludeChannelIds)
|
||||
? cfg.excludeChannelIds.map(String) // sécurité
|
||||
: [];
|
||||
|
||||
Array.from(selectExclude.options).forEach(option => {
|
||||
option.selected = excluded.includes(option.value);
|
||||
});
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
|
||||
|
||||
fetch(`/api/bot/get-roles/${guildId}`)
|
||||
.then(res => res.json())
|
||||
.then(roles => {
|
||||
const selectAutorole = document.getElementById("autorole-role");
|
||||
const selectAutoroleVocal = document.getElementById("autorole-vocal-role");
|
||||
roles.forEach(role => {
|
||||
const option = document.createElement("option");
|
||||
option.value = role.id;
|
||||
option.textContent = role.name;
|
||||
selectAutorole.appendChild(option);
|
||||
selectAutoroleVocal.appendChild(option.cloneNode(true));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
const welcomeForm = document.getElementById("welcome-form");
|
||||
welcomeForm.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
@@ -159,18 +264,51 @@
|
||||
});
|
||||
|
||||
|
||||
fetch(`/api/bot/get-text-channels/${guildId}`)
|
||||
.then(res => res.json())
|
||||
.then(channels => {
|
||||
const selectWelcome = document.getElementById("welcome-channel");
|
||||
const selectGoodbye = document.getElementById("goodbye-channel");
|
||||
channels.forEach(channel => {
|
||||
const option = document.createElement("option");
|
||||
option.value = channel.id;
|
||||
option.textContent = `#${channel.name}`;
|
||||
selectWelcome.appendChild(option);
|
||||
selectGoodbye.appendChild(option.cloneNode(true));
|
||||
const autoroleNewUserForm = document.getElementById("autorole-newuser-form");
|
||||
autoroleNewUserForm.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
const enabled = document.getElementById("autorole-enabled").checked;
|
||||
const roleId = document.getElementById("autorole-role").value;
|
||||
|
||||
const res = await fetch("/api/bot/save-autorole-newuser-config", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
guildId,
|
||||
roleId,
|
||||
enabled,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
document.getElementById("status-autorole-form").textContent = data.success
|
||||
? "Config d'auto-rôle pour nouveaux membres sauvegardée ✅"
|
||||
: "Erreur ❌";
|
||||
});
|
||||
|
||||
|
||||
const autoroleVocalForm = document.getElementById("autorole-vocal-form");
|
||||
autoroleVocalForm.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
const enabled = document.getElementById("autorole-vocal-enabled").checked;
|
||||
const roleId = document.getElementById("autorole-vocal-role").value;
|
||||
const excludeChannelSelect = document.getElementById("autorole-vocal-exclude-channel");
|
||||
const excludeChannelId = Array.from(excludeChannelSelect.selectedOptions).map(option => option.value);
|
||||
|
||||
const res = await fetch("/api/bot/save-autorole-vocal-config", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
guildId,
|
||||
roleId,
|
||||
excludeChannelId,
|
||||
enabled,
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
document.getElementById("status-autorole-vocal-form").textContent = data.success
|
||||
? "Config d'auto-rôle pour membres en vocal sauvegardée ✅"
|
||||
: "Erreur ❌";
|
||||
});
|
||||
|
||||
|
||||
@@ -190,6 +328,16 @@
|
||||
document.getElementById("goodbye-channel").value = cfg.channelId;
|
||||
document.getElementById("goodbye-message").value = cfg.message;
|
||||
});
|
||||
|
||||
|
||||
fetch(`/api/bot/get-autorole-newuser-config/${guildId}`)
|
||||
.then(res => res.json())
|
||||
.then(cfg => {
|
||||
document.getElementById("autorole-enabled").checked = cfg.enabled;
|
||||
document.getElementById("autorole-role").value = cfg.roleId;
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div id="profil">
|
||||
<img id="avatar" src="" alt="Avatar">
|
||||
<span id="username"></span>
|
||||
<a id="logout" href="/logout">Se déconnecter</a>
|
||||
<a id="logout" href="/auth/logout">Se déconnecter</a>
|
||||
</div>
|
||||
</nav>
|
||||
<h1>LazyBot</h1>
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
module.exports = (app, db, client) => {
|
||||
|
||||
// --- User info ---
|
||||
router.get("/user", (req, res) => {
|
||||
if (req.session.user) res.json(req.session.user);
|
||||
else res.status(401).json({ error: "Utilisateur non connecté" });
|
||||
});
|
||||
|
||||
router.get("/guilds", (req, res) => {
|
||||
const userGuilds = req.session.guilds;
|
||||
if (!userGuilds) return res.status(401).json({ error: "Utilisateur non connecté" });
|
||||
|
||||
const botGuildIds = client.guilds.cache.map(g => g.id);
|
||||
const validGuilds = userGuilds.filter(g => {
|
||||
const hasAdmin = (g.permissions & 0x8) === 0x8;
|
||||
return hasAdmin && botGuildIds.includes(g.id);
|
||||
});
|
||||
|
||||
res.json(validGuilds);
|
||||
});
|
||||
|
||||
|
||||
// API pour sauvegarder la configuration de bienvenue
|
||||
router.post("/bot/save-welcome-config", express.json(), (req, res) => {
|
||||
const { guildId, channelId, welcomeEnabled, welcomeMessage } = req.body;
|
||||
|
||||
if (!req.session.guilds) {
|
||||
return res.status(401).json({ success: false });
|
||||
}
|
||||
|
||||
const isAdmin = req.session.guilds.find(
|
||||
g => g.id === guildId && (BigInt(g.permissions) & 0x8n) === 0x8n
|
||||
);
|
||||
|
||||
if (!isAdmin) {
|
||||
return res.status(403).json({ success: false });
|
||||
}
|
||||
|
||||
db.run(
|
||||
`
|
||||
INSERT INTO welcome_config (guild_id, channel_id, enabled, message)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(guild_id)
|
||||
DO UPDATE SET channel_id = ?, enabled = ?, message = ?
|
||||
`,
|
||||
[
|
||||
guildId,
|
||||
channelId,
|
||||
welcomeEnabled ? 1 : 0,
|
||||
welcomeMessage,
|
||||
channelId,
|
||||
welcomeEnabled ? 1 : 0,
|
||||
welcomeMessage
|
||||
],
|
||||
err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return res.status(500).json({ success: false });
|
||||
}
|
||||
res.json({ success: true });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
router.get("/bot/get-welcome-config/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
|
||||
db.get(
|
||||
"SELECT enabled, channel_id, message FROM welcome_config WHERE guild_id = ?",
|
||||
[guildId],
|
||||
(err, row) => {
|
||||
if (err || !row) {
|
||||
return res.json({ enabled: false, channelId: null, message: "" });
|
||||
}
|
||||
res.json({
|
||||
enabled: !!row.enabled,
|
||||
channelId: row.channel_id,
|
||||
message: row.message
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
router.post("/bot/save-goodbye-config", express.json(), (req, res) => {
|
||||
const { guildId, channelId, goodbyeEnabled, goodbyeMessage } = req.body;
|
||||
|
||||
if (!req.session.guilds) {
|
||||
return res.status(401).json({ success: false });
|
||||
}
|
||||
|
||||
const isAdmin = req.session.guilds.find(
|
||||
g => g.id === guildId && (BigInt(g.permissions) & 0x8n) === 0x8n
|
||||
);
|
||||
|
||||
if (!isAdmin) {
|
||||
return res.status(403).json({ success: false });
|
||||
}
|
||||
|
||||
db.run(
|
||||
`
|
||||
INSERT INTO goodbye_config (guild_id, channel_id, enabled, message)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(guild_id)
|
||||
DO UPDATE SET channel_id = ?, enabled = ?, message = ?
|
||||
`,
|
||||
[
|
||||
guildId,
|
||||
channelId,
|
||||
goodbyeEnabled ? 1 : 0,
|
||||
goodbyeMessage,
|
||||
channelId,
|
||||
goodbyeEnabled ? 1 : 0,
|
||||
goodbyeMessage
|
||||
],
|
||||
err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return res.status(500).json({ success: false });
|
||||
}
|
||||
res.json({ success: true });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
router.get("/bot/get-goodbye-config/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
|
||||
db.get(
|
||||
"SELECT enabled, channel_id, message FROM goodbye_config WHERE guild_id = ?",
|
||||
[guildId],
|
||||
(err, row) => {
|
||||
if (err || !row) {
|
||||
return res.json({ enabled: false, channelId: null, message: "" });
|
||||
}
|
||||
res.json({
|
||||
enabled: !!row.enabled,
|
||||
channelId: row.channel_id,
|
||||
message: row.message
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
router.post("/bot/save-autorole-newuser-config", express.json(), (req, res) => {
|
||||
const { guildId, roleId, enabled } = req.body;
|
||||
console.log("Received autorole-newuser config:", { guildId, roleId, enabled });
|
||||
if (!req.session.guilds) {
|
||||
return res.status(401).json({ success: false });
|
||||
}
|
||||
|
||||
const isAdmin = req.session.guilds.find(
|
||||
g => g.id === guildId && (BigInt(g.permissions) & 0x8n) === 0x8n
|
||||
);
|
||||
|
||||
if (!isAdmin) {
|
||||
return res.status(403).json({ success: false });
|
||||
}
|
||||
|
||||
db.run(
|
||||
`
|
||||
INSERT INTO autorole_newuser_config (guild_id, role_id, enabled)
|
||||
VALUES (?, ?, ?)
|
||||
ON CONFLICT(guild_id)
|
||||
DO UPDATE SET role_id = ?, enabled = ?
|
||||
`,
|
||||
[
|
||||
guildId,
|
||||
roleId,
|
||||
enabled ? 1 : 0,
|
||||
roleId,
|
||||
enabled ? 1 : 0
|
||||
],
|
||||
err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return res.status(500).json({ success: false });
|
||||
}
|
||||
res.json({ success: true });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
router.get("/bot/get-autorole-newuser-config/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
|
||||
db.get(
|
||||
"SELECT enabled, role_id FROM autorole_newuser_config WHERE guild_id = ?",
|
||||
[guildId],
|
||||
(err, row) => {
|
||||
if (err || !row) {
|
||||
return res.json({ enabled: false, roleId: null });
|
||||
}
|
||||
res.json({
|
||||
enabled: !!row.enabled,
|
||||
roleId: row.role_id
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
router.post("/bot/save-autorole-vocal-config", express.json(), (req, res) => {
|
||||
const { guildId, roleId, excludeChannelId, enabled } = req.body;
|
||||
|
||||
if (!req.session.guilds) {
|
||||
return res.status(401).json({ success: false });
|
||||
}
|
||||
|
||||
const isAdmin = req.session.guilds.find(
|
||||
g => g.id === guildId && (BigInt(g.permissions) & 0x8n) === 0x8n
|
||||
);
|
||||
|
||||
if (!isAdmin) {
|
||||
return res.status(403).json({ success: false });
|
||||
}
|
||||
|
||||
const excludeChannelIdArray = Array.isArray(excludeChannelId) ? excludeChannelId : [excludeChannelId];
|
||||
|
||||
db.run(
|
||||
`
|
||||
INSERT INTO autorole_vocal_config (guild_id, role_id, exclude_channel_ids, enabled)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(guild_id)
|
||||
DO UPDATE SET role_id = ?, exclude_channel_ids = ?, enabled = ?
|
||||
`,
|
||||
[
|
||||
guildId,
|
||||
roleId,
|
||||
JSON.stringify(excludeChannelIdArray),
|
||||
enabled ? 1 : 0,
|
||||
roleId,
|
||||
JSON.stringify(excludeChannelIdArray),
|
||||
enabled ? 1 : 0
|
||||
],
|
||||
err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return res.status(500).json({ success: false });
|
||||
}
|
||||
res.json({ success: true });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
router.get("/bot/get-autorole-vocal-config/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
|
||||
db.get(
|
||||
"SELECT enabled, role_id, exclude_channel_ids FROM autorole_vocal_config WHERE guild_id = ?",
|
||||
[guildId],
|
||||
(err, row) => {
|
||||
if (err || !row) {
|
||||
return res.json({ enabled: false, roleId: null });
|
||||
}
|
||||
res.json({
|
||||
enabled: !!row.enabled,
|
||||
roleId: row.role_id,
|
||||
excludeChannelIds: JSON.parse(row.exclude_channel_ids),
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
router.get("/bot/get-text-channels/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
const guild = client.guilds.cache.get(guildId);
|
||||
if (!guild) {
|
||||
return res.status(404).json({ error: "Serveur non trouvé" });
|
||||
}
|
||||
|
||||
const channels = guild.channels.cache
|
||||
.filter(channel => channel.isTextBased())
|
||||
.map(channel => ({
|
||||
id: channel.id,
|
||||
name: channel.name
|
||||
}));
|
||||
|
||||
res.json(channels);
|
||||
});
|
||||
|
||||
|
||||
router.get("/bot/get-voice-channels/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
const guild = client.guilds.cache.get(guildId);
|
||||
if (!guild) {
|
||||
return res.status(404).json({ error: "Serveur non trouvé" });
|
||||
}
|
||||
|
||||
const channels = guild.channels.cache
|
||||
.filter(channel => channel.isVoiceBased())
|
||||
.map(channel => ({
|
||||
id: channel.id,
|
||||
name: channel.name
|
||||
}));
|
||||
|
||||
res.json(channels);
|
||||
});
|
||||
|
||||
|
||||
router.get("/bot/get-roles/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
const guild = client.guilds.cache.get(guildId);
|
||||
if (!guild) {
|
||||
return res.status(404).json({ error: "Serveur non trouvé" });
|
||||
}
|
||||
|
||||
const botMember = guild.members.cache.get(client.user.id);
|
||||
if (!botMember) return res.status(500).json({ error: "Bot non trouvé dans ce serveur" });
|
||||
|
||||
const botRolePos = botMember.roles.highest.position;
|
||||
|
||||
// On filtre :
|
||||
// - rôle sous le plus haut rôle du bot
|
||||
// - pas @everyone
|
||||
// - pas managed (roles de bot/intégrations)
|
||||
const roles = guild.roles.cache
|
||||
.filter(role =>
|
||||
role.position < botRolePos &&
|
||||
role.name !== "@everyone" &&
|
||||
role.managed === false
|
||||
)
|
||||
.map(role => ({
|
||||
id: role.id,
|
||||
name: role.name
|
||||
}));
|
||||
|
||||
res.json(roles);
|
||||
});
|
||||
|
||||
app.use("/api", router);
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
const express = require("express");
|
||||
const fetch = require("cross-fetch");
|
||||
const router = express.Router();
|
||||
const path = require("path");
|
||||
|
||||
const CLIENT_ID = process.env.CLIENT_ID;
|
||||
const CLIENT_SECRET = process.env.CLIENT_SECRET;
|
||||
const REDIRECT_URI = process.env.REDIRECT_URI;
|
||||
|
||||
module.exports = (app, db, client) => {
|
||||
// --- Connexion Discord ---
|
||||
router.get("/discord", (req, res) => {
|
||||
const url = `https://discord.com/api/oauth2/authorize?client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&response_type=code&scope=identify%20guilds`;
|
||||
res.redirect(url);
|
||||
});
|
||||
|
||||
router.get("/discord/callback", async (req, res) => {
|
||||
const code = req.query.code;
|
||||
if (!code) return res.send("Pas de code OAuth reçu !");
|
||||
|
||||
try {
|
||||
const data = new URLSearchParams();
|
||||
data.append("client_id", CLIENT_ID);
|
||||
data.append("client_secret", CLIENT_SECRET);
|
||||
data.append("grant_type", "authorization_code");
|
||||
data.append("code", code);
|
||||
data.append("redirect_uri", REDIRECT_URI);
|
||||
data.append("scope", "identify");
|
||||
|
||||
const tokenResponse = await fetch("https://discord.com/api/oauth2/token", {
|
||||
method: "POST",
|
||||
body: data,
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
});
|
||||
|
||||
const tokenJson = await tokenResponse.json();
|
||||
const accessToken = tokenJson.access_token;
|
||||
|
||||
const userResponse = await fetch("https://discord.com/api/users/@me", {
|
||||
headers: { Authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
const user = await userResponse.json();
|
||||
|
||||
const guildsResponse = await fetch("https://discord.com/api/users/@me/guilds", {
|
||||
headers: { Authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
const guilds = await guildsResponse.json();
|
||||
|
||||
req.session.user = user;
|
||||
req.session.guilds = guilds;
|
||||
|
||||
res.redirect("/dashboard");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.send("Erreur lors de la connexion Discord !");
|
||||
}
|
||||
});
|
||||
|
||||
router.get("/logout", (req, res) => {
|
||||
req.session.destroy();
|
||||
res.redirect("/");
|
||||
});
|
||||
|
||||
app.use("/auth", router);
|
||||
};
|
||||
+3
-233
@@ -31,94 +31,9 @@ app.use(session({
|
||||
// --- Servir le dossier public ---
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
|
||||
// --- Route pour démarrer la connexion Discord ---
|
||||
app.get("/auth/discord", (req, res) => {
|
||||
const url = `https://discord.com/api/oauth2/authorize?client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&response_type=code&scope=identify%20guilds`;
|
||||
res.redirect(url);
|
||||
});
|
||||
|
||||
// --- Callback après connexion Discord ---
|
||||
app.get("/auth/discord/callback", async (req, res) => {
|
||||
const code = req.query.code;
|
||||
if (!code) return res.send("Pas de code OAuth reçu !");
|
||||
|
||||
try {
|
||||
// Échange du code contre access token
|
||||
const data = new URLSearchParams();
|
||||
data.append("client_id", CLIENT_ID);
|
||||
data.append("client_secret", CLIENT_SECRET);
|
||||
data.append("grant_type", "authorization_code");
|
||||
data.append("code", code);
|
||||
data.append("redirect_uri", REDIRECT_URI);
|
||||
data.append("scope", "identify");
|
||||
|
||||
const tokenResponse = await fetch("https://discord.com/api/oauth2/token", {
|
||||
method: "POST",
|
||||
body: data,
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
});
|
||||
|
||||
const tokenJson = await tokenResponse.json();
|
||||
const accessToken = tokenJson.access_token;
|
||||
|
||||
// Récupération des infos utilisateur
|
||||
const userResponse = await fetch("https://discord.com/api/users/@me", {
|
||||
headers: { Authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
const user = await userResponse.json();
|
||||
|
||||
// Récupérer la liste des guilds
|
||||
const guildsResponse = await fetch("https://discord.com/api/users/@me/guilds", {
|
||||
headers: { Authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
const guilds = await guildsResponse.json();
|
||||
|
||||
// Stocker l'utilisateur dans la session
|
||||
req.session.user = user;
|
||||
req.session.guilds = guilds;
|
||||
|
||||
// Rediriger vers la page HTML
|
||||
res.redirect("/dashboard");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.send("Erreur lors de la connexion Discord !");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.get("/logout", (req, res) => {
|
||||
req.session.destroy();
|
||||
res.redirect("/");
|
||||
});
|
||||
|
||||
|
||||
// --- API pour récupérer l'objet user côté front ---
|
||||
app.get("/api/user", (req, res) => {
|
||||
if (req.session.user) {
|
||||
res.json(req.session.user);
|
||||
} else {
|
||||
res.status(401).json({ error: "Utilisateur non connecté" });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
app.get("/api/guilds", (req, res) => {
|
||||
const userGuilds = req.session.guilds; // toutes les guilds de l'utilisateur
|
||||
if (!userGuilds) return res.status(401).json({ error: "Utilisateur non connecté" });
|
||||
|
||||
// Liste des guilds où le bot est présent
|
||||
const botGuildIds = client.guilds.cache.map(g => g.id);
|
||||
|
||||
// Filtrer : bot présent + admin
|
||||
const validGuilds = userGuilds.filter(g => {
|
||||
const hasAdmin = (g.permissions & 0x8) === 0x8; // flag admin
|
||||
const botHere = botGuildIds.includes(g.id);
|
||||
return hasAdmin && botHere;
|
||||
});
|
||||
|
||||
res.json(validGuilds);
|
||||
});
|
||||
|
||||
// --- Routes ---
|
||||
require("./routes/auth")(app, db, client);
|
||||
require("./routes/api")(app, db, client);
|
||||
|
||||
app.get("/invite-bot", (req, res) => {
|
||||
const permissions = 8; // Permissions administrateur
|
||||
@@ -142,7 +57,6 @@ app.get("/invite-bot", (req, res) => {
|
||||
res.json({ url });
|
||||
});
|
||||
|
||||
|
||||
// Servir le dashboard par serveur
|
||||
app.get("/guild/:guildId", (req, res) => {
|
||||
const guildId = req.params.guildId;
|
||||
@@ -159,150 +73,6 @@ app.get("/guild/:guildId", (req, res) => {
|
||||
res.sendFile(path.join(__dirname, "public", "guild.html"));
|
||||
});
|
||||
|
||||
|
||||
// API pour sauvegarder la configuration de bienvenue
|
||||
app.post("/api/bot/save-welcome-config", express.json(), (req, res) => {
|
||||
const { guildId, channelId, welcomeEnabled, welcomeMessage } = req.body;
|
||||
|
||||
if (!req.session.guilds) {
|
||||
return res.status(401).json({ success: false });
|
||||
}
|
||||
|
||||
const isAdmin = req.session.guilds.find(
|
||||
g => g.id === guildId && (BigInt(g.permissions) & 0x8n) === 0x8n
|
||||
);
|
||||
|
||||
if (!isAdmin) {
|
||||
return res.status(403).json({ success: false });
|
||||
}
|
||||
|
||||
db.run(
|
||||
`
|
||||
INSERT INTO welcome_config (guild_id, channel_id, enabled, message)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(guild_id)
|
||||
DO UPDATE SET channel_id = ?, enabled = ?, message = ?
|
||||
`,
|
||||
[
|
||||
guildId,
|
||||
channelId,
|
||||
welcomeEnabled ? 1 : 0,
|
||||
welcomeMessage,
|
||||
channelId,
|
||||
welcomeEnabled ? 1 : 0,
|
||||
welcomeMessage
|
||||
],
|
||||
err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return res.status(500).json({ success: false });
|
||||
}
|
||||
res.json({ success: true });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
app.get("/api/bot/get-welcome-config/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
|
||||
db.get(
|
||||
"SELECT enabled, channel_id, message FROM welcome_config WHERE guild_id = ?",
|
||||
[guildId],
|
||||
(err, row) => {
|
||||
if (err || !row) {
|
||||
return res.json({ enabled: false, channelId: null, message: "" });
|
||||
}
|
||||
res.json({
|
||||
enabled: !!row.enabled,
|
||||
channelId: row.channel_id,
|
||||
message: row.message
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
app.post("/api/bot/save-goodbye-config", express.json(), (req, res) => {
|
||||
const { guildId, channelId, goodbyeEnabled, goodbyeMessage } = req.body;
|
||||
|
||||
if (!req.session.guilds) {
|
||||
return res.status(401).json({ success: false });
|
||||
}
|
||||
|
||||
const isAdmin = req.session.guilds.find(
|
||||
g => g.id === guildId && (BigInt(g.permissions) & 0x8n) === 0x8n
|
||||
);
|
||||
|
||||
if (!isAdmin) {
|
||||
return res.status(403).json({ success: false });
|
||||
}
|
||||
|
||||
db.run(
|
||||
`
|
||||
INSERT INTO goodbye_config (guild_id, channel_id, enabled, message)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(guild_id)
|
||||
DO UPDATE SET channel_id = ?, enabled = ?, message = ?
|
||||
`,
|
||||
[
|
||||
guildId,
|
||||
channelId,
|
||||
goodbyeEnabled ? 1 : 0,
|
||||
goodbyeMessage,
|
||||
channelId,
|
||||
goodbyeEnabled ? 1 : 0,
|
||||
goodbyeMessage
|
||||
],
|
||||
err => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return res.status(500).json({ success: false });
|
||||
}
|
||||
res.json({ success: true });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
app.get("/api/bot/get-goodbye-config/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
|
||||
db.get(
|
||||
"SELECT enabled, channel_id, message FROM goodbye_config WHERE guild_id = ?",
|
||||
[guildId],
|
||||
(err, row) => {
|
||||
if (err || !row) {
|
||||
return res.json({ enabled: false, channelId: null, message: "" });
|
||||
}
|
||||
res.json({
|
||||
enabled: !!row.enabled,
|
||||
channelId: row.channel_id,
|
||||
message: row.message
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
app.get("/api/bot/get-text-channels/:guildId", (req, res) => {
|
||||
const { guildId } = req.params;
|
||||
const guild = client.guilds.cache.get(guildId);
|
||||
if (!guild) {
|
||||
return res.status(404).json({ error: "Serveur non trouvé" });
|
||||
}
|
||||
|
||||
const channels = guild.channels.cache
|
||||
.filter(channel => channel.isTextBased())
|
||||
.map(channel => ({
|
||||
id: channel.id,
|
||||
name: channel.name
|
||||
}));
|
||||
|
||||
res.json(channels);
|
||||
});
|
||||
|
||||
|
||||
app.get("/dashboard", (req, res) => {
|
||||
if (!req.session.user) {
|
||||
return res.redirect("/auth/discord");
|
||||
|
||||
Reference in New Issue
Block a user