chore(commands): reorganize command files by metadata categories

This commit is contained in:
Puechberty Arthur
2026-04-10 15:25:21 +02:00
parent 23dcc69977
commit 1b5e51c428
154 changed files with 399 additions and 399 deletions
+136
View File
@@ -0,0 +1,136 @@
use serenity::model::prelude::*;
use serenity::prelude::*;
use crate::commands::common::{add_list_fields, send_embed};
use crate::db::{
DbPoolKey, get_command_alias, list_command_aliases, remove_command_alias, set_command_alias,
};
use crate::permissions::all_command_keys;
pub async fn handle_alias(ctx: &Context, msg: &Message, args: &[&str]) {
let bot_id = ctx.cache.current_user().id;
let Some(pool) = pool(ctx).await else {
let embed = serenity::builder::CreateEmbed::new()
.title("Erreur")
.description("DB indisponible.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
if args.len() == 1 {
let aliases = list_command_aliases(&pool, bot_id)
.await
.unwrap_or_default();
let lines = aliases
.into_iter()
.map(|(alias, command)| format!("`{}` -> `{}`", alias, command))
.collect::<Vec<_>>();
let mut embed = serenity::builder::CreateEmbed::new()
.title("Aliases")
.color(0x5865F2);
embed = add_list_fields(embed, &lines, "Aliases enregistrés");
send_embed(ctx, msg, embed).await;
return;
}
if args.len() < 2 {
let embed = serenity::builder::CreateEmbed::new()
.title("Erreur")
.description("Usage: `+alias <commande> <alias>`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
if args[0].eq_ignore_ascii_case("remove") || args[0].eq_ignore_ascii_case("delete") {
let alias_name = args[1].trim_start_matches('+').to_lowercase();
if alias_name.is_empty() {
let embed = serenity::builder::CreateEmbed::new()
.title("Erreur")
.description("Alias invalide.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
let removed = remove_command_alias(&pool, bot_id, &alias_name)
.await
.unwrap_or(0);
let embed = serenity::builder::CreateEmbed::new()
.title("Alias supprimé")
.description(format!("`{}` : {} suppression(s).", alias_name, removed))
.color(0x57F287);
send_embed(ctx, msg, embed).await;
return;
}
let command = args[0].trim_start_matches('+').to_lowercase();
if !all_command_keys()
.iter()
.any(|candidate| candidate == &command)
{
let embed = serenity::builder::CreateEmbed::new()
.title("Erreur")
.description("Commande cible inconnue.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
let alias_name = args[1].trim_start_matches('+').to_lowercase();
if alias_name.is_empty() {
let embed = serenity::builder::CreateEmbed::new()
.title("Erreur")
.description("Alias invalide.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
let _ = set_command_alias(&pool, bot_id, &alias_name, &command).await;
let embed = serenity::builder::CreateEmbed::new()
.title("Alias créé")
.description(format!(
"`{}` devient un alias de `{}`",
alias_name, command
))
.color(0x57F287);
send_embed(ctx, msg, embed).await;
}
async fn pool(ctx: &Context) -> Option<sqlx::PgPool> {
let data = ctx.data.read().await;
data.get::<DbPoolKey>().cloned()
}
pub async fn resolve_alias(ctx: &Context, command: &str) -> Option<String> {
let bot_id = ctx.cache.current_user().id;
let pool = pool(ctx).await?;
get_command_alias(&pool, bot_id, command)
.await
.ok()
.flatten()
}
pub async fn resolve_command_alias_name(ctx: &Context, command: &str) -> Option<String> {
resolve_alias(ctx, command).await
}
pub struct AliasCommand;
pub static COMMAND_DESCRIPTOR: AliasCommand = AliasCommand;
impl crate::commands::command_contract::CommandSpec for AliasCommand {
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
crate::commands::command_contract::CommandMetadata {
name: "alias",
category: "perms",
params: "<commande> <alias> | remove <alias> | list",
description: "Liste, ajoute ou supprime des aliases de commandes stockes en base.",
examples: &["+alias", "+as", "+help alias"],
default_aliases: &["als"],
allow_in_dm: false,
default_permission: 6,
}
}
}
+137
View File
@@ -0,0 +1,137 @@
use serenity::builder::{CreateActionRow, CreateButton, CreateEmbed, CreateMessage};
use serenity::model::prelude::*;
use serenity::prelude::*;
use crate::commands::perms_helpers::ensure_owner;
use crate::commands::{common::theme_color, common::truncate_text};
use crate::permissions::{all_command_keys, command_required_permission, default_permission};
const ALLPERMS_PAGE_SIZE: usize = 12;
const ALLPERMS_CUSTOM_ID_PREFIX: &str = "allperms";
async fn collect_allperms_lines(ctx: &Context) -> Vec<String> {
let mut commands = all_command_keys();
if !commands.iter().any(|c| c == "allperms") {
commands.push("allperms".to_string());
}
commands.sort();
let mut lines = Vec::with_capacity(commands.len());
for cmd in commands {
let required = command_required_permission(ctx, &cmd).await;
let default = default_permission(&cmd);
if required == default {
lines.push(format!("`{}` -> `{}`", cmd, required));
} else {
lines.push(format!(
"`{}` -> `{}` (defaut `{}`)",
cmd, required, default
));
}
}
lines
}
fn total_pages_for(total_items: usize) -> usize {
((total_items + ALLPERMS_PAGE_SIZE.saturating_sub(1)) / ALLPERMS_PAGE_SIZE).max(1)
}
fn build_allperms_embed(lines: &[String], page: usize, color: u32) -> CreateEmbed {
let total_pages = total_pages_for(lines.len());
let safe_page = page.min(total_pages.saturating_sub(1));
let start = safe_page * ALLPERMS_PAGE_SIZE;
let end = (start + ALLPERMS_PAGE_SIZE).min(lines.len());
let chunk = if start < end { &lines[start..end] } else { &[] };
let value = if chunk.is_empty() {
"Aucune commande.".to_string()
} else {
truncate_text(&chunk.join("\n"), 1024)
};
CreateEmbed::new()
.title("Permissions de toutes les commandes")
.description(format!(
"{} commande(s) · Page {}/{}",
lines.len(),
safe_page + 1,
total_pages
))
.field("Niveaux requis", value, false)
.color(color)
}
fn allperms_components(owner_id: UserId, page: usize, total_pages: usize) -> Vec<CreateActionRow> {
let safe_total = total_pages.max(1);
let safe_page = page.min(safe_total.saturating_sub(1));
let prev_page = safe_page.saturating_sub(1);
let next_page = (safe_page + 1).min(safe_total.saturating_sub(1));
vec![CreateActionRow::Buttons(vec![
CreateButton::new(format!(
"{}:{}:{}",
ALLPERMS_CUSTOM_ID_PREFIX,
owner_id.get(),
prev_page
))
.label("◀ Precedent")
.style(ButtonStyle::Primary)
.disabled(safe_page == 0),
CreateButton::new(format!(
"{}:{}:{}",
ALLPERMS_CUSTOM_ID_PREFIX,
owner_id.get(),
next_page
))
.label("Suivant ▶")
.style(ButtonStyle::Primary)
.disabled(safe_page + 1 >= safe_total),
])]
}
pub async fn handle_allperms(ctx: &Context, msg: &Message, args: &[&str]) {
if !ensure_owner(ctx, msg).await {
return;
}
let lines = collect_allperms_lines(ctx).await;
let total_pages = total_pages_for(lines.len());
let requested_page = args
.first()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(1)
.saturating_sub(1);
let page = requested_page.min(total_pages.saturating_sub(1));
let color = theme_color(ctx).await;
let embed = build_allperms_embed(&lines, page, color);
let components = allperms_components(msg.author.id, page, total_pages);
let _ = msg
.channel_id
.send_message(
&ctx.http,
CreateMessage::new().embed(embed).components(components),
)
.await;
}
pub struct AllpermsCommand;
pub static COMMAND_DESCRIPTOR: AllpermsCommand = AllpermsCommand;
impl crate::commands::command_contract::CommandSpec for AllpermsCommand {
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
crate::commands::command_contract::CommandMetadata {
name: "allperms",
category: "perms",
params: "[page]",
description: "Affiche le niveau ACL requis pour chaque commande avec pagination.",
examples: &["+allperms", "+as", "+help allperms"],
default_aliases: &["apm"],
allow_in_dm: false,
default_permission: 7,
}
}
}
+48
View File
@@ -0,0 +1,48 @@
use serenity::builder::CreateEmbed;
use serenity::model::prelude::*;
use serenity::prelude::*;
use crate::commands::common::send_embed;
use crate::commands::perms_helpers::{ensure_owner, get_pool};
use crate::db::clear_role_permissions;
pub async fn handle_clear_perms(ctx: &Context, msg: &Message) {
if !ensure_owner(ctx, msg).await {
return;
}
let bot_id = ctx.cache.current_user().id;
let Some(pool) = get_pool(ctx).await else {
let embed = CreateEmbed::new()
.title("Erreur")
.description("DB indisponible.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
let removed = clear_role_permissions(&pool, bot_id).await.unwrap_or(0);
let embed = CreateEmbed::new()
.title("Permissions roles supprimees")
.description(format!("{} entree(s) supprimee(s).", removed))
.color(0x57F287);
send_embed(ctx, msg, embed).await;
}
pub struct ClearPermsCommand;
pub static COMMAND_DESCRIPTOR: ClearPermsCommand = ClearPermsCommand;
impl crate::commands::command_contract::CommandSpec for ClearPermsCommand {
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
crate::commands::command_contract::CommandMetadata {
name: "clear_perms",
category: "perms",
params: "aucun",
description: "Supprime toutes les permissions ACL configurees en base.",
examples: &["+clear perms", "+cs", "+help clear perms"],
default_aliases: &["cpm"],
allow_in_dm: false,
default_permission: 9,
}
}
}
+69
View File
@@ -0,0 +1,69 @@
use serenity::builder::CreateEmbed;
use serenity::model::prelude::*;
use serenity::prelude::*;
use crate::commands::common::send_embed;
use crate::commands::perms_helpers::{ensure_owner, get_pool, parse_user_or_role};
use crate::db::remove_scope_permissions;
pub async fn handle_del(ctx: &Context, msg: &Message, args: &[&str]) {
if !ensure_owner(ctx, msg).await {
return;
}
if args.len() < 2 || !args[0].eq_ignore_ascii_case("perm") {
let embed = CreateEmbed::new()
.title("Erreur")
.description("Usage: `del perm <role>`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
let Some((scope_type, scope_id)) = parse_user_or_role(args[1]) else {
let embed = CreateEmbed::new()
.title("Erreur")
.description("Role/membre invalide.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
let bot_id = ctx.cache.current_user().id;
let Some(pool) = get_pool(ctx).await else {
let embed = CreateEmbed::new()
.title("Erreur")
.description("DB indisponible.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
let removed = remove_scope_permissions(&pool, bot_id, scope_type, scope_id)
.await
.unwrap_or(0);
let embed = CreateEmbed::new()
.title("Permissions supprimees")
.description(format!("{} entree(s) supprimee(s).", removed))
.color(0x57F287);
send_embed(ctx, msg, embed).await;
}
pub struct DelCommand;
pub static COMMAND_DESCRIPTOR: DelCommand = DelCommand;
impl crate::commands::command_contract::CommandSpec for DelCommand {
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
crate::commands::command_contract::CommandMetadata {
name: "del",
category: "perms",
params: "perm <@&rôle/@membre/ID>",
description: "Supprime les permissions ACL associees a un role ou utilisateur.",
examples: &["+del", "+dl", "+help del"],
default_aliases: &["dlp"],
allow_in_dm: false,
default_permission: 7,
}
}
}
File diff suppressed because it is too large Load Diff
+80
View File
@@ -0,0 +1,80 @@
use serenity::model::prelude::*;
use serenity::prelude::*;
use crate::commands::common::send_embed;
use crate::db::{DbPoolKey, get_help_aliases_enabled, set_help_aliases_enabled};
pub async fn handle_helpalias(ctx: &Context, msg: &Message, args: &[&str]) {
let bot_id = ctx.cache.current_user().id;
let Some(pool) = pool(ctx).await 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 enabled = get_help_aliases_enabled(&pool, bot_id)
.await
.ok()
.flatten()
.unwrap_or(true);
let embed = serenity::builder::CreateEmbed::new()
.title("Aliases dans help")
.description(format!(
"État actuel: `{}`",
if enabled { "on" } else { "off" }
))
.color(0x5865F2);
send_embed(ctx, msg, embed).await;
return;
}
let enabled = match args[0].to_lowercase().as_str() {
"on" | "true" | "yes" => true,
"off" | "false" | "no" => false,
_ => {
let embed = serenity::builder::CreateEmbed::new()
.title("Erreur")
.description("Usage: `+helpalias <on/off>`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
};
let _ = set_help_aliases_enabled(&pool, bot_id, enabled).await;
let embed = serenity::builder::CreateEmbed::new()
.title("Help aliases mis à jour")
.description(format!(
"Aliases dans l'aide: `{}`",
if enabled { "on" } else { "off" }
))
.color(0x57F287);
send_embed(ctx, msg, embed).await;
}
async fn pool(ctx: &Context) -> Option<sqlx::PgPool> {
let data = ctx.data.read().await;
data.get::<DbPoolKey>().cloned()
}
pub struct HelpaliasCommand;
pub static COMMAND_DESCRIPTOR: HelpaliasCommand = HelpaliasCommand;
impl crate::commands::command_contract::CommandSpec for HelpaliasCommand {
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
crate::commands::command_contract::CommandMetadata {
name: "helpalias",
category: "perms",
params: "<on|off>",
description: "Active ou desactive laffichage des aliases dans laide.",
examples: &["+helpalias", "+hs", "+help helpalias"],
default_aliases: &["hal"],
allow_in_dm: true,
default_permission: 0,
}
}
}
+412
View File
@@ -0,0 +1,412 @@
use serenity::builder::{
CreateActionRow, CreateButton, CreateEmbed, CreateInteractionResponse,
CreateInteractionResponseMessage, CreateMessage, CreateSelectMenu, CreateSelectMenuKind,
CreateSelectMenuOption,
};
use serenity::model::application::ComponentInteractionDataKind;
use serenity::model::prelude::*;
use serenity::prelude::*;
use crate::commands::common::send_embed;
use crate::db::{
DbPoolKey, get_help_aliases_enabled, get_help_perms_enabled, get_help_type,
set_help_aliases_enabled, set_help_perms_enabled, set_help_type,
};
#[derive(Clone)]
struct HelpSettingsData {
layout: String,
aliases_enabled: bool,
perms_enabled: bool,
}
fn normalize_layout(value: &str) -> Option<&'static str> {
match value.to_lowercase().as_str() {
"button" => Some("button"),
"select" => Some("select"),
"hybrid" => Some("hybrid"),
_ => None,
}
}
fn owner_id_from_custom_id(custom_id: &str) -> Option<u64> {
custom_id.rsplit(':').next()?.parse::<u64>().ok()
}
fn mode_from_custom_id(custom_id: &str) -> Option<&str> {
let parts = custom_id.split(':').collect::<Vec<_>>();
if parts.len() != 4 || parts[0] != "helpsetting" || parts[1] != "setmode" {
return None;
}
Some(parts[2])
}
async fn pool(ctx: &Context) -> Option<sqlx::PgPool> {
let data = ctx.data.read().await;
data.get::<DbPoolKey>().cloned()
}
async fn read_settings(pool: &sqlx::PgPool, bot_id: UserId) -> HelpSettingsData {
let layout = get_help_type(pool, bot_id)
.await
.ok()
.flatten()
.unwrap_or_else(|| "button".to_string());
let aliases_enabled = get_help_aliases_enabled(pool, bot_id)
.await
.ok()
.flatten()
.unwrap_or(true);
let perms_enabled = get_help_perms_enabled(pool, bot_id)
.await
.ok()
.flatten()
.unwrap_or(true);
HelpSettingsData {
layout,
aliases_enabled,
perms_enabled,
}
}
fn build_embed(settings: &HelpSettingsData) -> CreateEmbed {
CreateEmbed::new()
.title("Configuration de l'aide")
.description("Tu peux modifier ces paramètres via boutons ou menu select.")
.field("Mode d'affichage", format!("`{}`", settings.layout), true)
.field(
"Aliases",
format!(
"`{}`",
if settings.aliases_enabled {
"on"
} else {
"off"
}
),
true,
)
.field(
"Permissions",
format!("`{}`", if settings.perms_enabled { "on" } else { "off" }),
true,
)
.color(0x5865F2)
}
fn build_components(owner_id: UserId, settings: &HelpSettingsData) -> Vec<CreateActionRow> {
let mode_button_style = if settings.layout == "button" {
ButtonStyle::Success
} else {
ButtonStyle::Secondary
};
let mode_select_style = if settings.layout == "select" {
ButtonStyle::Success
} else {
ButtonStyle::Secondary
};
let mode_hybrid_style = if settings.layout == "hybrid" {
ButtonStyle::Success
} else {
ButtonStyle::Secondary
};
let aliases_style = if settings.aliases_enabled {
ButtonStyle::Success
} else {
ButtonStyle::Danger
};
let perms_style = if settings.perms_enabled {
ButtonStyle::Success
} else {
ButtonStyle::Danger
};
let mode_row = CreateActionRow::Buttons(vec![
CreateButton::new(format!("helpsetting:setmode:button:{}", owner_id.get()))
.label("Mode Button")
.style(mode_button_style),
CreateButton::new(format!("helpsetting:setmode:select:{}", owner_id.get()))
.label("Mode Select")
.style(mode_select_style),
CreateButton::new(format!("helpsetting:setmode:hybrid:{}", owner_id.get()))
.label("Mode Hybrid")
.style(mode_hybrid_style),
]);
let toggle_row = CreateActionRow::Buttons(vec![
CreateButton::new(format!("helpsetting:toggle:aliases:{}", owner_id.get()))
.label(if settings.aliases_enabled {
"Aliases: on"
} else {
"Aliases: off"
})
.style(aliases_style),
CreateButton::new(format!("helpsetting:toggle:perms:{}", owner_id.get()))
.label(if settings.perms_enabled {
"Perms: on"
} else {
"Perms: off"
})
.style(perms_style),
CreateButton::new(format!("helpsetting:refresh:{}", owner_id.get()))
.label("Rafraîchir")
.style(ButtonStyle::Primary),
]);
let quick_options = vec![
CreateSelectMenuOption::new("Mode button", "mode:button"),
CreateSelectMenuOption::new("Mode select", "mode:select"),
CreateSelectMenuOption::new("Mode hybrid", "mode:hybrid"),
CreateSelectMenuOption::new("Aliases on", "aliases:on"),
CreateSelectMenuOption::new("Aliases off", "aliases:off"),
CreateSelectMenuOption::new("Perms on", "perms:on"),
CreateSelectMenuOption::new("Perms off", "perms:off"),
];
let quick_menu = CreateSelectMenu::new(
format!("helpsetting:quick:{}", owner_id.get()),
CreateSelectMenuKind::String {
options: quick_options,
},
)
.placeholder("Action rapide (select)");
vec![
mode_row,
toggle_row,
CreateActionRow::SelectMenu(quick_menu),
]
}
async fn send_settings_panel(
ctx: &Context,
msg: &Message,
pool: &sqlx::PgPool,
bot_id: UserId,
owner_id: UserId,
) {
let settings = read_settings(pool, bot_id).await;
let embed = build_embed(&settings);
let components = build_components(owner_id, &settings);
let _ = msg
.channel_id
.send_message(
&ctx.http,
CreateMessage::new().embed(embed).components(components),
)
.await;
}
async fn apply_quick_action(pool: &sqlx::PgPool, bot_id: UserId, action: &str) {
match action {
"mode:button" => {
let _ = set_help_type(pool, bot_id, "button").await;
}
"mode:select" => {
let _ = set_help_type(pool, bot_id, "select").await;
}
"mode:hybrid" => {
let _ = set_help_type(pool, bot_id, "hybrid").await;
}
"aliases:on" => {
let _ = set_help_aliases_enabled(pool, bot_id, true).await;
}
"aliases:off" => {
let _ = set_help_aliases_enabled(pool, bot_id, false).await;
}
"perms:on" => {
let _ = set_help_perms_enabled(pool, bot_id, true).await;
}
"perms:off" => {
let _ = set_help_perms_enabled(pool, bot_id, false).await;
}
_ => {}
}
}
pub async fn handle_component_interaction(ctx: &Context, component: &ComponentInteraction) -> bool {
let custom_id = &component.data.custom_id;
if !custom_id.starts_with("helpsetting:") {
return false;
}
let Some(owner_id) = owner_id_from_custom_id(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 de la commande peut utiliser ces contrôles.")
.ephemeral(true),
),
)
.await;
return true;
}
let bot_id = ctx.cache.current_user().id;
let Some(pool) = pool(ctx).await else {
let _ = component
.create_response(
&ctx.http,
CreateInteractionResponse::Message(
CreateInteractionResponseMessage::new()
.content("DB indisponible.")
.ephemeral(true),
),
)
.await;
return true;
};
if custom_id.starts_with("helpsetting:setmode:") {
if let Some(mode) = mode_from_custom_id(custom_id).and_then(normalize_layout) {
let _ = set_help_type(&pool, bot_id, mode).await;
}
} else if custom_id.starts_with("helpsetting:toggle:aliases:") {
let settings = read_settings(&pool, bot_id).await;
let _ = set_help_aliases_enabled(&pool, bot_id, !settings.aliases_enabled).await;
} else if custom_id.starts_with("helpsetting:toggle:perms:") {
let settings = read_settings(&pool, bot_id).await;
let _ = set_help_perms_enabled(&pool, bot_id, !settings.perms_enabled).await;
} else if custom_id.starts_with("helpsetting:quick:") {
if let ComponentInteractionDataKind::StringSelect { values } = &component.data.kind {
if let Some(action) = values.first() {
apply_quick_action(&pool, bot_id, action).await;
}
}
}
let settings = read_settings(&pool, bot_id).await;
let embed = build_embed(&settings);
let components = build_components(component.user.id, &settings);
let _ = component
.create_response(
&ctx.http,
CreateInteractionResponse::UpdateMessage(
CreateInteractionResponseMessage::new()
.embed(embed)
.components(components),
),
)
.await;
true
}
pub async fn handle_helpsetting(ctx: &Context, msg: &Message, args: &[&str]) {
let bot_id = ctx.cache.current_user().id;
let Some(pool) = pool(ctx).await else {
let embed = CreateEmbed::new()
.title("Erreur")
.description("DB indisponible.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
if args.is_empty() {
send_settings_panel(ctx, msg, &pool, bot_id, msg.author.id).await;
return;
}
match args[0].to_lowercase().as_str() {
"type" | "mode" => {
let Some(value) = args.get(1).and_then(|value| normalize_layout(value)) else {
let embed = CreateEmbed::new()
.title("Erreur")
.description("Usage: `+helpsetting type <button|select|hybrid>`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
let _ = set_help_type(&pool, bot_id, value).await;
send_settings_panel(ctx, msg, &pool, bot_id, msg.author.id).await;
}
"aliases" | "alias" => {
let Some(value) = args.get(1) else {
let embed = CreateEmbed::new()
.title("Erreur")
.description("Usage: `+helpsetting aliases <on|off>`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
let enabled = match value.to_lowercase().as_str() {
"on" | "true" | "yes" => true,
"off" | "false" | "no" => false,
_ => {
let embed = CreateEmbed::new()
.title("Erreur")
.description("Valeurs valides: `on`, `off`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
};
let _ = set_help_aliases_enabled(&pool, bot_id, enabled).await;
send_settings_panel(ctx, msg, &pool, bot_id, msg.author.id).await;
}
"perms" | "permissions" => {
let Some(value) = args.get(1) else {
let embed = CreateEmbed::new()
.title("Erreur")
.description("Usage: `+helpsetting perms <on|off>`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
let enabled = match value.to_lowercase().as_str() {
"on" | "true" | "yes" => true,
"off" | "false" | "no" => false,
_ => {
let embed = CreateEmbed::new()
.title("Erreur")
.description("Valeurs valides: `on`, `off`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
};
let _ = set_help_perms_enabled(&pool, bot_id, enabled).await;
send_settings_panel(ctx, msg, &pool, bot_id, msg.author.id).await;
}
_ => {
let embed = CreateEmbed::new()
.title("Erreur")
.description("Sous-commandes: `type`, `aliases`, `perms`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
}
}
}
pub struct HelpsettingCommand;
pub static COMMAND_DESCRIPTOR: HelpsettingCommand = HelpsettingCommand;
impl crate::commands::command_contract::CommandSpec for HelpsettingCommand {
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
crate::commands::command_contract::CommandMetadata {
name: "helpsetting",
category: "perms",
params: "[type|aliases|perms] [value]",
description: "Permet de configurer le mode d'affichage, l'affichage des alias et l'affichage des permissions du système d'aide.",
examples: &[
"+helpsetting",
"+helpsetting type hybrid",
"+helpsetting perms off",
],
default_aliases: &["hs", "helpetting"],
allow_in_dm: false,
default_permission: 6,
}
}
}
+77
View File
@@ -0,0 +1,77 @@
use serenity::model::prelude::*;
use serenity::prelude::*;
use crate::commands::common::send_embed;
use crate::db::{DbPoolKey, get_help_type, set_help_type};
pub async fn handle_helptype(ctx: &Context, msg: &Message, args: &[&str]) {
let bot_id = ctx.cache.current_user().id;
let Some(pool) = pool(ctx).await 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 current = get_help_type(&pool, bot_id)
.await
.ok()
.flatten()
.unwrap_or_else(|| "button".to_string());
let embed = serenity::builder::CreateEmbed::new()
.title("Mode help")
.description(format!(
"Mode actuel: `{}`\nValeurs: `button`, `select`, `hybrid`",
current
))
.color(0x5865F2);
send_embed(ctx, msg, embed).await;
return;
}
let normalized = match args[0].to_lowercase().as_str() {
"button" => "button",
"select" => "select",
"hybrid" => "hybrid",
_ => {
let embed = serenity::builder::CreateEmbed::new()
.title("Erreur")
.description("Usage: `+helptype <button/select/hybrid>`")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
}
};
let _ = set_help_type(&pool, bot_id, normalized).await;
let embed = serenity::builder::CreateEmbed::new()
.title("Mode help mis à jour")
.description(format!("Nouveau mode: `{}`", normalized))
.color(0x57F287);
send_embed(ctx, msg, embed).await;
}
async fn pool(ctx: &Context) -> Option<sqlx::PgPool> {
let data = ctx.data.read().await;
data.get::<DbPoolKey>().cloned()
}
pub struct HelptypeCommand;
pub static COMMAND_DESCRIPTOR: HelptypeCommand = HelptypeCommand;
impl crate::commands::command_contract::CommandSpec for HelptypeCommand {
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
crate::commands::command_contract::CommandMetadata {
name: "helptype",
category: "perms",
params: "<button|select|hybrid>",
description: "Definit le mode daffichage de laide entre button, select et hybrid.",
examples: &["+helptype", "+he", "+help helptype"],
default_aliases: &["htp"],
allow_in_dm: true,
default_permission: 0,
}
}
}
+80
View File
@@ -0,0 +1,80 @@
use serenity::builder::CreateEmbed;
use serenity::model::prelude::*;
use serenity::prelude::*;
use crate::commands::common::{add_list_fields, send_embed, truncate_text};
use crate::commands::perms_helpers::{ensure_owner, get_pool};
use crate::db::{list_role_command_access, list_role_perm_levels, list_role_scopes};
pub async fn handle_perms(ctx: &Context, msg: &Message, args: &[&str]) {
let _ = args;
if !ensure_owner(ctx, msg).await {
return;
}
let bot_id = ctx.cache.current_user().id;
let Some(pool) = get_pool(ctx).await else {
let embed = CreateEmbed::new()
.title("Erreur")
.description("DB indisponible.")
.color(0xED4245);
send_embed(ctx, msg, embed).await;
return;
};
let roles = list_role_scopes(&pool, bot_id).await.unwrap_or_default();
let mut lines = Vec::new();
for rid in roles {
let perm_levels = list_role_perm_levels(&pool, bot_id, rid as u64)
.await
.unwrap_or_default();
let command_access = list_role_command_access(&pool, bot_id, rid as u64)
.await
.unwrap_or_default();
let perms = if perm_levels.is_empty() {
"aucun".to_string()
} else {
perm_levels
.iter()
.map(|p| p.to_string())
.collect::<Vec<_>>()
.join(",")
};
let commands = if command_access.is_empty() {
"aucune".to_string()
} else {
truncate_text(&command_access.join(", "), 80)
};
lines.push(format!(
"<@&{}> · perms [{}] · cmd [{}]",
rid, perms, commands
));
}
let mut embed = CreateEmbed::new().title("Permissions du bot");
embed = add_list_fields(embed, &lines, "Roles configures");
send_embed(ctx, msg, embed).await;
}
pub struct PermsCommand;
pub static COMMAND_DESCRIPTOR: PermsCommand = PermsCommand;
impl crate::commands::command_contract::CommandSpec for PermsCommand {
fn metadata(&self) -> crate::commands::command_contract::CommandMetadata {
crate::commands::command_contract::CommandMetadata {
name: "perms",
category: "perms",
params: "aucun",
description: "Affiche les permissions ACL configurees par role ou scope.",
examples: &["+perms", "+ps", "+help perms"],
default_aliases: &["prm"],
allow_in_dm: false,
default_permission: 6,
}
}
}