mirror of
https://github.com/arthur-pbty/shadowbot.git
synced 2026-06-03 23:36:25 +02:00
clean dossier commands et correction quelque commands
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_addrole(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_add_del_role(ctx, msg, args, true).await;
|
||||
}
|
||||
|
||||
pub struct AddroleCommand;
|
||||
pub static COMMAND_DESCRIPTOR: AddroleCommand = AddroleCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for AddroleCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "addrole",
|
||||
command: "addrole",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> <@role/ID>",
|
||||
summary: "Ajoute un role",
|
||||
description: "Ajoute un role a un ou plusieurs membres.",
|
||||
examples: &["+addrole @User @Membre"],
|
||||
alias_source_key: "addrole",
|
||||
default_aliases: &["ar"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_autobackup(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_autobackup(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct AutoBackupCommand;
|
||||
pub static COMMAND_DESCRIPTOR: AutoBackupCommand = AutoBackupCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for AutoBackupCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "autobackup",
|
||||
command: "autobackup",
|
||||
category: "admin",
|
||||
params: "<serveur/emoji> <jours>",
|
||||
summary: "Configure les backups automatiques",
|
||||
description: "Definit l'intervalle en jours des backups automatiques.",
|
||||
examples: &["+autobackup serveur 3", "+autobackup emoji 7"],
|
||||
alias_source_key: "autobackup",
|
||||
default_aliases: &["abkp"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_autoconfiglog(ctx: &Context, msg: &Message) {
|
||||
logs_service::handle_autoconfiglog(ctx, msg).await;
|
||||
}
|
||||
|
||||
pub struct AutoconfiglogCommand;
|
||||
pub static COMMAND_DESCRIPTOR: AutoconfiglogCommand = AutoconfiglogCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for AutoconfiglogCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "autoconfiglog",
|
||||
command: "autoconfiglog",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Cree tous les salons de logs",
|
||||
description: "Cree automatiquement les salons de logs et les configure.",
|
||||
examples: &["+autoconfiglog"],
|
||||
alias_source_key: "autoconfiglog",
|
||||
default_aliases: &["acl"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::CreateEmbed;
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::{parse_channel_id, send_embed};
|
||||
use crate::db;
|
||||
|
||||
pub async fn handle_autopublish(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
if args.is_empty() {
|
||||
let Some(pool) = ({
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let channels = db::get_autopublish_channels(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let description = if channels.is_empty() {
|
||||
"Aucun salon d'annonces configuré.".to_string()
|
||||
} else {
|
||||
channels
|
||||
.into_iter()
|
||||
.map(|channel| format!("<#{}>", channel.channel_id))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
};
|
||||
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Autopublish")
|
||||
.description(description)
|
||||
.colour(Colour::from_rgb(100, 150, 255)),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let enabled = args[0].eq_ignore_ascii_case("on") || args[0].eq_ignore_ascii_case("enable");
|
||||
let disabled = args[0].eq_ignore_ascii_case("off") || args[0].eq_ignore_ascii_case("disable");
|
||||
if !enabled && !disabled {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Autopublish")
|
||||
.description("Utilisation: +autopublish on|off [#canal]")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(pool) = ({
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let guild_id_i64 = guild_id.get() as i64;
|
||||
let channel_id = args
|
||||
.get(1)
|
||||
.and_then(|value| parse_channel_id(value))
|
||||
.unwrap_or(msg.channel_id);
|
||||
|
||||
let result = if enabled {
|
||||
db::add_autopublish_channel(&pool, bot_id, guild_id_i64, channel_id.get() as i64).await
|
||||
} else {
|
||||
db::remove_autopublish_channel(&pool, bot_id, guild_id_i64, channel_id.get() as i64).await
|
||||
};
|
||||
|
||||
if result.is_err() {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Autopublish")
|
||||
.description("Impossible de mettre à jour le salon d'annonces.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let embed = if enabled {
|
||||
CreateEmbed::new()
|
||||
.title("Autopublish activé")
|
||||
.description(format!("Salon: <#{}>", channel_id.get()))
|
||||
.colour(Colour::from_rgb(0, 200, 120))
|
||||
.timestamp(Utc::now())
|
||||
} else {
|
||||
CreateEmbed::new()
|
||||
.title("Autopublish désactivé")
|
||||
.description(format!("Salon: <#{}>", channel_id.get()))
|
||||
.colour(Colour::from_rgb(255, 120, 0))
|
||||
.timestamp(Utc::now())
|
||||
};
|
||||
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_autoreact(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_autoreact(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct AutoReactCommand;
|
||||
pub static COMMAND_DESCRIPTOR: AutoReactCommand = AutoReactCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for AutoReactCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "autoreact",
|
||||
command: "autoreact",
|
||||
category: "admin",
|
||||
params: "<add/del> <salon> <emoji> | list",
|
||||
summary: "Configure les reactions automatiques",
|
||||
description: "Ajoute, retire et liste les reactions automatiquement appliquees aux messages d'un salon.",
|
||||
examples: &["+autoreact add #general 😀", "+autoreact list"],
|
||||
alias_source_key: "autoreact",
|
||||
default_aliases: &["ar", "reactauto"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_backup(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_backup(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct BackupCommand;
|
||||
pub static COMMAND_DESCRIPTOR: BackupCommand = BackupCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for BackupCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "backup",
|
||||
command: "backup",
|
||||
category: "admin",
|
||||
params: "<serveur/emoji> <nom> | list/delete/load",
|
||||
summary: "Gere les backups serveur et emojis",
|
||||
description: "Cree, liste, supprime et recharge des backups serveur ou emojis.",
|
||||
examples: &[
|
||||
"+backup serveur prod_1",
|
||||
"+backup list serveur",
|
||||
"+backup load emoji nightly",
|
||||
],
|
||||
alias_source_key: "backup",
|
||||
default_aliases: &["bkp"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_ban(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_ban(ctx, msg, args, false).await;
|
||||
}
|
||||
pub struct BanCommand;
|
||||
pub static COMMAND_DESCRIPTOR: BanCommand = BanCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for BanCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "ban",
|
||||
command: "ban",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> [raison]",
|
||||
summary: "Bannit un membre",
|
||||
description: "Ban un ou plusieurs membres.",
|
||||
examples: &["+ban @User"],
|
||||
alias_source_key: "ban",
|
||||
default_aliases: &["b"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_banlist(ctx: &Context, msg: &Message) {
|
||||
moderation_tools::handle_banlist(ctx, msg).await;
|
||||
}
|
||||
pub struct BanlistCommand;
|
||||
pub static COMMAND_DESCRIPTOR: BanlistCommand = BanlistCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for BanlistCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "banlist",
|
||||
command: "banlist",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Liste les bans",
|
||||
description: "Affiche la liste des bannissements en cours.",
|
||||
examples: &["+banlist"],
|
||||
alias_source_key: "banlist",
|
||||
default_aliases: &["bls"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::{ban_user_everywhere, ensure_owner, parse_user_id};
|
||||
use crate::commands::common::{add_list_fields, send_embed, theme_color, truncate_text};
|
||||
use crate::db::{DbPoolKey, add_to_blacklist, list_blacklist};
|
||||
|
||||
pub async fn handle_bl(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
if ensure_owner(ctx, msg).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
let bot_id = ctx.cache.current_user().id;
|
||||
let pool = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<DbPoolKey>().cloned()
|
||||
};
|
||||
|
||||
let Some(pool) = pool else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("DB indisponible.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
if args.is_empty() {
|
||||
let rows = list_blacklist(&pool, bot_id).await.unwrap_or_default();
|
||||
let lines = rows
|
||||
.iter()
|
||||
.map(|r| format!("<@{}> · {}", r.user_id, truncate_text(&r.reason, 80)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let color = theme_color(ctx).await;
|
||||
let mut embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Blacklist")
|
||||
.color(color);
|
||||
embed = add_list_fields(embed, &lines, "Membres blacklistés");
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(target) = parse_user_id(args[0]) else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Membre invalide.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let reason = if args.len() > 1 {
|
||||
args[1..].join(" ")
|
||||
} else {
|
||||
"Aucune raison fournie".to_string()
|
||||
};
|
||||
|
||||
let _ = add_to_blacklist(&pool, bot_id, target, &reason, Some(msg.author.id)).await;
|
||||
let (ok, ko) = ban_user_everywhere(ctx, target, &format!("Blacklist: {}", reason)).await;
|
||||
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Blacklist mise à jour")
|
||||
.description(format!("<@{}> a été blacklisté.", target.get()))
|
||||
.field("Raison", truncate_text(&reason, 1024), false)
|
||||
.field(
|
||||
"Bans appliqués",
|
||||
format!("{} réussis · {} échecs", ok, ko),
|
||||
false,
|
||||
)
|
||||
.color(0x57F287);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
|
||||
pub struct BlCommand;
|
||||
pub static COMMAND_DESCRIPTOR: BlCommand = BlCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for BlCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "bl",
|
||||
command: "bl",
|
||||
category: "admin",
|
||||
params: "[<@membre/ID> [raison...]]",
|
||||
summary: "Gere la blacklist globale",
|
||||
description: "Affiche la blacklist ou ajoute un utilisateur a la blacklist globale du bot.",
|
||||
examples: &["+bl", "+help bl"],
|
||||
alias_source_key: "bl",
|
||||
default_aliases: &["bls"],
|
||||
default_permission: 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::{ensure_owner, parse_user_id};
|
||||
use crate::commands::common::{send_embed, truncate_text};
|
||||
use crate::db::{DbPoolKey, get_blacklist_info};
|
||||
|
||||
pub async fn handle_blinfo(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
if ensure_owner(ctx, msg).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
if args.is_empty() {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Usage: `+blinfo <@membre/ID>`")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(target) = parse_user_id(args[0]) else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Membre invalide.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id;
|
||||
let pool = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<DbPoolKey>().cloned()
|
||||
};
|
||||
|
||||
let Some(pool) = pool else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("DB indisponible.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let info = get_blacklist_info(&pool, bot_id, target)
|
||||
.await
|
||||
.ok()
|
||||
.flatten();
|
||||
let Some(info) = info else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Blacklist")
|
||||
.description("Ce membre n'est pas blacklisté.")
|
||||
.color(0xFF0000);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let added_at = crate::commands::common::discord_ts(
|
||||
Timestamp::from_unix_timestamp(info.added_at.timestamp())
|
||||
.unwrap_or_else(|_| Timestamp::now()),
|
||||
"F",
|
||||
);
|
||||
|
||||
let by = info
|
||||
.added_by
|
||||
.map(|id| format!("<@{}>", id))
|
||||
.unwrap_or_else(|| "Inconnu".to_string());
|
||||
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Informations blacklist")
|
||||
.field("Membre", format!("<@{}>", info.user_id), true)
|
||||
.field("Ajouté par", by, true)
|
||||
.field("Ajouté le", added_at, true)
|
||||
.field("Raison", truncate_text(&info.reason, 1024), false)
|
||||
.color(0xFF0000);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
|
||||
pub struct BlinfoCommand;
|
||||
pub static COMMAND_DESCRIPTOR: BlinfoCommand = BlinfoCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for BlinfoCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "blinfo",
|
||||
command: "blinfo",
|
||||
category: "admin",
|
||||
params: "<@membre/ID>",
|
||||
summary: "Affiche les details blacklist",
|
||||
description: "Affiche les details de blacklist pour un utilisateur donne.",
|
||||
examples: &["+blinfo", "+bo", "+help blinfo"],
|
||||
alias_source_key: "blinfo",
|
||||
default_aliases: &["bli"],
|
||||
default_permission: 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_boostembed(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_boostembed(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct BoostembedCommand;
|
||||
pub static COMMAND_DESCRIPTOR: BoostembedCommand = BoostembedCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for BoostembedCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "boostembed",
|
||||
command: "boostembed",
|
||||
category: "admin",
|
||||
params: "<on|off|test>",
|
||||
summary: "Active, coupe ou teste l embed boost",
|
||||
description: "Controle l embed de boost et permet un test rapide.",
|
||||
examples: &["+boostembed on", "+boostembed test"],
|
||||
alias_source_key: "boostembed",
|
||||
default_aliases: &["bembed"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_boostlog(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_log_toggle(ctx, msg, args, "boost", "BoostLog").await;
|
||||
}
|
||||
|
||||
pub struct BoostlogCommand;
|
||||
pub static COMMAND_DESCRIPTOR: BoostlogCommand = BoostlogCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for BoostlogCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "boostlog",
|
||||
command: "boostlog",
|
||||
category: "admin",
|
||||
params: "<on [salon]|off>",
|
||||
summary: "Active les logs de boosts",
|
||||
description: "Active ou desactive les logs de boosts.",
|
||||
examples: &["+boostlog on #logs", "+boostlog off"],
|
||||
alias_source_key: "boostlog",
|
||||
default_aliases: &["blog"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_bringall(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_bringall(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct BringAllCommand;
|
||||
pub static COMMAND_DESCRIPTOR: BringAllCommand = BringAllCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for BringAllCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "bringall",
|
||||
command: "bringall",
|
||||
category: "admin",
|
||||
params: "[salon_vocal_destination]",
|
||||
summary: "Rassemble tous les vocaux",
|
||||
description: "Deplace tous les membres actuellement en vocal vers un salon cible.",
|
||||
examples: &["+bringall #Event", "+bringall"],
|
||||
alias_source_key: "bringall",
|
||||
default_aliases: &["ball", "vbring"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_button(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_button(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct ButtonCommand;
|
||||
pub static COMMAND_DESCRIPTOR: ButtonCommand = ButtonCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for ButtonCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "button",
|
||||
command: "button",
|
||||
category: "admin",
|
||||
params: "<add/del> <lien>",
|
||||
summary: "Gere des boutons decoratifs",
|
||||
description: "Ajoute ou supprime un bouton de decoration personnalise sur un message du bot.",
|
||||
examples: &[
|
||||
"+button add https://example.com",
|
||||
"+button del https://example.com",
|
||||
],
|
||||
alias_source_key: "button",
|
||||
default_aliases: &["btn"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::CreateEmbed;
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db;
|
||||
|
||||
pub async fn handle_claim(ctx: &Context, msg: &Message, _args: &[&str]) {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(pool) = ({
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let guild_id_i64 = guild_id.get() as i64;
|
||||
let channel_id = msg.channel_id.get() as i64;
|
||||
|
||||
let Some(ticket) = db::get_ticket_by_channel(&pool, bot_id, guild_id_i64, channel_id)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
else {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Ce salon n'est pas reconnu comme un ticket.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
};
|
||||
|
||||
if db::claim_ticket(&pool, ticket.id, msg.author.id.get() as i64)
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Impossible de revendiquer ce ticket.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Ticket revendiqué")
|
||||
.description(format!("Le ticket #{} a été revendiqué.", ticket.id))
|
||||
.colour(Colour::from_rgb(0, 200, 120))
|
||||
.timestamp(Utc::now()),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_cleanup(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_cleanup(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct CleanupCommand;
|
||||
pub static COMMAND_DESCRIPTOR: CleanupCommand = CleanupCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for CleanupCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "cleanup",
|
||||
command: "cleanup",
|
||||
category: "admin",
|
||||
params: "<salon_vocal>",
|
||||
summary: "Vide un salon vocal",
|
||||
description: "Deconnecte tous les utilisateurs presents dans un salon vocal cible.",
|
||||
examples: &["+cleanup #General"],
|
||||
alias_source_key: "cleanup",
|
||||
default_aliases: &["vclean", "vcleanup"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::moderation_tools;
|
||||
|
||||
pub async fn handle_clear_all_sanctions(ctx: &Context, msg: &Message) {
|
||||
moderation_tools::handle_clear_all_sanctions(ctx, msg).await;
|
||||
}
|
||||
|
||||
pub struct ClearAllSanctionsCommand;
|
||||
pub static COMMAND_DESCRIPTOR: ClearAllSanctionsCommand = ClearAllSanctionsCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for ClearAllSanctionsCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "clear_all_sanctions",
|
||||
command: "clear all sanctions",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Supprime toutes les sanctions du serveur",
|
||||
description: "Efface toutes les sanctions de tous les membres du serveur.",
|
||||
examples: &["+clear all sanctions"],
|
||||
alias_source_key: "clear_all_sanctions",
|
||||
default_aliases: &["casanctions"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::ensure_owner;
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db::{DbPoolKey, clear_blacklist};
|
||||
|
||||
pub async fn handle_clear_bl(ctx: &Context, msg: &Message) {
|
||||
if ensure_owner(ctx, msg).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
let bot_id = ctx.cache.current_user().id;
|
||||
let pool = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<DbPoolKey>().cloned()
|
||||
};
|
||||
|
||||
let Some(pool) = pool else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("DB indisponible.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let count = clear_blacklist(&pool, bot_id).await.unwrap_or(0);
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Blacklist réinitialisée")
|
||||
.description(format!("{} membre(s) retiré(s) de la blacklist.", count))
|
||||
.color(0x57F287);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
|
||||
pub struct ClearBlCommand;
|
||||
pub static COMMAND_DESCRIPTOR: ClearBlCommand = ClearBlCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for ClearBlCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "clear_bl",
|
||||
command: "clear bl",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Vide la blacklist globale",
|
||||
description: "Supprime toutes les entrees de la blacklist globale.",
|
||||
examples: &["+clear bl", "+cl", "+help clear bl"],
|
||||
alias_source_key: "clear_bl",
|
||||
default_aliases: &["cbl"],
|
||||
default_permission: 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::moderation_tools;
|
||||
|
||||
pub async fn handle_clear_messages(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_clear_messages(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct ClearMessagesCommand;
|
||||
pub static COMMAND_DESCRIPTOR: ClearMessagesCommand = ClearMessagesCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for ClearMessagesCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "clear_messages",
|
||||
command: "clear",
|
||||
category: "admin",
|
||||
params: "<nombre> [@membre/ID]",
|
||||
summary: "Supprime des messages dans le salon",
|
||||
description: "Supprime un nombre de messages, optionnellement filtres par membre.",
|
||||
examples: &["+clear 20", "+clear 20 @User"],
|
||||
alias_source_key: "clear_messages",
|
||||
default_aliases: &["purge"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::ensure_owner;
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db::{DbPoolKey, clear_bot_owners};
|
||||
|
||||
pub async fn handle_clear_owners(ctx: &Context, msg: &Message) {
|
||||
if ensure_owner(ctx, msg).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
let bot_id = ctx.cache.current_user().id;
|
||||
let pool = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<DbPoolKey>().cloned()
|
||||
};
|
||||
|
||||
let Some(pool) = pool else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("DB indisponible.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let count = clear_bot_owners(&pool, bot_id).await.unwrap_or(0);
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Owners réinitialisés")
|
||||
.description(format!("{} owner(s) supprimé(s).", count))
|
||||
.color(0x57F287);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
|
||||
pub struct ClearOwnersCommand;
|
||||
pub static COMMAND_DESCRIPTOR: ClearOwnersCommand = ClearOwnersCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for ClearOwnersCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "clear_owners",
|
||||
command: "clear owners",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Vide la liste des owners",
|
||||
description: "Supprime tous les owners supplementaires en base de donnees.",
|
||||
examples: &["+clear owners", "+cs", "+help clear owners"],
|
||||
alias_source_key: "clear_owners",
|
||||
default_aliases: &["cro"],
|
||||
default_permission: 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::moderation_tools;
|
||||
|
||||
pub async fn handle_clear_sanctions(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_clear_sanctions(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct ClearSanctionsCommand;
|
||||
pub static COMMAND_DESCRIPTOR: ClearSanctionsCommand = ClearSanctionsCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for ClearSanctionsCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "clear_sanctions",
|
||||
command: "clear sanctions",
|
||||
category: "admin",
|
||||
params: "<@membre/ID>",
|
||||
summary: "Supprime toutes les sanctions d un membre",
|
||||
description: "Efface completement les sanctions d un membre cible.",
|
||||
examples: &["+clear sanctions @User"],
|
||||
alias_source_key: "clear_sanctions",
|
||||
default_aliases: &["csanctions"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::CreateEmbed;
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db;
|
||||
|
||||
pub async fn handle_close(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let reason = if args.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(args.join(" "))
|
||||
};
|
||||
|
||||
let Some(pool) = ({
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let guild_id_i64 = guild_id.get() as i64;
|
||||
let channel_id = msg.channel_id.get() as i64;
|
||||
|
||||
let Some(ticket) = db::get_ticket_by_channel(&pool, bot_id, guild_id_i64, channel_id)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
else {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Ce salon n'est pas reconnu comme un ticket.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
};
|
||||
|
||||
if db::close_ticket(&pool, ticket.id, reason.clone())
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Impossible de fermer ce ticket.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let mut embed = CreateEmbed::new()
|
||||
.title("Ticket fermé")
|
||||
.description(format!("Le ticket #{} a été fermé.", ticket.id))
|
||||
.colour(Colour::from_rgb(255, 120, 0))
|
||||
.timestamp(Utc::now());
|
||||
|
||||
if let Some(reason) = reason {
|
||||
embed = embed.field("Raison", reason, false);
|
||||
}
|
||||
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_cmute(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_cmute(ctx, msg, args, false).await;
|
||||
}
|
||||
pub struct CmuteCommand;
|
||||
pub static COMMAND_DESCRIPTOR: CmuteCommand = CmuteCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for CmuteCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "cmute",
|
||||
command: "cmute",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> [raison]",
|
||||
summary: "Mute salon",
|
||||
description: "Mute un membre sur le salon courant.",
|
||||
examples: &["+cmute @User"],
|
||||
alias_source_key: "cmute",
|
||||
default_aliases: &["cm"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_create(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_create(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct CreateCommand;
|
||||
pub static COMMAND_DESCRIPTOR: CreateCommand = CreateCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for CreateCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "create",
|
||||
command: "create",
|
||||
category: "admin",
|
||||
params: "[emoji/url] [nom]",
|
||||
summary: "Cree un emoji custom",
|
||||
description: "Cree un emoji custom a partir d'une image, d'un lien ou d'un emoji nitro.",
|
||||
examples: &[
|
||||
"+create <:blob:123456789012345678> blobcopy",
|
||||
"+create https://... logo",
|
||||
],
|
||||
alias_source_key: "create",
|
||||
default_aliases: &["mkemoji", "ce"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::moderation_tools;
|
||||
|
||||
pub async fn handle_del_sanction(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_del_sanction(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct DelSanctionCommand;
|
||||
pub static COMMAND_DESCRIPTOR: DelSanctionCommand = DelSanctionCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for DelSanctionCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "del_sanction",
|
||||
command: "del sanction",
|
||||
category: "admin",
|
||||
params: "<@membre/ID> <nombre>",
|
||||
summary: "Supprime une sanction d un membre",
|
||||
description: "Supprime une sanction specifique dans l historique d un membre.",
|
||||
examples: &["+del sanction @User 1"],
|
||||
alias_source_key: "del_sanction",
|
||||
default_aliases: &["delsanction"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_delrole(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_add_del_role(ctx, msg, args, false).await;
|
||||
}
|
||||
|
||||
pub struct DelroleCommand;
|
||||
pub static COMMAND_DESCRIPTOR: DelroleCommand = DelroleCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for DelroleCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "delrole",
|
||||
command: "delrole",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> <@role/ID>",
|
||||
summary: "Retire un role",
|
||||
description: "Retire un role a un ou plusieurs membres.",
|
||||
examples: &["+delrole @User @Membre"],
|
||||
alias_source_key: "delrole",
|
||||
default_aliases: &["dr"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_derank(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_derank(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct DerankCommand;
|
||||
pub static COMMAND_DESCRIPTOR: DerankCommand = DerankCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for DerankCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "derank",
|
||||
command: "derank",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]>",
|
||||
summary: "Retire tous les roles",
|
||||
description: "Retire tous les roles gerables d un membre.",
|
||||
examples: &["+derank @User"],
|
||||
alias_source_key: "derank",
|
||||
default_aliases: &["drk"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_embed(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_embed_builder(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct EmbedCommand;
|
||||
pub static COMMAND_DESCRIPTOR: EmbedCommand = EmbedCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for EmbedCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "embed",
|
||||
command: "embed",
|
||||
category: "admin",
|
||||
params: "title | description (v1)",
|
||||
summary: "Ouvre le generateur d'embed",
|
||||
description: "Affiche un generateur d'embed interactif version rapide.",
|
||||
examples: &["+embed"],
|
||||
alias_source_key: "embed",
|
||||
default_aliases: &["emb"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_end(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_end(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct EndCommand;
|
||||
pub static COMMAND_DESCRIPTOR: EndCommand = EndCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for EndCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "end",
|
||||
command: "end",
|
||||
category: "admin",
|
||||
params: "giveaway <id_message>",
|
||||
summary: "Termine un giveaway par ID",
|
||||
description: "Permet de stopper instantanement un giveaway avec l'identifiant du message.",
|
||||
examples: &["+end giveaway 123456789012345678"],
|
||||
alias_source_key: "end",
|
||||
default_aliases: &["gend"],
|
||||
default_permission: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_giveaway(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_giveaway(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct GiveawayCommand;
|
||||
pub static COMMAND_DESCRIPTOR: GiveawayCommand = GiveawayCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for GiveawayCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "giveaway",
|
||||
command: "giveaway",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Ouvre un menu de creation de giveaway",
|
||||
description: "Affiche une interface rapide pour initier un giveaway depuis le salon courant.",
|
||||
examples: &["+giveaway"],
|
||||
alias_source_key: "giveaway",
|
||||
default_aliases: &["gstart", "gw"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_hide(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_hide_unhide(ctx, msg, args, true).await;
|
||||
}
|
||||
pub struct HideCommand;
|
||||
pub static COMMAND_DESCRIPTOR: HideCommand = HideCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for HideCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "hide",
|
||||
command: "hide",
|
||||
category: "admin",
|
||||
params: "[salon]",
|
||||
summary: "Cache un salon",
|
||||
description: "Retire la visibilite d un salon.",
|
||||
examples: &["+hide", "+hide #general"],
|
||||
alias_source_key: "hide",
|
||||
default_aliases: &["hd"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_hideall(ctx: &Context, msg: &Message) {
|
||||
moderation_tools::handle_hideall_unhideall(ctx, msg, true).await;
|
||||
}
|
||||
|
||||
pub struct HideallCommand;
|
||||
pub static COMMAND_DESCRIPTOR: HideallCommand = HideallCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for HideallCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "hideall",
|
||||
command: "hideall",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Cache tous les salons",
|
||||
description: "Retire la visibilite de tous les salons.",
|
||||
examples: &["+hideall"],
|
||||
alias_source_key: "hideall",
|
||||
default_aliases: &["hda"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
use serenity::builder::CreateEmbed;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::commands::server::resolve_guild_target;
|
||||
|
||||
pub async fn handle_invite(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
if args.is_empty() {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Usage: `+invite <ID/nombre>`")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(guild_id) = resolve_guild_target(ctx, args[0]).await else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Serveur introuvable.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let Ok(channels) = guild_id.channels(&ctx.http).await else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Impossible de lire les salons.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let mut invite_url = None;
|
||||
for channel in channels.values() {
|
||||
if matches!(channel.kind, ChannelType::Text | ChannelType::News) {
|
||||
if let Ok(invite) = channel
|
||||
.create_invite(
|
||||
&ctx.http,
|
||||
serenity::builder::CreateInvite::new().max_age(3600),
|
||||
)
|
||||
.await
|
||||
{
|
||||
invite_url = Some(invite.url());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(url) = invite_url else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Aucun salon éligible pour créer une invitation.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Invitation créée")
|
||||
.description(url)
|
||||
.color(0x57F287);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
pub struct InviteCommand;
|
||||
pub static COMMAND_DESCRIPTOR: InviteCommand = InviteCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for InviteCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "invite",
|
||||
command: "invite",
|
||||
category: "admin",
|
||||
params: "<ID_serveur/index>",
|
||||
summary: "Cree une invitation serveur",
|
||||
description: "Cree une invitation temporaire sur un serveur cible accessible par le bot.",
|
||||
examples: &["+invite", "+ie", "+help invite"],
|
||||
alias_source_key: "invite",
|
||||
default_aliases: &["ivt"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_join(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_join_leave_settings(ctx, msg, args, "join").await;
|
||||
}
|
||||
|
||||
pub struct JoinCommand;
|
||||
pub static COMMAND_DESCRIPTOR: JoinCommand = JoinCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for JoinCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "join",
|
||||
command: "join",
|
||||
category: "admin",
|
||||
params: "settings [on/off] [salon] [message]",
|
||||
summary: "Parametre les actions de join",
|
||||
description: "Permet de configurer les actions quand un membre rejoint.",
|
||||
examples: &[
|
||||
"+join settings",
|
||||
"+join settings on #welcome Bienvenue {user}",
|
||||
],
|
||||
alias_source_key: "join",
|
||||
default_aliases: &["jset"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_kick(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_kick(ctx, msg, args).await;
|
||||
}
|
||||
pub struct KickCommand;
|
||||
pub static COMMAND_DESCRIPTOR: KickCommand = KickCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for KickCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "kick",
|
||||
command: "kick",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> [raison]",
|
||||
summary: "Expulse un membre",
|
||||
description: "Kick un ou plusieurs membres.",
|
||||
examples: &["+kick @User"],
|
||||
alias_source_key: "kick",
|
||||
default_aliases: &["k"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
use serenity::builder::CreateEmbed;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::commands::server::resolve_guild_target;
|
||||
|
||||
pub async fn handle_leave(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
let target = if args.is_empty() {
|
||||
msg.guild_id
|
||||
} else {
|
||||
resolve_guild_target(ctx, args[0]).await
|
||||
};
|
||||
|
||||
let Some(guild_id) = target else {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Serveur introuvable.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let _ = guild_id.leave(&ctx.http).await;
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Serveur quitté")
|
||||
.description(format!("Le bot a quitté `{}`.", guild_id.get()))
|
||||
.color(0x57F287);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
pub struct LeaveCommand;
|
||||
pub static COMMAND_DESCRIPTOR: LeaveCommand = LeaveCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for LeaveCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "leave",
|
||||
command: "leave",
|
||||
category: "admin",
|
||||
params: "[ID_serveur/index]",
|
||||
summary: "Fait quitter un serveur",
|
||||
description: "Force le bot a quitter un serveur cible ou le serveur courant.",
|
||||
examples: &["+leave", "+le", "+help leave"],
|
||||
alias_source_key: "leave",
|
||||
default_aliases: &["lvg"],
|
||||
default_permission: 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::logs_service;
|
||||
|
||||
pub async fn handle_leave_settings(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_join_leave_settings(ctx, msg, args, "leave").await;
|
||||
}
|
||||
|
||||
pub struct LeaveSettingsCommand;
|
||||
pub static COMMAND_DESCRIPTOR: LeaveSettingsCommand = LeaveSettingsCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for LeaveSettingsCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "leave_settings",
|
||||
command: "leave settings",
|
||||
category: "admin",
|
||||
params: "settings [on/off] [salon] [message]",
|
||||
summary: "Parametre les actions de leave",
|
||||
description: "Configure les actions a executer quand un membre quitte le serveur.",
|
||||
examples: &[
|
||||
"+leave settings",
|
||||
"+leave settings on #logs {user} a quitte",
|
||||
],
|
||||
alias_source_key: "leave_settings",
|
||||
default_aliases: &["lset"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_lock(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_lock_unlock(ctx, msg, args, true).await;
|
||||
}
|
||||
pub struct LockCommand;
|
||||
pub static COMMAND_DESCRIPTOR: LockCommand = LockCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for LockCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "lock",
|
||||
command: "lock",
|
||||
category: "admin",
|
||||
params: "[salon]",
|
||||
summary: "Ferme un salon",
|
||||
description: "Verrouille un salon texte ou vocal.",
|
||||
examples: &["+lock", "+lock #general"],
|
||||
alias_source_key: "lock",
|
||||
default_aliases: &["lk"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_lockall(ctx: &Context, msg: &Message) {
|
||||
moderation_tools::handle_lockall_unlockall(ctx, msg, true).await;
|
||||
}
|
||||
pub struct LockallCommand;
|
||||
pub static COMMAND_DESCRIPTOR: LockallCommand = LockallCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for LockallCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "lockall",
|
||||
command: "lockall",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Ferme tous les salons",
|
||||
description: "Verrouille tous les salons du serveur.",
|
||||
examples: &["+lockall"],
|
||||
alias_source_key: "lockall",
|
||||
default_aliases: &["lka"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_massiverole(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_massive_role(ctx, msg, args, true).await;
|
||||
}
|
||||
|
||||
pub struct MassiveRoleCommand;
|
||||
pub static COMMAND_DESCRIPTOR: MassiveRoleCommand = MassiveRoleCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for MassiveRoleCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "massiverole",
|
||||
command: "massiverole",
|
||||
category: "admin",
|
||||
params: "<role_cible> [role_filtre]",
|
||||
summary: "Ajoute un role en masse",
|
||||
description: "Ajoute un role a tous les membres ou a ceux qui ont deja un role filtre.",
|
||||
examples: &["+massiverole @VIP", "+massiverole @VIP @Membres"],
|
||||
alias_source_key: "massiverole",
|
||||
default_aliases: &["mrole", "mr"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_messagelog(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_log_toggle(ctx, msg, args, "message", "MessageLog").await;
|
||||
}
|
||||
|
||||
pub struct MessagelogCommand;
|
||||
pub static COMMAND_DESCRIPTOR: MessagelogCommand = MessagelogCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for MessagelogCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "messagelog",
|
||||
command: "messagelog",
|
||||
category: "admin",
|
||||
params: "<on [salon]|off>",
|
||||
summary: "Active les logs de messages",
|
||||
description: "Active ou desactive les logs des messages supprimes et edites.",
|
||||
examples: &["+messagelog on #logs", "+messagelog off"],
|
||||
alias_source_key: "messagelog",
|
||||
default_aliases: &["msglog"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_modlog(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_log_toggle(ctx, msg, args, "moderation", "ModLog").await;
|
||||
}
|
||||
|
||||
pub struct ModlogCommand;
|
||||
pub static COMMAND_DESCRIPTOR: ModlogCommand = ModlogCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for ModlogCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "modlog",
|
||||
command: "modlog",
|
||||
category: "admin",
|
||||
params: "<on [salon]|off>",
|
||||
summary: "Active les logs de moderation",
|
||||
description: "Active ou desactive les logs de moderation dans un salon cible.",
|
||||
examples: &["+modlog on #logs", "+modlog off"],
|
||||
alias_source_key: "modlog",
|
||||
default_aliases: &["mlog"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_mute(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_mute(ctx, msg, args, false).await;
|
||||
}
|
||||
pub struct MuteCommand;
|
||||
pub static COMMAND_DESCRIPTOR: MuteCommand = MuteCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for MuteCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "mute",
|
||||
command: "mute",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> [raison]",
|
||||
summary: "Mute un membre",
|
||||
description: "Applique un mute a un ou plusieurs membres.",
|
||||
examples: &["+mute @User abus"],
|
||||
alias_source_key: "mute",
|
||||
default_aliases: &["tmute"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_mutelist(ctx: &Context, msg: &Message) {
|
||||
moderation_tools::handle_mutelist(ctx, msg).await;
|
||||
}
|
||||
pub struct MutelistCommand;
|
||||
pub static COMMAND_DESCRIPTOR: MutelistCommand = MutelistCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for MutelistCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "mutelist",
|
||||
command: "mutelist",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Liste les mutes",
|
||||
description: "Affiche tous les mutes en cours.",
|
||||
examples: &["+mutelist"],
|
||||
alias_source_key: "mutelist",
|
||||
default_aliases: &["ml"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_newsticker(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_new_sticker(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct NewStickerCommand;
|
||||
pub static COMMAND_DESCRIPTOR: NewStickerCommand = NewStickerCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for NewStickerCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "newsticker",
|
||||
command: "newsticker",
|
||||
category: "admin",
|
||||
params: "[nom]",
|
||||
summary: "Cree un sticker serveur",
|
||||
description: "Cree un nouveau sticker a partir d'un sticker ou fichier repondu.",
|
||||
examples: &["+newsticker cool_pack"],
|
||||
alias_source_key: "newsticker",
|
||||
default_aliases: &["stcreate", "nst"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_nolog(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_nolog(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct NologCommand;
|
||||
pub static COMMAND_DESCRIPTOR: NologCommand = NologCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for NologCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "nolog",
|
||||
command: "nolog",
|
||||
category: "admin",
|
||||
params: "<add/del> [salon] [message|voice|all]",
|
||||
summary: "Exclut des salons des logs",
|
||||
description: "Desactive ou reactive les logs message/voice pour certains salons.",
|
||||
examples: &["+nolog add #secret all", "+nolog del #secret message"],
|
||||
alias_source_key: "nolog",
|
||||
default_aliases: &["nlg"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::{app_owner_id, ensure_owner};
|
||||
use crate::commands::common::{add_list_fields, send_embed, theme_color};
|
||||
use crate::db::{DbPoolKey, list_bot_owners};
|
||||
|
||||
pub async fn handle_owner(ctx: &Context, msg: &Message, _args: &[&str]) {
|
||||
if ensure_owner(ctx, msg).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
let bot_id = ctx.cache.current_user().id;
|
||||
let pool = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<DbPoolKey>().cloned()
|
||||
};
|
||||
|
||||
let mut lines: Vec<String> = Vec::new();
|
||||
|
||||
if let Some(app_owner) = app_owner_id(ctx).await {
|
||||
lines.push(format!("<@{}> (owner application)", app_owner.get()));
|
||||
}
|
||||
|
||||
if let Some(pool) = pool {
|
||||
if let Ok(extra) = list_bot_owners(&pool, bot_id).await {
|
||||
for uid in extra {
|
||||
lines.push(format!("<@{}>", uid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let color = theme_color(ctx).await;
|
||||
let mut embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Owners du bot")
|
||||
.color(color);
|
||||
embed = add_list_fields(embed, &lines, "Owners");
|
||||
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
|
||||
pub struct OwnerCommand;
|
||||
pub static COMMAND_DESCRIPTOR: OwnerCommand = OwnerCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for OwnerCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "owner",
|
||||
command: "owner",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Liste les owners du bot",
|
||||
description: "Affiche l owner application et les owners ajoutes en base.",
|
||||
examples: &["+owner", "+or", "+help owner"],
|
||||
alias_source_key: "owner",
|
||||
default_aliases: &["own"],
|
||||
default_permission: 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_raidlog(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_raidlog(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct RaidlogCommand;
|
||||
pub static COMMAND_DESCRIPTOR: RaidlogCommand = RaidlogCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for RaidlogCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "raidlog",
|
||||
command: "raidlog",
|
||||
category: "admin",
|
||||
params: "[salon]|off",
|
||||
summary: "Active les logs antiraid",
|
||||
description: "Active les logs antiraid dans un salon ou les desactive.",
|
||||
examples: &["+raidlog #logs", "+raidlog off"],
|
||||
alias_source_key: "raidlog",
|
||||
default_aliases: &["rdlog"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::CreateEmbed;
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db;
|
||||
|
||||
fn sanitize_ticket_name(input: &str) -> String {
|
||||
let mut out = String::new();
|
||||
let mut previous_dash = false;
|
||||
|
||||
for ch in input.to_lowercase().chars() {
|
||||
let keep = ch.is_ascii_alphanumeric();
|
||||
let dash = ch.is_whitespace() || ch == '-' || ch == '_';
|
||||
|
||||
if keep {
|
||||
out.push(ch);
|
||||
previous_dash = false;
|
||||
} else if dash && !previous_dash {
|
||||
out.push('-');
|
||||
previous_dash = true;
|
||||
}
|
||||
}
|
||||
|
||||
out.trim_matches('-').to_string()
|
||||
}
|
||||
|
||||
pub async fn handle_rename(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let new_name_raw = args.join(" ").trim().to_string();
|
||||
if new_name_raw.is_empty() {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Utilisation: +rename <nom>")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let new_name = sanitize_ticket_name(&new_name_raw);
|
||||
if new_name.is_empty() {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Nom invalide.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(pool) = ({
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let guild_id_i64 = guild_id.get() as i64;
|
||||
let channel_id = msg.channel_id.get() as i64;
|
||||
|
||||
let Some(ticket) = db::get_ticket_by_channel(&pool, bot_id, guild_id_i64, channel_id)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
else {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Ce salon n'est pas reconnu comme un ticket.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
};
|
||||
|
||||
if msg
|
||||
.channel_id
|
||||
.edit(&ctx.http, serenity::builder::EditChannel::new().name(new_name.clone()))
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Impossible de renommer le salon.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let _ = db::update_ticket_title(&pool, ticket.id, &new_name).await;
|
||||
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Ticket renommé")
|
||||
.description(format!("Nouveau nom: `{}`", new_name))
|
||||
.colour(Colour::from_rgb(0, 200, 120))
|
||||
.timestamp(Utc::now()),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_renew(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_renew(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct RenewCommand;
|
||||
pub static COMMAND_DESCRIPTOR: RenewCommand = RenewCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for RenewCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "renew",
|
||||
command: "renew",
|
||||
category: "admin",
|
||||
params: "[salon]",
|
||||
summary: "Recree un salon textuel",
|
||||
description: "Supprime puis recree un salon textuel en conservant les options principales.",
|
||||
examples: &["+renew", "+renew #general"],
|
||||
alias_source_key: "renew",
|
||||
default_aliases: &["nuke", "rebuildch"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_reroll(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_reroll(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct RerollCommand;
|
||||
pub static COMMAND_DESCRIPTOR: RerollCommand = RerollCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for RerollCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "reroll",
|
||||
command: "reroll",
|
||||
category: "admin",
|
||||
params: "aucun (en reponse a un message)",
|
||||
summary: "Relance un tirage giveaway",
|
||||
description: "Choisit un nouveau gagnant depuis le message cible.",
|
||||
examples: &["+reroll"],
|
||||
alias_source_key: "reroll",
|
||||
default_aliases: &["rro", "greroll"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_rolelog(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_log_toggle(ctx, msg, args, "role", "RoleLog").await;
|
||||
}
|
||||
|
||||
pub struct RolelogCommand;
|
||||
pub static COMMAND_DESCRIPTOR: RolelogCommand = RolelogCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for RolelogCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "rolelog",
|
||||
command: "rolelog",
|
||||
category: "admin",
|
||||
params: "<on [salon]|off>",
|
||||
summary: "Active les logs de roles",
|
||||
description: "Active ou desactive les logs des roles.",
|
||||
examples: &["+rolelog on #logs", "+rolelog off"],
|
||||
alias_source_key: "rolelog",
|
||||
default_aliases: &["rlog"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::moderation_tools;
|
||||
|
||||
pub async fn handle_sanctions(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_sanctions(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct SanctionsCommand;
|
||||
pub static COMMAND_DESCRIPTOR: SanctionsCommand = SanctionsCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for SanctionsCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "sanctions",
|
||||
command: "sanctions",
|
||||
category: "admin",
|
||||
params: "<@membre/ID>",
|
||||
summary: "Affiche les sanctions d un membre",
|
||||
description: "Liste l historique des sanctions d un membre.",
|
||||
examples: &["+sanctions @User"],
|
||||
alias_source_key: "sanctions",
|
||||
default_aliases: &["sanct"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::ensure_owner;
|
||||
|
||||
pub async fn handle_say(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
if ensure_owner(ctx, msg).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
if args.is_empty() {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Usage: `+say <message>`")
|
||||
.color(0xED4245);
|
||||
crate::commands::common::send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
}
|
||||
|
||||
let text = args.join(" ");
|
||||
let _ = msg.channel_id.say(&ctx.http, text).await;
|
||||
}
|
||||
|
||||
pub struct SayCommand;
|
||||
pub static COMMAND_DESCRIPTOR: SayCommand = SayCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for SayCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "say",
|
||||
command: "say",
|
||||
category: "admin",
|
||||
params: "<message...>",
|
||||
summary: "Fait parler le bot",
|
||||
description: "Envoie un message brut dans le salon courant via le bot.",
|
||||
examples: &["+say", "+sy", "+help say"],
|
||||
alias_source_key: "say",
|
||||
default_aliases: &["sym"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::logs_service;
|
||||
|
||||
pub async fn handle_set_boostembed(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_set_boostembed(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct SetBoostembedCommand;
|
||||
pub static COMMAND_DESCRIPTOR: SetBoostembedCommand = SetBoostembedCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for SetBoostembedCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "set_boostembed",
|
||||
command: "set boostembed",
|
||||
category: "admin",
|
||||
params: "<title|description|color> <valeur>",
|
||||
summary: "Parametre l embed de boost",
|
||||
description: "Configure le titre, la description et la couleur de l embed boost.",
|
||||
examples: &[
|
||||
"+set boostembed title Merci",
|
||||
"+set boostembed color #FF66CC",
|
||||
],
|
||||
alias_source_key: "set_boostembed",
|
||||
default_aliases: &["sboostembed"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::logs_service;
|
||||
|
||||
pub async fn handle_set_modlogs(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_set_modlogs(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct SetModlogsCommand;
|
||||
pub static COMMAND_DESCRIPTOR: SetModlogsCommand = SetModlogsCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for SetModlogsCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "set_modlogs",
|
||||
command: "set modlogs",
|
||||
category: "admin",
|
||||
params: "[event on/off]",
|
||||
summary: "Parametre les evenements de modlogs",
|
||||
description: "Affiche ou modifie les evenements qui apparaissent dans les logs de moderation.",
|
||||
examples: &["+set modlogs", "+set modlogs warn off"],
|
||||
alias_source_key: "set_modlogs",
|
||||
default_aliases: &["smodlog"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::{
|
||||
CreateActionRow, CreateButton, CreateEmbed, CreateInputText, CreateInteractionResponse,
|
||||
CreateInteractionResponseMessage, CreateMessage, CreateModal,
|
||||
};
|
||||
use serenity::model::application::{
|
||||
ActionRowComponent, ButtonStyle, ComponentInteraction, InputTextStyle, ModalInteraction,
|
||||
};
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db;
|
||||
|
||||
const SUGGESTION_MENU: &str = "suggestion:settings";
|
||||
|
||||
fn parse_owner_id(custom_id: &str) -> Option<(String, u64)> {
|
||||
let mut parts = custom_id.rsplitn(2, ':');
|
||||
let owner = parts.next()?.parse::<u64>().ok()?;
|
||||
let action = parts.next()?.to_string();
|
||||
Some((action, owner))
|
||||
}
|
||||
|
||||
fn modal_value(modal: &ModalInteraction, wanted_id: &str) -> Option<String> {
|
||||
for row in &modal.data.components {
|
||||
for component in &row.components {
|
||||
if let ActionRowComponent::InputText(input) = component {
|
||||
if input.custom_id == wanted_id {
|
||||
return input.value.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn suggestion_embed(author: &User, content: &str) -> CreateEmbed {
|
||||
CreateEmbed::new()
|
||||
.title("💡 Suggestion")
|
||||
.description(content)
|
||||
.colour(Colour::from_rgb(255, 200, 0))
|
||||
.author(
|
||||
serenity::builder::CreateEmbedAuthor::new(&author.name).icon_url(author.face()),
|
||||
)
|
||||
.timestamp(Utc::now())
|
||||
}
|
||||
|
||||
fn suggestion_settings_embed(settings: &db::SuggestionSettings) -> CreateEmbed {
|
||||
let mut embed = CreateEmbed::new()
|
||||
.title("Gestion des suggestions")
|
||||
.description("Configure le système de suggestions du serveur.")
|
||||
.colour(Colour::from_rgb(255, 200, 0))
|
||||
.timestamp(Utc::now())
|
||||
.field("Statut", if settings.enabled { "Actif" } else { "Inactif" }, true);
|
||||
|
||||
if let Some(channel_id) = settings.channel_id {
|
||||
embed = embed.field("Canal", format!("<#{}>", channel_id), true);
|
||||
}
|
||||
|
||||
if let Some(approve_channel_id) = settings.approve_channel_id {
|
||||
embed = embed.field("Validation", format!("<#{}>", approve_channel_id), true);
|
||||
}
|
||||
|
||||
embed
|
||||
}
|
||||
|
||||
fn suggestion_components(owner_id: UserId, settings: &db::SuggestionSettings) -> Vec<CreateActionRow> {
|
||||
let toggle_label = if settings.enabled { "Désactiver" } else { "Activer" };
|
||||
|
||||
vec![CreateActionRow::Buttons(vec![
|
||||
CreateButton::new(format!("{}:submit:{}", SUGGESTION_MENU, owner_id.get()))
|
||||
.label("Soumettre")
|
||||
.style(ButtonStyle::Success),
|
||||
CreateButton::new(format!("{}:configure:{}", SUGGESTION_MENU, owner_id.get()))
|
||||
.label("Configurer")
|
||||
.style(ButtonStyle::Secondary),
|
||||
CreateButton::new(format!("{}:toggle:{}", SUGGESTION_MENU, owner_id.get()))
|
||||
.label(toggle_label)
|
||||
.style(ButtonStyle::Primary),
|
||||
CreateButton::new(format!("{}:refresh:{}", SUGGESTION_MENU, owner_id.get()))
|
||||
.label("Rafraîchir")
|
||||
.style(ButtonStyle::Secondary),
|
||||
])]
|
||||
}
|
||||
|
||||
async fn pool(ctx: &Context) -> Option<sqlx::PgPool> {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}
|
||||
|
||||
async fn show_menu(ctx: &Context, msg: &Message) {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let settings = db::get_or_create_suggestion_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let Some(settings) = settings else {
|
||||
return;
|
||||
};
|
||||
|
||||
let _ = msg
|
||||
.channel_id
|
||||
.send_message(
|
||||
&ctx.http,
|
||||
CreateMessage::new()
|
||||
.embed(suggestion_settings_embed(&settings))
|
||||
.components(suggestion_components(msg.author.id, &settings)),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn submit_suggestion(
|
||||
ctx: &Context,
|
||||
guild_id: GuildId,
|
||||
author: &User,
|
||||
content: String,
|
||||
) -> Result<(), String> {
|
||||
let pool = pool(ctx).await.ok_or_else(|| "Base de données indisponible".to_string())?;
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let settings = db::get_or_create_suggestion_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.map_err(|e| format!("Erreur: {e}"))?;
|
||||
|
||||
if !settings.enabled {
|
||||
return Err("Le système de suggestions est désactivé.".to_string());
|
||||
}
|
||||
|
||||
let channel_id = settings.channel_id.ok_or_else(|| "Canal de suggestions non configuré".to_string())?;
|
||||
let channel = ChannelId::new(channel_id as u64)
|
||||
.to_channel(&ctx.http)
|
||||
.await
|
||||
.map_err(|e| format!("Erreur: {e}"))?;
|
||||
let guild_channel = channel.guild().ok_or_else(|| "Canal de suggestions introuvable".to_string())?;
|
||||
|
||||
let message = guild_channel
|
||||
.send_message(
|
||||
&ctx.http,
|
||||
serenity::builder::CreateMessage::new().embed(suggestion_embed(author, &content)),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| format!("Erreur: {e}"))?;
|
||||
|
||||
db::create_suggestion(
|
||||
&pool,
|
||||
bot_id,
|
||||
guild_id.get() as i64,
|
||||
channel_id,
|
||||
message.id.get() as i64,
|
||||
author.id.get() as i64,
|
||||
content.clone(),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| format!("Erreur: {e}"))?;
|
||||
|
||||
let _ = message.react(&ctx.http, '👍').await;
|
||||
let _ = message.react(&ctx.http, '👎').await;
|
||||
|
||||
if let Ok(channels) = db::get_autopublish_channels(&pool, bot_id, guild_id.get() as i64).await {
|
||||
for autopublish_channel in channels {
|
||||
if autopublish_channel.channel_id == channel_id {
|
||||
continue;
|
||||
}
|
||||
|
||||
let _ = ChannelId::new(autopublish_channel.channel_id as u64)
|
||||
.send_message(
|
||||
&ctx.http,
|
||||
serenity::builder::CreateMessage::new()
|
||||
.embed(suggestion_embed(author, &content)),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn handle_suggestion(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
if args.first().map(|value| value.eq_ignore_ascii_case("settings")).unwrap_or(false) {
|
||||
show_menu(ctx, msg).await;
|
||||
return;
|
||||
}
|
||||
|
||||
if args.is_empty() {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Suggestion")
|
||||
.description("Utilisation: +suggestion <contenu> ou +suggestion settings")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let content = args.join(" ");
|
||||
if content.trim().is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(error) = submit_suggestion(ctx, guild_id, &msg.author, content).await {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Suggestion")
|
||||
.description(error)
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Suggestion envoyée")
|
||||
.description("La suggestion a été publiée.")
|
||||
.colour(Colour::from_rgb(0, 200, 120))
|
||||
.timestamp(Utc::now()),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn handle_component_interaction(ctx: &Context, component: &ComponentInteraction) -> bool {
|
||||
if !component.data.custom_id.starts_with(SUGGESTION_MENU) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some((action, owner_id)) = parse_owner_id(&component.data.custom_id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if component.user.id.get() != owner_id {
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Seul l'auteur du menu peut l'utiliser.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
let Some(guild_id) = component.guild_id else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let settings = db::get_or_create_suggestion_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let Some(settings) = settings else {
|
||||
return true;
|
||||
};
|
||||
|
||||
if action.ends_with(":refresh") {
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::UpdateMessage(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(suggestion_settings_embed(&settings))
|
||||
.components(suggestion_components(component.user.id, &settings)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":toggle") {
|
||||
if let Ok(updated) = db::update_suggestion_settings(
|
||||
&pool,
|
||||
bot_id,
|
||||
guild_id.get() as i64,
|
||||
!settings.enabled,
|
||||
settings.channel_id,
|
||||
settings.approve_channel_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::UpdateMessage(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(suggestion_settings_embed(&updated))
|
||||
.components(suggestion_components(component.user.id, &updated)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":configure") {
|
||||
let modal = CreateModal::new(component.data.custom_id.clone(), "Configurer les suggestions")
|
||||
.components(vec![
|
||||
CreateActionRow::InputText(
|
||||
CreateInputText::new(InputTextStyle::Short, "Canal des suggestions", "channel_id")
|
||||
.required(false),
|
||||
),
|
||||
CreateActionRow::InputText(
|
||||
CreateInputText::new(InputTextStyle::Short, "Canal d'approbation", "approve_channel_id")
|
||||
.required(false),
|
||||
),
|
||||
]);
|
||||
|
||||
let _ = component
|
||||
.create_response(&ctx.http, CreateInteractionResponse::Modal(modal))
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":submit") {
|
||||
let modal = CreateModal::new(component.data.custom_id.clone(), "Soumettre une suggestion")
|
||||
.components(vec![CreateActionRow::InputText(
|
||||
CreateInputText::new(InputTextStyle::Paragraph, "Contenu", "content")
|
||||
.required(true)
|
||||
.max_length(2000),
|
||||
)]);
|
||||
|
||||
let _ = component
|
||||
.create_response(&ctx.http, CreateInteractionResponse::Modal(modal))
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub async fn handle_modal_interaction(ctx: &Context, modal: &ModalInteraction) -> bool {
|
||||
if !modal.data.custom_id.starts_with(SUGGESTION_MENU) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some((action, owner_id)) = parse_owner_id(&modal.data.custom_id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if modal.user.id.get() != owner_id {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Seul l'auteur du menu peut soumettre ce formulaire.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
let Some(guild_id) = modal.guild_id else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let current = db::get_or_create_suggestion_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let Some(settings) = current else {
|
||||
return true;
|
||||
};
|
||||
|
||||
if action.ends_with(":configure") {
|
||||
let channel_id = modal_value(modal, "channel_id")
|
||||
.and_then(|value| value.trim().parse::<i64>().ok());
|
||||
let approve_channel_id = modal_value(modal, "approve_channel_id")
|
||||
.and_then(|value| value.trim().parse::<i64>().ok());
|
||||
|
||||
if let Ok(updated) = db::update_suggestion_settings(
|
||||
&pool,
|
||||
bot_id,
|
||||
guild_id.get() as i64,
|
||||
settings.enabled,
|
||||
channel_id,
|
||||
approve_channel_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(suggestion_settings_embed(&updated))
|
||||
.components(suggestion_components(modal.user.id, &updated))
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":submit") {
|
||||
let content = modal_value(modal, "content").unwrap_or_default();
|
||||
if content.trim().is_empty() {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Contenu invalide.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
match submit_suggestion(ctx, guild_id, &modal.user, content).await {
|
||||
Ok(_) => {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Suggestion envoyée.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(error) => {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content(error)
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_sync(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_sync(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct SyncCommand;
|
||||
pub static COMMAND_DESCRIPTOR: SyncCommand = SyncCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for SyncCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "sync",
|
||||
command: "sync",
|
||||
category: "admin",
|
||||
params: "<salon/categorie/all>",
|
||||
summary: "Synchronise les permissions",
|
||||
description: "Synchronise les permissions d'un salon avec sa categorie, ou tous les salons avec all.",
|
||||
examples: &["+sync all", "+sync #general"],
|
||||
alias_source_key: "sync",
|
||||
default_aliases: &["chsync"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_tempban(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_ban(ctx, msg, args, true).await;
|
||||
}
|
||||
pub struct TempbanCommand;
|
||||
pub static COMMAND_DESCRIPTOR: TempbanCommand = TempbanCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for TempbanCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "tempban",
|
||||
command: "tempban",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> <duree> [raison]",
|
||||
summary: "Ban temporaire",
|
||||
description: "Ban temporairement un ou plusieurs membres.",
|
||||
examples: &["+tempban @User 1d"],
|
||||
alias_source_key: "tempban",
|
||||
default_aliases: &["tb"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_tempcmute(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_cmute(ctx, msg, args, true).await;
|
||||
}
|
||||
pub struct TempcmuteCommand;
|
||||
pub static COMMAND_DESCRIPTOR: TempcmuteCommand = TempcmuteCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for TempcmuteCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "tempcmute",
|
||||
command: "tempcmute",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> <duree> [raison]",
|
||||
summary: "Mute salon temporaire",
|
||||
description: "Mute temporaire sur le salon courant.",
|
||||
examples: &["+tempcmute @User 5m"],
|
||||
alias_source_key: "tempcmute",
|
||||
default_aliases: &["tcm"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_tempmute(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_mute(ctx, msg, args, true).await;
|
||||
}
|
||||
pub struct TempmuteCommand;
|
||||
pub static COMMAND_DESCRIPTOR: TempmuteCommand = TempmuteCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for TempmuteCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "tempmute",
|
||||
command: "tempmute",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> <duree> [raison]",
|
||||
summary: "Mute temporaire",
|
||||
description: "Mute un ou plusieurs membres pour une duree donnee.",
|
||||
examples: &["+tempmute @User 10m"],
|
||||
alias_source_key: "tempmute",
|
||||
default_aliases: &["tm"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_temprole(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_temprole(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct TempRoleCommand;
|
||||
pub static COMMAND_DESCRIPTOR: TempRoleCommand = TempRoleCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for TempRoleCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "temprole",
|
||||
command: "temprole",
|
||||
category: "admin",
|
||||
params: "<membre> <role> <duree>",
|
||||
summary: "Ajoute un role temporaire",
|
||||
description: "Attribue un role a un membre pour une duree donnee puis le retire automatiquement.",
|
||||
examples: &["+temprole @User @VIP 2h"],
|
||||
alias_source_key: "temprole",
|
||||
default_aliases: &["trole", "tmprole"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::{
|
||||
CreateActionRow, CreateButton, CreateChannel, CreateEmbed, CreateInputText,
|
||||
CreateInteractionResponse, CreateInteractionResponseMessage, CreateMessage, CreateModal,
|
||||
};
|
||||
use serenity::model::application::{
|
||||
ActionRowComponent, ButtonStyle, ComponentInteraction, InputTextStyle, ModalInteraction,
|
||||
};
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::db;
|
||||
|
||||
const TEMPVOC_MENU: &str = "tempvoc:settings";
|
||||
|
||||
fn parse_owner_id(custom_id: &str) -> Option<(String, u64)> {
|
||||
let mut parts = custom_id.rsplitn(2, ':');
|
||||
let owner = parts.next()?.parse::<u64>().ok()?;
|
||||
let action = parts.next()?.to_string();
|
||||
Some((action, owner))
|
||||
}
|
||||
|
||||
fn modal_value(modal: &ModalInteraction, wanted_id: &str) -> Option<String> {
|
||||
for row in &modal.data.components {
|
||||
for component in &row.components {
|
||||
if let ActionRowComponent::InputText(input) = component {
|
||||
if input.custom_id == wanted_id {
|
||||
return input.value.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn tempvoc_embed(settings: &db::TempvocSettings) -> CreateEmbed {
|
||||
let mut embed = CreateEmbed::new()
|
||||
.title("Tempvoc")
|
||||
.description("Gère les vocaux temporaires du serveur.")
|
||||
.colour(Colour::from_rgb(100, 180, 255))
|
||||
.timestamp(Utc::now())
|
||||
.field("Statut", if settings.enabled { "Actif" } else { "Inactif" }, true);
|
||||
|
||||
if let Some(trigger) = settings.trigger_channel_id {
|
||||
embed = embed.field("Canal déclencheur", format!("<#{}>", trigger), true);
|
||||
}
|
||||
|
||||
if let Some(category) = settings.category_id {
|
||||
embed = embed.field("Catégorie", format!("<#{}>", category), true);
|
||||
}
|
||||
|
||||
embed
|
||||
}
|
||||
|
||||
fn tempvoc_components(owner_id: UserId, settings: &db::TempvocSettings) -> Vec<CreateActionRow> {
|
||||
let toggle_label = if settings.enabled { "Désactiver" } else { "Activer" };
|
||||
|
||||
vec![CreateActionRow::Buttons(vec![
|
||||
CreateButton::new(format!("{}:toggle:{}", TEMPVOC_MENU, owner_id.get()))
|
||||
.label(toggle_label)
|
||||
.style(ButtonStyle::Primary),
|
||||
CreateButton::new(format!("{}:configure:{}", TEMPVOC_MENU, owner_id.get()))
|
||||
.label("Configurer")
|
||||
.style(ButtonStyle::Secondary),
|
||||
CreateButton::new(format!("{}:refresh:{}", TEMPVOC_MENU, owner_id.get()))
|
||||
.label("Rafraîchir")
|
||||
.style(ButtonStyle::Success),
|
||||
])]
|
||||
}
|
||||
|
||||
async fn pool(ctx: &Context) -> Option<sqlx::PgPool> {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}
|
||||
|
||||
async fn show_menu(ctx: &Context, msg: &Message) {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let settings = db::get_or_create_tempvoc_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.unwrap_or(db::TempvocSettings {
|
||||
bot_id,
|
||||
guild_id: guild_id.get() as i64,
|
||||
trigger_channel_id: None,
|
||||
category_id: None,
|
||||
enabled: false,
|
||||
updated_at: chrono::Utc::now(),
|
||||
});
|
||||
|
||||
let _ = msg
|
||||
.channel_id
|
||||
.send_message(
|
||||
&ctx.http,
|
||||
CreateMessage::new()
|
||||
.embed(tempvoc_embed(&settings))
|
||||
.components(tempvoc_components(msg.author.id, &settings)),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn handle_tempvoc(ctx: &Context, msg: &Message, _args: &[&str]) {
|
||||
show_menu(ctx, msg).await;
|
||||
}
|
||||
|
||||
pub async fn handle_component_interaction(ctx: &Context, component: &ComponentInteraction) -> bool {
|
||||
if !component.data.custom_id.starts_with(TEMPVOC_MENU) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some((action, owner_id)) = parse_owner_id(&component.data.custom_id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if component.user.id.get() != owner_id {
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Seul l'auteur du menu peut l'utiliser.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
let Some(guild_id) = component.guild_id else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let settings = db::get_or_create_tempvoc_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let Some(settings) = settings else {
|
||||
return true;
|
||||
};
|
||||
|
||||
if action.ends_with(":configure") {
|
||||
let modal = CreateModal::new(component.data.custom_id.clone(), "Configurer Tempvoc")
|
||||
.components(vec![
|
||||
CreateActionRow::InputText(
|
||||
CreateInputText::new(
|
||||
InputTextStyle::Short,
|
||||
"Canal déclencheur",
|
||||
"trigger_channel_id",
|
||||
)
|
||||
.required(false),
|
||||
),
|
||||
CreateActionRow::InputText(
|
||||
CreateInputText::new(InputTextStyle::Short, "Catégorie", "category_id")
|
||||
.required(false),
|
||||
),
|
||||
]);
|
||||
|
||||
let _ = component
|
||||
.create_response(&ctx.http, CreateInteractionResponse::Modal(modal))
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":toggle") {
|
||||
let new_settings = db::update_tempvoc_settings(
|
||||
&pool,
|
||||
bot_id,
|
||||
guild_id.get() as i64,
|
||||
settings.trigger_channel_id,
|
||||
settings.category_id,
|
||||
!settings.enabled,
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
if let Some(updated) = new_settings {
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::UpdateMessage(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(tempvoc_embed(&updated))
|
||||
.components(tempvoc_components(component.user.id, &updated)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":refresh") {
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::UpdateMessage(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(tempvoc_embed(&settings))
|
||||
.components(tempvoc_components(component.user.id, &settings)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub async fn handle_modal_interaction(ctx: &Context, modal: &ModalInteraction) -> bool {
|
||||
if !modal.data.custom_id.starts_with(TEMPVOC_MENU) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some((action, owner_id)) = parse_owner_id(&modal.data.custom_id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if modal.user.id.get() != owner_id {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Seul l'auteur du menu peut soumettre ce formulaire.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
if !action.contains(":configure") {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some(guild_id) = modal.guild_id else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let trigger_channel_id = modal_value(modal, "trigger_channel_id")
|
||||
.and_then(|value| value.trim().parse::<i64>().ok());
|
||||
let category_id = modal_value(modal, "category_id")
|
||||
.and_then(|value| value.trim().parse::<i64>().ok());
|
||||
|
||||
let updated = db::update_tempvoc_settings(
|
||||
&pool,
|
||||
bot_id,
|
||||
guild_id.get() as i64,
|
||||
trigger_channel_id,
|
||||
category_id,
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
if let Some(updated) = updated {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(tempvoc_embed(&updated))
|
||||
.components(tempvoc_components(modal.user.id, &updated))
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn sanitize_voice_name(input: &str) -> String {
|
||||
let mut out = String::new();
|
||||
let mut previous_dash = false;
|
||||
|
||||
for ch in input.to_lowercase().chars() {
|
||||
if ch.is_ascii_alphanumeric() {
|
||||
out.push(ch);
|
||||
previous_dash = false;
|
||||
} else if (ch.is_whitespace() || ch == '-' || ch == '_') && !previous_dash {
|
||||
out.push('-');
|
||||
previous_dash = true;
|
||||
}
|
||||
}
|
||||
|
||||
out.trim_matches('-').to_string()
|
||||
}
|
||||
|
||||
async fn cached_room_members(ctx: &Context, guild_id: GuildId, channel_id: ChannelId) -> usize {
|
||||
ctx.cache
|
||||
.guild(guild_id)
|
||||
.map(|guild| {
|
||||
guild
|
||||
.voice_states
|
||||
.values()
|
||||
.filter(|state| state.channel_id == Some(channel_id))
|
||||
.count()
|
||||
})
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
async fn create_temp_channel(ctx: &Context, guild_id: GuildId, user: &User, settings: &db::TempvocSettings) {
|
||||
let Some(trigger_channel_id) = settings.trigger_channel_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Ok(trigger_channel) = ChannelId::new(trigger_channel_id as u64)
|
||||
.to_channel(&ctx.http)
|
||||
.await else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Channel::Guild(trigger) = trigger_channel else {
|
||||
return;
|
||||
};
|
||||
|
||||
let category_id = settings
|
||||
.category_id
|
||||
.map(|value| ChannelId::new(value as u64))
|
||||
.or(trigger.parent_id);
|
||||
let name = sanitize_voice_name(&user.name);
|
||||
if name.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut builder = CreateChannel::new(format!("🎤 {}", name))
|
||||
.kind(ChannelType::Voice)
|
||||
.permissions(trigger.permission_overwrites.clone());
|
||||
|
||||
if let Some(category_id) = category_id {
|
||||
builder = builder.category(category_id);
|
||||
}
|
||||
|
||||
let Ok(channel) = guild_id.create_channel(&ctx.http, builder).await else {
|
||||
return;
|
||||
};
|
||||
|
||||
if guild_id
|
||||
.move_member(&ctx.http, user.id, channel.id)
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
let _ = channel.delete(&ctx.http).await;
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(pool) = pool(ctx).await {
|
||||
let _ = db::create_tempvoc_room(
|
||||
&pool,
|
||||
settings.bot_id,
|
||||
settings.guild_id,
|
||||
channel.id.get() as i64,
|
||||
user.id.get() as i64,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn delete_temp_channel(ctx: &Context, channel_id: ChannelId) {
|
||||
if let Ok(channel) = channel_id.to_channel(&ctx.http).await {
|
||||
if let Channel::Guild(guild_channel) = channel {
|
||||
let _ = guild_channel.delete(&ctx.http).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_voice_state_update(ctx: &Context, old: Option<&VoiceState>, new: &VoiceState) {
|
||||
let Some(guild_id) = new.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let guild_id_i64 = guild_id.get() as i64;
|
||||
let settings = db::get_or_create_tempvoc_settings(&pool, bot_id, guild_id_i64)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let Some(settings) = settings else {
|
||||
return;
|
||||
};
|
||||
|
||||
let old_channel = old.and_then(|state| state.channel_id);
|
||||
let new_channel = new.channel_id;
|
||||
|
||||
if settings.enabled
|
||||
&& settings.trigger_channel_id.is_some()
|
||||
&& new_channel.map(|channel| channel.get() as i64) == settings.trigger_channel_id
|
||||
{
|
||||
if let Ok(member) = guild_id.member(&ctx.http, new.user_id).await {
|
||||
create_temp_channel(ctx, guild_id, &member.user, &settings).await;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(old_channel) = old_channel {
|
||||
if db::get_tempvoc_room_by_channel(&pool, old_channel.get() as i64)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
.is_some()
|
||||
&& cached_room_members(ctx, guild_id, old_channel).await == 0
|
||||
{
|
||||
delete_temp_channel(ctx, old_channel).await;
|
||||
let _ = db::delete_tempvoc_room(&pool, old_channel.get() as i64).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::CreateEmbed;
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::send_embed;
|
||||
|
||||
pub async fn handle_tempvoc_cmd(ctx: &Context, msg: &Message, _args: &[&str]) {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Commandes Tempvoc")
|
||||
.description("\n+tempvoc\n+tempvoc cmd\n\nLe salon de création est surveillé automatiquement: lorsqu'un membre le rejoint, un vocal temporaire est créé et l'utilisateur y est déplacé.")
|
||||
.colour(Colour::from_rgb(100, 180, 255))
|
||||
.timestamp(Utc::now());
|
||||
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::{
|
||||
CreateActionRow, CreateButton, CreateChannel, CreateEmbed, CreateInputText,
|
||||
CreateInteractionResponse, CreateInteractionResponseMessage, CreateMessage, CreateModal,
|
||||
};
|
||||
use serenity::model::application::{
|
||||
ActionRowComponent, ButtonStyle, ComponentInteraction, InputTextStyle, ModalInteraction,
|
||||
};
|
||||
use serenity::all::{PermissionOverwrite, PermissionOverwriteType, Permissions};
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::db;
|
||||
|
||||
const TICKET_MENU: &str = "ticket:settings";
|
||||
|
||||
fn parse_owner_id(custom_id: &str) -> Option<(String, u64)> {
|
||||
let mut parts = custom_id.rsplitn(2, ':');
|
||||
let owner = parts.next()?.parse::<u64>().ok()?;
|
||||
let action = parts.next()?.to_string();
|
||||
Some((action, owner))
|
||||
}
|
||||
|
||||
fn modal_value(modal: &ModalInteraction, wanted_id: &str) -> Option<String> {
|
||||
for row in &modal.data.components {
|
||||
for component in &row.components {
|
||||
if let ActionRowComponent::InputText(input) = component {
|
||||
if input.custom_id == wanted_id {
|
||||
return input.value.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn sanitize_channel_name(input: &str) -> String {
|
||||
let mut out = String::new();
|
||||
let mut previous_dash = false;
|
||||
|
||||
for ch in input.to_lowercase().chars() {
|
||||
if ch.is_ascii_alphanumeric() {
|
||||
out.push(ch);
|
||||
previous_dash = false;
|
||||
} else if (ch.is_whitespace() || ch == '-' || ch == '_') && !previous_dash {
|
||||
out.push('-');
|
||||
previous_dash = true;
|
||||
}
|
||||
}
|
||||
|
||||
out.trim_matches('-').to_string()
|
||||
}
|
||||
|
||||
fn ticket_embed(settings: &db::TicketSettings) -> CreateEmbed {
|
||||
let mut embed = CreateEmbed::new()
|
||||
.title("Gestion des tickets")
|
||||
.description("Utilise les boutons ci-dessous pour gérer le système de tickets.")
|
||||
.colour(Colour::from_rgb(90, 160, 255))
|
||||
.timestamp(Utc::now())
|
||||
.field("Statut", if settings.enabled { "Actif" } else { "Inactif" }, true);
|
||||
|
||||
if let Some(category_id) = settings.category_id {
|
||||
embed = embed.field("Catégorie", format!("<#{}>", category_id), true);
|
||||
}
|
||||
|
||||
if let Some(log_channel_id) = settings.log_channel_id {
|
||||
embed = embed.field("Logs", format!("<#{}>", log_channel_id), true);
|
||||
}
|
||||
|
||||
embed
|
||||
}
|
||||
|
||||
fn ticket_components(owner_id: UserId, settings: &db::TicketSettings) -> Vec<CreateActionRow> {
|
||||
let toggle_label = if settings.enabled { "Désactiver" } else { "Activer" };
|
||||
|
||||
vec![CreateActionRow::Buttons(vec![
|
||||
CreateButton::new(format!("{}:create:{}", TICKET_MENU, owner_id.get()))
|
||||
.label("Créer")
|
||||
.style(ButtonStyle::Success),
|
||||
CreateButton::new(format!("{}:configure:{}", TICKET_MENU, owner_id.get()))
|
||||
.label("Configurer")
|
||||
.style(ButtonStyle::Secondary),
|
||||
CreateButton::new(format!("{}:toggle:{}", TICKET_MENU, owner_id.get()))
|
||||
.label(toggle_label)
|
||||
.style(ButtonStyle::Primary),
|
||||
CreateButton::new(format!("{}:refresh:{}", TICKET_MENU, owner_id.get()))
|
||||
.label("Rafraîchir")
|
||||
.style(ButtonStyle::Secondary),
|
||||
])]
|
||||
}
|
||||
|
||||
async fn pool(ctx: &Context) -> Option<sqlx::PgPool> {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}
|
||||
|
||||
async fn current_settings(ctx: &Context, guild_id: GuildId) -> Option<db::TicketSettings> {
|
||||
let pool = pool(ctx).await?;
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
db::get_or_create_ticket_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.ok()
|
||||
}
|
||||
|
||||
async fn show_menu(ctx: &Context, msg: &Message) {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(settings) = current_settings(ctx, guild_id).await else {
|
||||
return;
|
||||
};
|
||||
|
||||
let _ = msg
|
||||
.channel_id
|
||||
.send_message(
|
||||
&ctx.http,
|
||||
CreateMessage::new()
|
||||
.embed(ticket_embed(&settings))
|
||||
.components(ticket_components(msg.author.id, &settings)),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn create_ticket_channel(
|
||||
ctx: &Context,
|
||||
guild_id: GuildId,
|
||||
creator: UserId,
|
||||
title: String,
|
||||
settings: &db::TicketSettings,
|
||||
) -> Result<ChannelId, String> {
|
||||
let pool = pool(ctx).await.ok_or_else(|| "Base de données indisponible".to_string())?;
|
||||
|
||||
let name = sanitize_channel_name(&title);
|
||||
if name.is_empty() {
|
||||
return Err("Nom de ticket invalide".to_string());
|
||||
}
|
||||
|
||||
let mut builder = CreateChannel::new(format!("ticket-{}", name))
|
||||
.kind(ChannelType::Text)
|
||||
.permissions(vec![
|
||||
PermissionOverwrite {
|
||||
allow: Permissions::empty(),
|
||||
deny: Permissions::VIEW_CHANNEL.union(
|
||||
Permissions::SEND_MESSAGES
|
||||
| Permissions::READ_MESSAGE_HISTORY
|
||||
| Permissions::ATTACH_FILES
|
||||
| Permissions::EMBED_LINKS,
|
||||
),
|
||||
kind: PermissionOverwriteType::Role(RoleId::new(guild_id.get())),
|
||||
},
|
||||
PermissionOverwrite {
|
||||
allow: Permissions::VIEW_CHANNEL
|
||||
| Permissions::SEND_MESSAGES
|
||||
| Permissions::READ_MESSAGE_HISTORY
|
||||
| Permissions::ATTACH_FILES
|
||||
| Permissions::EMBED_LINKS
|
||||
| Permissions::ADD_REACTIONS,
|
||||
deny: Permissions::empty(),
|
||||
kind: PermissionOverwriteType::Member(creator),
|
||||
},
|
||||
]);
|
||||
|
||||
if let Some(category_id) = settings.category_id {
|
||||
builder = builder.category(ChannelId::new(category_id as u64));
|
||||
}
|
||||
|
||||
let channel = guild_id
|
||||
.create_channel(&ctx.http, builder)
|
||||
.await
|
||||
.map_err(|e| format!("Impossible de créer le salon: {e}"))?;
|
||||
|
||||
let _ = db::create_ticket(
|
||||
&pool,
|
||||
settings.bot_id,
|
||||
settings.guild_id,
|
||||
channel.id.get() as i64,
|
||||
creator.get() as i64,
|
||||
title,
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(channel.id)
|
||||
}
|
||||
|
||||
pub async fn handle_ticket_settings(ctx: &Context, msg: &Message, _args: &[&str]) {
|
||||
show_menu(ctx, msg).await;
|
||||
}
|
||||
|
||||
pub async fn handle_component_interaction(ctx: &Context, component: &ComponentInteraction) -> bool {
|
||||
if !component.data.custom_id.starts_with(TICKET_MENU) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some((action, owner_id)) = parse_owner_id(&component.data.custom_id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if component.user.id.get() != owner_id {
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Seul l'auteur du menu peut l'utiliser.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
let Some(guild_id) = component.guild_id else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let settings = db::get_or_create_ticket_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let Some(settings) = settings else {
|
||||
return true;
|
||||
};
|
||||
|
||||
if action.ends_with(":refresh") {
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::UpdateMessage(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(ticket_embed(&settings))
|
||||
.components(ticket_components(component.user.id, &settings)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":toggle") {
|
||||
if let Ok(updated) = db::update_ticket_settings(
|
||||
&pool,
|
||||
bot_id,
|
||||
guild_id.get() as i64,
|
||||
settings.category_id,
|
||||
settings.log_channel_id,
|
||||
!settings.enabled,
|
||||
)
|
||||
.await
|
||||
{
|
||||
let _ = component
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::UpdateMessage(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(ticket_embed(&updated))
|
||||
.components(ticket_components(component.user.id, &updated)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":configure") {
|
||||
let modal = CreateModal::new(component.data.custom_id.clone(), "Configurer les tickets")
|
||||
.components(vec![
|
||||
CreateActionRow::InputText(
|
||||
CreateInputText::new(InputTextStyle::Short, "Catégorie", "category_id")
|
||||
.required(false),
|
||||
),
|
||||
CreateActionRow::InputText(
|
||||
CreateInputText::new(InputTextStyle::Short, "Salon de logs", "log_channel_id")
|
||||
.required(false),
|
||||
),
|
||||
]);
|
||||
|
||||
let _ = component
|
||||
.create_response(&ctx.http, CreateInteractionResponse::Modal(modal))
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":create") {
|
||||
let modal = CreateModal::new(component.data.custom_id.clone(), "Créer un ticket")
|
||||
.components(vec![CreateActionRow::InputText(
|
||||
CreateInputText::new(InputTextStyle::Short, "Nom du ticket", "ticket_title")
|
||||
.required(true)
|
||||
.max_length(100),
|
||||
)]);
|
||||
|
||||
let _ = component
|
||||
.create_response(&ctx.http, CreateInteractionResponse::Modal(modal))
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub async fn handle_modal_interaction(ctx: &Context, modal: &ModalInteraction) -> bool {
|
||||
if !modal.data.custom_id.starts_with(TICKET_MENU) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some((action, owner_id)) = parse_owner_id(&modal.data.custom_id) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
if modal.user.id.get() != owner_id {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Seul l'auteur du menu peut soumettre ce formulaire.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
let Some(guild_id) = modal.guild_id else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let Some(pool) = pool(ctx).await else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let current = db::get_or_create_ticket_settings(&pool, bot_id, guild_id.get() as i64)
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let Some(settings) = current else {
|
||||
return true;
|
||||
};
|
||||
|
||||
if action.ends_with(":configure") {
|
||||
let category_id = modal_value(modal, "category_id")
|
||||
.and_then(|value| value.trim().parse::<i64>().ok());
|
||||
let log_channel_id = modal_value(modal, "log_channel_id")
|
||||
.and_then(|value| value.trim().parse::<i64>().ok());
|
||||
|
||||
if let Ok(updated) = db::update_ticket_settings(
|
||||
&pool,
|
||||
bot_id,
|
||||
guild_id.get() as i64,
|
||||
category_id,
|
||||
log_channel_id,
|
||||
settings.enabled,
|
||||
)
|
||||
.await
|
||||
{
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(ticket_embed(&updated))
|
||||
.components(ticket_components(modal.user.id, &updated))
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if action.ends_with(":create") {
|
||||
let title = modal_value(modal, "ticket_title").unwrap_or_default();
|
||||
let title = title.trim().to_string();
|
||||
|
||||
if title.is_empty() {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content("Nom de ticket invalide.")
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
return true;
|
||||
}
|
||||
|
||||
match create_ticket_channel(ctx, guild_id, modal.user.id, title.clone(), &settings).await {
|
||||
Ok(channel_id) => {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.embed(
|
||||
CreateEmbed::new()
|
||||
.title("Ticket créé")
|
||||
.description(format!("Salon: <#{}>", channel_id.get()))
|
||||
.colour(Colour::from_rgb(0, 200, 120))
|
||||
.timestamp(Utc::now()),
|
||||
)
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(error) => {
|
||||
let _ = modal
|
||||
.create_response(
|
||||
&ctx.http,
|
||||
CreateInteractionResponse::Message(
|
||||
CreateInteractionResponseMessage::new()
|
||||
.content(error)
|
||||
.ephemeral(true),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
use chrono::Utc;
|
||||
use serenity::all::{PermissionOverwrite, PermissionOverwriteType, Permissions};
|
||||
use serenity::builder::{CreateEmbed, EditChannel};
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::parse_user_id;
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db;
|
||||
|
||||
const TICKET_ALLOW: Permissions = Permissions::VIEW_CHANNEL
|
||||
.union(Permissions::SEND_MESSAGES)
|
||||
.union(Permissions::READ_MESSAGE_HISTORY)
|
||||
.union(Permissions::ATTACH_FILES)
|
||||
.union(Permissions::EMBED_LINKS)
|
||||
.union(Permissions::ADD_REACTIONS);
|
||||
|
||||
fn ticket_member_id(args: &[&str], msg: &Message) -> Option<UserId> {
|
||||
msg.mentions.first().map(|user| user.id).or_else(|| {
|
||||
args.first().and_then(|value| parse_user_id(value))
|
||||
})
|
||||
}
|
||||
|
||||
async fn ticket_member_update(
|
||||
ctx: &Context,
|
||||
msg: &Message,
|
||||
args: &[&str],
|
||||
allow: bool,
|
||||
) -> Result<(), ()> {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return Err(());
|
||||
};
|
||||
|
||||
let Some(user_id) = ticket_member_id(args, msg) else {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Utilisateur introuvable.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return Err(());
|
||||
};
|
||||
|
||||
let Some(pool) = ({
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}) else {
|
||||
return Err(());
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
let guild_id_i64 = guild_id.get() as i64;
|
||||
let channel_id = msg.channel_id.get() as i64;
|
||||
|
||||
let Some(ticket) = db::get_ticket_by_channel(&pool, bot_id, guild_id_i64, channel_id)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
else {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Ce salon n'est pas reconnu comme un ticket.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return Err(());
|
||||
};
|
||||
|
||||
let Ok(channel) = msg.channel_id.to_channel(&ctx.http).await else {
|
||||
return Err(());
|
||||
};
|
||||
|
||||
let Channel::Guild(guild_channel) = channel else {
|
||||
return Err(());
|
||||
};
|
||||
|
||||
let mut overwrites = guild_channel.permission_overwrites.clone();
|
||||
overwrites.retain(|overwrite| {
|
||||
!matches!(overwrite.kind, PermissionOverwriteType::Member(id) if id == user_id)
|
||||
});
|
||||
|
||||
if allow {
|
||||
overwrites.push(PermissionOverwrite {
|
||||
allow: TICKET_ALLOW,
|
||||
deny: Permissions::empty(),
|
||||
kind: PermissionOverwriteType::Member(user_id),
|
||||
});
|
||||
}
|
||||
|
||||
if msg
|
||||
.channel_id
|
||||
.edit(&ctx.http, EditChannel::new().permissions(overwrites))
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Impossible de mettre à jour les permissions du ticket.")
|
||||
.color(0xED4245),
|
||||
)
|
||||
.await;
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if allow {
|
||||
let _ = db::add_ticket_member(&pool, ticket.id, user_id.get() as i64).await;
|
||||
} else {
|
||||
let _ = db::remove_ticket_member(&pool, ticket.id, user_id.get() as i64).await;
|
||||
}
|
||||
|
||||
let title = if allow { "Membre ajouté" } else { "Membre retiré" };
|
||||
let description = if allow {
|
||||
format!("<@{}> a été ajouté au ticket.", user_id.get())
|
||||
} else {
|
||||
format!("<@{}> a été retiré du ticket.", user_id.get())
|
||||
};
|
||||
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title(title)
|
||||
.description(description)
|
||||
.colour(Colour::from_rgb(0, 200, 120))
|
||||
.timestamp(Utc::now()),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn handle_ticket_add(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
let _ = ticket_member_update(ctx, msg, args, true).await;
|
||||
}
|
||||
|
||||
pub async fn handle_ticket_remove(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
let _ = ticket_member_update(ctx, msg, args, false).await;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
use chrono::Utc;
|
||||
use serenity::builder::{CreateEmbed, CreateEmbedFooter};
|
||||
use serenity::model::Colour;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db;
|
||||
|
||||
pub async fn handle_tickets(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
let Some(guild_id) = msg.guild_id else {
|
||||
return;
|
||||
};
|
||||
|
||||
let page = args
|
||||
.first()
|
||||
.and_then(|value| value.parse::<i64>().ok())
|
||||
.unwrap_or(1)
|
||||
.max(1);
|
||||
|
||||
let Some(pool) = ({
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<db::DbPoolKey>().cloned()
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let limit = 10i64;
|
||||
let offset = (page - 1) * limit;
|
||||
let bot_id = ctx.cache.current_user().id.get() as i64;
|
||||
|
||||
let tickets = db::get_guild_tickets(
|
||||
&pool,
|
||||
bot_id,
|
||||
guild_id.get() as i64,
|
||||
limit,
|
||||
offset,
|
||||
)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
if tickets.is_empty() {
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Tickets")
|
||||
.description("Aucun ticket trouvé.")
|
||||
.colour(Colour::from_rgb(100, 100, 100)),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let mut description = String::new();
|
||||
for ticket in tickets {
|
||||
description.push_str(&format!(
|
||||
"**#{} - {}**\nAuteur: <@{}> | Statut: {}\n\n",
|
||||
ticket.id, ticket.title, ticket.creator_id, ticket.status
|
||||
));
|
||||
}
|
||||
|
||||
send_embed(
|
||||
ctx,
|
||||
msg,
|
||||
CreateEmbed::new()
|
||||
.title("Tickets")
|
||||
.description(description)
|
||||
.colour(Colour::from_rgb(0, 100, 200))
|
||||
.footer(CreateEmbedFooter::new(format!("Page {}", page)))
|
||||
.timestamp(Utc::now()),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_unban(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_unban(ctx, msg, args).await;
|
||||
}
|
||||
pub struct UnbanCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnbanCommand = UnbanCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for UnbanCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unban",
|
||||
command: "unban",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]>",
|
||||
summary: "Retire un ban",
|
||||
description: "Unban un ou plusieurs membres.",
|
||||
examples: &["+unban @User"],
|
||||
alias_source_key: "unban",
|
||||
default_aliases: &["ub"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_unbanall(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_unbanall(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct UnbanAllCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnbanAllCommand = UnbanAllCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for UnbanAllCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unbanall",
|
||||
command: "unbanall",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Retire tous les bannissements",
|
||||
description: "Supprime tous les bans du serveur cible.",
|
||||
examples: &["+unbanall"],
|
||||
alias_source_key: "unbanall",
|
||||
default_aliases: &["uball", "clearbans"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::{ensure_owner, parse_user_id};
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db::{DbPoolKey, remove_from_blacklist};
|
||||
|
||||
pub async fn handle_unbl(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
if ensure_owner(ctx, msg).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
if args.is_empty() {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Usage: `+unbl <@membre/ID>`")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(target) = parse_user_id(args[0]) else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Membre invalide.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let bot_id = ctx.cache.current_user().id;
|
||||
let pool = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<DbPoolKey>().cloned()
|
||||
};
|
||||
|
||||
let Some(pool) = pool else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("DB indisponible.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let count = remove_from_blacklist(&pool, bot_id, target)
|
||||
.await
|
||||
.unwrap_or(0);
|
||||
let desc = if count > 0 {
|
||||
format!("<@{}> retiré de la blacklist.", target.get())
|
||||
} else {
|
||||
format!("<@{}> n'était pas blacklisté.", target.get())
|
||||
};
|
||||
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Unblacklist")
|
||||
.description(desc)
|
||||
.color(0x57F287);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
|
||||
pub struct UnblCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnblCommand = UnblCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for UnblCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unbl",
|
||||
command: "unbl",
|
||||
category: "admin",
|
||||
params: "<@membre/ID>",
|
||||
summary: "Retire un utilisateur blacklist",
|
||||
description: "Retire un utilisateur de la blacklist globale du bot.",
|
||||
examples: &["+unbl", "+ul", "+help unbl"],
|
||||
alias_source_key: "unbl",
|
||||
default_aliases: &["unb"],
|
||||
default_permission: 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_uncmute(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_uncmute(ctx, msg, args).await;
|
||||
}
|
||||
pub struct UncmuteCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UncmuteCommand = UncmuteCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for UncmuteCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "uncmute",
|
||||
command: "uncmute",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]>",
|
||||
summary: "Retire un cmute",
|
||||
description: "Met fin au mute salon.",
|
||||
examples: &["+uncmute @User"],
|
||||
alias_source_key: "uncmute",
|
||||
default_aliases: &["ucm"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_unhide(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_hide_unhide(ctx, msg, args, false).await;
|
||||
}
|
||||
pub struct UnhideCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnhideCommand = UnhideCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for UnhideCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unhide",
|
||||
command: "unhide",
|
||||
category: "admin",
|
||||
params: "[salon]",
|
||||
summary: "Affiche un salon",
|
||||
description: "Rend a nouveau visible un salon.",
|
||||
examples: &["+unhide", "+unhide #general"],
|
||||
alias_source_key: "unhide",
|
||||
default_aliases: &["uhd"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_unhideall(ctx: &Context, msg: &Message) {
|
||||
moderation_tools::handle_hideall_unhideall(ctx, msg, false).await;
|
||||
}
|
||||
|
||||
pub struct UnhideallCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnhideallCommand = UnhideallCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for UnhideallCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unhideall",
|
||||
command: "unhideall",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Affiche tous les salons",
|
||||
description: "Rend visibles tous les salons du serveur.",
|
||||
examples: &["+unhideall"],
|
||||
alias_source_key: "unhideall",
|
||||
default_aliases: &["uhda"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_unlock(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_lock_unlock(ctx, msg, args, false).await;
|
||||
}
|
||||
pub struct UnlockCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnlockCommand = UnlockCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for UnlockCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unlock",
|
||||
command: "unlock",
|
||||
category: "admin",
|
||||
params: "[salon]",
|
||||
summary: "Ouvre un salon",
|
||||
description: "Deverrouille un salon texte ou vocal.",
|
||||
examples: &["+unlock", "+unlock #general"],
|
||||
alias_source_key: "unlock",
|
||||
default_aliases: &["ulk"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_unlockall(ctx: &Context, msg: &Message) {
|
||||
moderation_tools::handle_lockall_unlockall(ctx, msg, false).await;
|
||||
}
|
||||
pub struct UnlockallCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnlockallCommand = UnlockallCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for UnlockallCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unlockall",
|
||||
command: "unlockall",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Ouvre tous les salons",
|
||||
description: "Deverrouille tous les salons du serveur.",
|
||||
examples: &["+unlockall"],
|
||||
alias_source_key: "unlockall",
|
||||
default_aliases: &["ulka"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_unmassiverole(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_massive_role(ctx, msg, args, false).await;
|
||||
}
|
||||
|
||||
pub struct UnMassiveRoleCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnMassiveRoleCommand = UnMassiveRoleCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for UnMassiveRoleCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unmassiverole",
|
||||
command: "unmassiverole",
|
||||
category: "admin",
|
||||
params: "<role_cible> [role_filtre]",
|
||||
summary: "Retire un role en masse",
|
||||
description: "Retire un role a tous les membres ou a ceux qui ont un role filtre.",
|
||||
examples: &["+unmassiverole @VIP", "+unmassiverole @VIP @Membres"],
|
||||
alias_source_key: "unmassiverole",
|
||||
default_aliases: &["umrole", "umr"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_unmute(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_unmute(ctx, msg, args).await;
|
||||
}
|
||||
pub struct UnmuteCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnmuteCommand = UnmuteCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for UnmuteCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unmute",
|
||||
command: "unmute",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]>",
|
||||
summary: "Retire un mute",
|
||||
description: "Met fin au mute d un ou plusieurs membres.",
|
||||
examples: &["+unmute @User"],
|
||||
alias_source_key: "unmute",
|
||||
default_aliases: &["um"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_unmuteall(ctx: &Context, msg: &Message) {
|
||||
moderation_tools::handle_unmuteall(ctx, msg).await;
|
||||
}
|
||||
pub struct UnmuteallCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnmuteallCommand = UnmuteallCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for UnmuteallCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unmuteall",
|
||||
command: "unmuteall",
|
||||
category: "admin",
|
||||
params: "aucun",
|
||||
summary: "Retire tous les mutes",
|
||||
description: "Supprime tous les mutes en cours.",
|
||||
examples: &["+unmuteall"],
|
||||
alias_source_key: "unmuteall",
|
||||
default_aliases: &["uma"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::admin_common::{app_owner_id, ensure_owner, parse_user_id};
|
||||
use crate::commands::common::send_embed;
|
||||
use crate::db::{DbPoolKey, remove_bot_owner};
|
||||
|
||||
pub async fn handle_unowner(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
if ensure_owner(ctx, msg).await.is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
if args.is_empty() {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Usage: `+unowner <@membre/ID>`")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(target) = parse_user_id(args[0]) else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("Membre invalide.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(app_owner) = app_owner_id(ctx).await {
|
||||
if app_owner == target {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Refusé")
|
||||
.description("Impossible de retirer l'owner principal de l'application.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let bot_id = ctx.cache.current_user().id;
|
||||
let pool = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<DbPoolKey>().cloned()
|
||||
};
|
||||
|
||||
let Some(pool) = pool else {
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Erreur")
|
||||
.description("DB indisponible.")
|
||||
.color(0xED4245);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
return;
|
||||
};
|
||||
|
||||
let removed = remove_bot_owner(&pool, bot_id, target).await.unwrap_or(0);
|
||||
let desc = if removed > 0 {
|
||||
format!("<@{}> n'est plus owner.", target.get())
|
||||
} else {
|
||||
format!("<@{}> n'était pas owner.", target.get())
|
||||
};
|
||||
|
||||
let embed = serenity::builder::CreateEmbed::new()
|
||||
.title("Unowner")
|
||||
.description(desc)
|
||||
.color(0x57F287);
|
||||
send_embed(ctx, msg, embed).await;
|
||||
}
|
||||
|
||||
pub struct UnownerCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnownerCommand = UnownerCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for UnownerCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "unowner",
|
||||
command: "unowner",
|
||||
category: "admin",
|
||||
params: "<@membre/ID>",
|
||||
summary: "Retire un owner du bot",
|
||||
description: "Retire un utilisateur de la liste des owners supplementaires du bot.",
|
||||
examples: &["+unowner", "+ur", "+help unowner"],
|
||||
alias_source_key: "unowner",
|
||||
default_aliases: &["uow"],
|
||||
default_permission: 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_untemprole(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_untemprole(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct UnTempRoleCommand;
|
||||
pub static COMMAND_DESCRIPTOR: UnTempRoleCommand = UnTempRoleCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for UnTempRoleCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "untemprole",
|
||||
command: "untemprole",
|
||||
category: "admin",
|
||||
params: "<membre> <role>",
|
||||
summary: "Retire un role temporaire",
|
||||
description: "Retire immediatement un role temporaire et desactive son expiration.",
|
||||
examples: &["+untemprole @User @VIP"],
|
||||
alias_source_key: "untemprole",
|
||||
default_aliases: &["untrole", "deltrole"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_voicekick(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_voicekick(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct VoiceKickCommand;
|
||||
pub static COMMAND_DESCRIPTOR: VoiceKickCommand = VoiceKickCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for VoiceKickCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "voicekick",
|
||||
command: "voicekick",
|
||||
category: "admin",
|
||||
params: "<membre...>",
|
||||
summary: "Deconnecte des membres du vocal",
|
||||
description: "Deconnecte un ou plusieurs membres de leur salon vocal actuel.",
|
||||
examples: &["+voicekick @User", "+voicekick @U1 @U2"],
|
||||
alias_source_key: "voicekick",
|
||||
default_aliases: &["vk", "vdisconnect"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::commands::logs_service;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
pub async fn handle_voicelog(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
logs_service::handle_log_toggle(ctx, msg, args, "voice", "VoiceLog").await;
|
||||
}
|
||||
|
||||
pub struct VoicelogCommand;
|
||||
pub static COMMAND_DESCRIPTOR: VoicelogCommand = VoicelogCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for VoicelogCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "voicelog",
|
||||
command: "voicelog",
|
||||
category: "admin",
|
||||
params: "<on [salon]|off>",
|
||||
summary: "Active les logs vocaux",
|
||||
description: "Active ou desactive les logs de l activite vocale.",
|
||||
examples: &["+voicelog on #logs", "+voicelog off"],
|
||||
alias_source_key: "voicelog",
|
||||
default_aliases: &["vlog"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
|
||||
use crate::commands::advanced_tools;
|
||||
|
||||
pub async fn handle_voicemove(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
advanced_tools::handle_voicemove(ctx, msg, args).await;
|
||||
}
|
||||
|
||||
pub struct VoiceMoveCommand;
|
||||
pub static COMMAND_DESCRIPTOR: VoiceMoveCommand = VoiceMoveCommand;
|
||||
|
||||
impl crate::commands::command_contract::CommandSpec for VoiceMoveCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "voicemove",
|
||||
command: "voicemove",
|
||||
category: "admin",
|
||||
params: "<salon_source> <salon_destination>",
|
||||
summary: "Deplace les membres vocaux",
|
||||
description: "Deplace tous les membres d'un salon vocal vers un autre salon.",
|
||||
examples: &["+voicemove #General #Event"],
|
||||
alias_source_key: "voicemove",
|
||||
default_aliases: &["vmove", "vmoveall"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use crate::commands::moderation_tools;
|
||||
use serenity::model::prelude::*;
|
||||
use serenity::prelude::*;
|
||||
pub async fn handle_warn(ctx: &Context, msg: &Message, args: &[&str]) {
|
||||
moderation_tools::handle_warn(ctx, msg, args).await;
|
||||
}
|
||||
pub struct WarnCommand;
|
||||
pub static COMMAND_DESCRIPTOR: WarnCommand = WarnCommand;
|
||||
impl crate::commands::command_contract::CommandSpec for WarnCommand {
|
||||
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
|
||||
crate::commands::command_contract::CommandMetadata {
|
||||
key: "warn",
|
||||
command: "warn",
|
||||
category: "admin",
|
||||
params: "<@membre/ID[,..]> [raison]",
|
||||
summary: "Donne un warn",
|
||||
description: "Ajoute un warn a un ou plusieurs membres.",
|
||||
examples: &["+warn @User spam"],
|
||||
alias_source_key: "warn",
|
||||
default_aliases: &["avert"],
|
||||
default_permission: 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user