feat: add feature: add admin, handling of the user has administrator perm, and start working on the function that the bot has
This commit is contained in:
parent
7524fe07e2
commit
f7fefb1ab6
@ -1,6 +1,7 @@
|
||||
use utoipa::OpenApi;
|
||||
|
||||
use crate::api::bot::info;
|
||||
use crate::db::{concour, server_config, user_image};
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
@ -18,6 +19,10 @@ use crate::api::bot::info;
|
||||
schemas(
|
||||
info::Info,
|
||||
info::InfoGuild,
|
||||
server_config::ServerConfig,
|
||||
user_image::User,
|
||||
concour::Concour,
|
||||
concour::ConcourStatus,
|
||||
)
|
||||
),
|
||||
paths(
|
||||
|
@ -27,16 +27,20 @@ pub async fn answer(
|
||||
if let Ok(answer) = answer {
|
||||
match answer {
|
||||
AnswerResult::Embed(embeds, attachments) => {
|
||||
let mut reply = CreateReply::default();
|
||||
reply.embeds = embeds;
|
||||
reply.attachments = attachments;
|
||||
let reply = CreateReply {
|
||||
embeds,
|
||||
attachments,
|
||||
..Default::default()
|
||||
};
|
||||
if let Err(why) = ctx.send(reply).await {
|
||||
tracing::error!("Error sending message: {:?}", why);
|
||||
}
|
||||
}
|
||||
AnswerResult::Animated(attachments) => {
|
||||
let mut reply = CreateReply::default();
|
||||
reply.attachments = attachments;
|
||||
let reply = CreateReply {
|
||||
attachments,
|
||||
..Default::default()
|
||||
};
|
||||
if let Err(why) = ctx.send(reply).await {
|
||||
tracing::error!("Error sending message: {:?}", why);
|
||||
}
|
||||
|
@ -30,13 +30,13 @@ pub async fn list(ctx: Context<'_>) -> Result<(), Error> {
|
||||
.fields(chunks.to_vec())
|
||||
.footer(footer)
|
||||
});
|
||||
let mut reply = CreateReply::default();
|
||||
reply.embeds = embed_vec.collect();
|
||||
let reply = CreateReply {
|
||||
embeds: embed_vec.collect(),
|
||||
..Default::default()
|
||||
};
|
||||
if let Err(why) = ctx.send(reply).await {
|
||||
tracing::error!("Error sending message: {:?}", why);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://github.com/serenity-rs/poise/blob/current/examples/fluent_localization/main.rs
|
||||
|
88
src/botv2/cmd/server_config/admin.rs
Normal file
88
src/botv2/cmd/server_config/admin.rs
Normal file
@ -0,0 +1,88 @@
|
||||
use crate::botv2::{
|
||||
domain::server_config::{
|
||||
admin_role::admin_role,
|
||||
check_if_server_enable_and_admin::check_if_server_enable_and_user_admin,
|
||||
},
|
||||
init::{Context, Error},
|
||||
};
|
||||
use poise::{
|
||||
serenity_prelude::{model::colour, CreateEmbed, CreateEmbedFooter, Role},
|
||||
CreateReply,
|
||||
};
|
||||
use tracing::instrument;
|
||||
|
||||
/// add/remove admin role
|
||||
#[instrument(skip(ctx), level = "info", fields(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get()))]
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
prefix_command,
|
||||
category = "server_config",
|
||||
guild_only = true
|
||||
)]
|
||||
pub async fn admin(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Add admin role"] add: Option<Role>,
|
||||
#[description = "Remove admin role"] remove: Option<Role>,
|
||||
) -> Result<(), Error> {
|
||||
let guild = match ctx.guild_id() {
|
||||
Some(guild) => guild,
|
||||
None => return Ok(()),
|
||||
};
|
||||
let entity_name = ctx.data().entity_name.clone();
|
||||
let footer = CreateEmbedFooter::new(entity_name.clone());
|
||||
match check_if_server_enable_and_user_admin(guild.get(), ctx.author().id.get(), ctx.http())
|
||||
.await
|
||||
{
|
||||
Ok((ok, _)) => {
|
||||
if !ok {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("You are not an admin")
|
||||
.color(colour::Color::RED)
|
||||
.footer(footer);
|
||||
if let Err(why) = ctx
|
||||
.send(CreateReply::default().embed(embed).ephemeral(true))
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error sending message: {:?}", why);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("You are not an admin")
|
||||
.color(colour::Color::RED)
|
||||
.footer(footer);
|
||||
if let Err(why) = ctx
|
||||
.send(CreateReply::default().embed(embed).ephemeral(true))
|
||||
.await
|
||||
{
|
||||
tracing::error!("Error sending message: {:?}", why);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let role_add = match add {
|
||||
Some(role) => Some(role.id.get()),
|
||||
None => None,
|
||||
};
|
||||
let role_remove = match remove {
|
||||
Some(role) => Some(role.id.get()),
|
||||
None => None,
|
||||
};
|
||||
let mut output = match admin_role(guild.get(), role_add, role_remove).await {
|
||||
Ok(_) => CreateEmbed::new()
|
||||
.title("Success handling admin role")
|
||||
.color(colour::Color::DARK_GREEN),
|
||||
Err(_) => CreateEmbed::new()
|
||||
.title("Error handling admin role")
|
||||
.color(colour::Color::RED),
|
||||
};
|
||||
output = output.footer(footer);
|
||||
let mut builder = CreateReply::default().ephemeral(true);
|
||||
builder = builder.embed(output);
|
||||
if let Err(why) = ctx.send(builder).await {
|
||||
tracing::error!("Error sending message: {:?}", why);
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
use crate::botv2::{
|
||||
domain::server_config::{
|
||||
change_enable_server::change_enable_server,
|
||||
check_if_server_enable_and_admin::check_if_server_enable_and_user_admin,
|
||||
enable_feature_auto_meme::enable_feature_meme,
|
||||
enable_feature_concour::enable_feature_concour,
|
||||
},
|
||||
init::{Context, Error},
|
||||
};
|
||||
@ -63,7 +64,7 @@ pub async fn feature(
|
||||
}
|
||||
};
|
||||
let answer_auto_meme = match auto_meme {
|
||||
Some(enable) => match change_enable_server(guild.get(), enable).await {
|
||||
Some(enable) => match enable_feature_meme(guild.get(), enable).await {
|
||||
Ok(_) => Some(
|
||||
CreateEmbed::new()
|
||||
.title(format!("Auto meme feature initialized: {}", enable))
|
||||
@ -78,7 +79,7 @@ pub async fn feature(
|
||||
None => None,
|
||||
};
|
||||
let answer_enable_concour = match concour {
|
||||
Some(enable) => match change_enable_server(guild.get(), enable).await {
|
||||
Some(enable) => match enable_feature_concour(guild.get(), enable).await {
|
||||
Ok(_) => Some(
|
||||
CreateEmbed::new()
|
||||
.title(format!("Concour feature initialized: {}", enable))
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod admin;
|
||||
pub mod feature;
|
||||
pub mod init_server;
|
||||
pub mod server;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::botv2::{
|
||||
cmd::server_config::{feature::feature, init_server::init},
|
||||
cmd::server_config::{admin::admin, feature::feature, init_server::init},
|
||||
domain::server_config::{
|
||||
check_if_server_enable_and_admin::check_if_server_enable_and_user_admin,
|
||||
get_server_config::get_server_config,
|
||||
@ -18,7 +18,7 @@ use tracing::instrument;
|
||||
slash_command,
|
||||
prefix_command,
|
||||
category = "server_config",
|
||||
subcommands("init", "info", "feature"),
|
||||
subcommands("init", "info", "feature", "admin"),
|
||||
guild_only = true
|
||||
)]
|
||||
pub async fn server(
|
||||
|
53
src/botv2/domain/concour/create_concour.rs
Normal file
53
src/botv2/domain/concour/create_concour.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{info, instrument};
|
||||
|
||||
use crate::db::concour::Concour;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum CreateConcourError {
|
||||
AlreadyExist,
|
||||
FindError(String),
|
||||
UnknownError(String),
|
||||
}
|
||||
|
||||
#[instrument(level = "info")]
|
||||
pub async fn create_concour(
|
||||
server_id: u64,
|
||||
channel_id: u64,
|
||||
title: String,
|
||||
description: String,
|
||||
) -> Result<Option<Concour>, CreateConcourError> {
|
||||
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
|
||||
Ok(list_concour) => list_concour,
|
||||
Err(err) => {
|
||||
tracing::error!(error = err.to_string(), "Error finding concour");
|
||||
return Err(CreateConcourError::UnknownError(
|
||||
"Error finding concour".to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if concour.is_some() {
|
||||
info!("Concour already exist");
|
||||
return Err(CreateConcourError::AlreadyExist);
|
||||
}
|
||||
|
||||
let concour = Concour {
|
||||
server_id,
|
||||
channel_id,
|
||||
title,
|
||||
description,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
match concour.create().await {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
tracing::error!(error = err.to_string(), "Error creating concour");
|
||||
return Err(CreateConcourError::UnknownError(
|
||||
"Error creating concour".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(Some(concour))
|
||||
}
|
28
src/botv2/domain/concour/get_channel_concour.rs
Normal file
28
src/botv2/domain/concour/get_channel_concour.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::db::concour::Concour;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum GetChannelConcourError {
|
||||
FindError(String),
|
||||
UnknownError(String),
|
||||
}
|
||||
|
||||
#[instrument(level = "info")]
|
||||
pub async fn get_channel_concour(
|
||||
server_id: u64,
|
||||
channel_id: u64,
|
||||
) -> Result<Option<Concour>, GetChannelConcourError> {
|
||||
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
|
||||
Ok(list_concour) => list_concour,
|
||||
Err(err) => {
|
||||
tracing::error!(error = err.to_string(), "Error finding concour");
|
||||
return Err(GetChannelConcourError::UnknownError(
|
||||
"Error finding concour".to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
Ok(concour)
|
||||
}
|
@ -1,2 +1,4 @@
|
||||
pub mod check_if_allowed;
|
||||
pub mod create_concour;
|
||||
pub mod get_channel_concour;
|
||||
pub mod list_concour;
|
||||
|
45
src/botv2/domain/server_config/admin_role.rs
Normal file
45
src/botv2/domain/server_config/admin_role.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use crate::db::server_config::ServerConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{info, instrument};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum AddAdminConfigError {
|
||||
UnknownError(String),
|
||||
}
|
||||
|
||||
#[instrument(level = "info")]
|
||||
pub async fn admin_role(
|
||||
server_id: u64,
|
||||
role_add_id: Option<u64>,
|
||||
role_remove_id: Option<u64>,
|
||||
) -> Result<(), AddAdminConfigError> {
|
||||
let server_config = match ServerConfig::find_by_server_id(&server_id).await {
|
||||
Ok(server_config) => server_config,
|
||||
Err(err) => {
|
||||
tracing::error!(error = err.to_string(), "Error finding server config");
|
||||
return Err(AddAdminConfigError::UnknownError(
|
||||
"Error finding server config".to_string(),
|
||||
));
|
||||
}
|
||||
};
|
||||
if let Some(mut config) = server_config {
|
||||
if let Some(role_id) = role_add_id {
|
||||
info!(id = role_id, "Adding role to admin role");
|
||||
config.admin_role.push(role_id);
|
||||
}
|
||||
if let Some(role_id) = role_remove_id {
|
||||
info!(id = role_id, "Remove role to admin role");
|
||||
config.admin_role.retain(|&x| x != role_id);
|
||||
}
|
||||
match config.update().await {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
tracing::error!(error = err.to_string(), "Error updating server config");
|
||||
return Err(AddAdminConfigError::UnknownError(
|
||||
"Error updating server config".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -34,6 +34,14 @@ pub async fn check_if_server_enable_and_user_admin(
|
||||
match guild.member(http, UserId::new(user_id)).await {
|
||||
Ok(member) => {
|
||||
info!("Checking if user is admin");
|
||||
if member
|
||||
.permissions
|
||||
.into_iter()
|
||||
.any(|perm| perm.administrator())
|
||||
{
|
||||
info!("User has administarator permission");
|
||||
return Ok((true, Some(server_config)));
|
||||
}
|
||||
Ok((
|
||||
server_config
|
||||
.clone()
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod admin_role;
|
||||
pub mod change_enable_server;
|
||||
pub mod check_if_server_enable;
|
||||
pub mod check_if_server_enable_and_admin;
|
||||
|
@ -19,7 +19,7 @@ pub async fn event_handler(
|
||||
serenity::FullEvent::Message { new_message } => {
|
||||
if new_message.author.bot
|
||||
|| new_message.content.starts_with(&data.config.prefix.clone())
|
||||
|| new_message.content.len() == 0
|
||||
|| new_message.content.is_empty()
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
@ -53,7 +53,7 @@ pub async fn event_handler(
|
||||
if !user_in_db.enable {
|
||||
return Ok(());
|
||||
}
|
||||
if config_img.keyword.len() == 0 || new_message.content.len() > 50 {
|
||||
if config_img.keyword.is_empty() || new_message.content.len() > 50 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ pub async fn start_bot(config: Config, rx: oneshot::Receiver<()>) -> Arc<Http> {
|
||||
.options(poise::FrameworkOptions {
|
||||
commands: vec![age(), ping(), help(), list(), enable(), answer(), server()],
|
||||
prefix_options: poise::PrefixFrameworkOptions {
|
||||
prefix: Some(prefix.into()),
|
||||
prefix: Some(prefix),
|
||||
..Default::default()
|
||||
},
|
||||
event_handler: |ctx, event, framework, data| {
|
||||
@ -78,7 +78,7 @@ pub async fn start_bot(config: Config, rx: oneshot::Receiver<()>) -> Arc<Http> {
|
||||
entity_name: format!(
|
||||
"{}-{}",
|
||||
config.bot_name.clone(),
|
||||
env!("CARGO_PKG_VERSION").to_string()
|
||||
env!("CARGO_PKG_VERSION")
|
||||
),
|
||||
})
|
||||
})
|
||||
|
@ -3,10 +3,11 @@ use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use surrealdb::opt::Resource;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
const CONCOUR: &str = "concour";
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub enum ConcourStatus {
|
||||
Created,
|
||||
Paused,
|
||||
@ -20,7 +21,7 @@ impl fmt::Display for ConcourStatus {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct Concour {
|
||||
pub server_id: u64,
|
||||
pub enable: bool,
|
||||
@ -37,12 +38,12 @@ pub struct Concour {
|
||||
pub winner: HashMap<String, (u64, chrono::DateTime<chrono::Utc>)>,
|
||||
}
|
||||
|
||||
impl Concour {
|
||||
pub fn new(server_id: u64, channel_id: u64, enable: bool) -> Result<Self, surrealdb::Error> {
|
||||
Ok(Self {
|
||||
server_id,
|
||||
enable,
|
||||
channel_id,
|
||||
impl Default for Concour {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
server_id: 0,
|
||||
enable: true,
|
||||
channel_id: 0,
|
||||
title: String::new(),
|
||||
description: String::new(),
|
||||
start_date: chrono::Utc::now(),
|
||||
@ -53,6 +54,26 @@ impl Concour {
|
||||
index_keyword: 0,
|
||||
status: ConcourStatus::Created,
|
||||
winner: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Concour {
|
||||
pub fn new(server_id: u64, channel_id: u64) -> Result<Self, surrealdb::Error> {
|
||||
Ok(Self {
|
||||
server_id,
|
||||
enable: true,
|
||||
channel_id,
|
||||
title: String::new(),
|
||||
description: String::new(),
|
||||
start_date: chrono::Utc::now(),
|
||||
periode: time::Duration::days(1),
|
||||
role_récompense: 0,
|
||||
keywords: Vec::new(),
|
||||
banner: None,
|
||||
index_keyword: 0,
|
||||
status: ConcourStatus::Created,
|
||||
winner: HashMap::new(),
|
||||
})
|
||||
}
|
||||
pub async fn create(&self) -> Result<(), surrealdb::Error> {
|
||||
|
@ -2,13 +2,14 @@ use super::init::DB;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use surrealdb::opt::Resource;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
const SERVER_CONFIG: &str = "server_config";
|
||||
const fn default_false() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct ServerConfig {
|
||||
#[serde(default = "default_false")]
|
||||
pub enable: bool,
|
||||
|
@ -1,11 +1,12 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use surrealdb::opt::Resource;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use super::init::DB;
|
||||
|
||||
const USERIMAGE: &str = "userimage";
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
pub struct User {
|
||||
pub server_id: u64,
|
||||
pub user_id: u64,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use poise::serenity_prelude::prelude::TypeMapKey;
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use poise::serenity_prelude::prelude::TypeMapKey;
|
||||
use std::fmt::Debug;
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
@ -18,18 +18,18 @@ impl KeyWordItem {
|
||||
})
|
||||
}
|
||||
pub fn output_folder_content(path: String) -> Vec<DirEntry> {
|
||||
let file_folder: Vec<DirEntry> = WalkDir::new(&path)
|
||||
let file_folder: Vec<DirEntry> = WalkDir::new(path)
|
||||
.into_iter()
|
||||
.filter_entry(|_e| true)
|
||||
.filter(|e| {
|
||||
if let Some(file) = &e.as_ref().ok() {
|
||||
return !file.metadata().unwrap().is_dir();
|
||||
}
|
||||
return true;
|
||||
true
|
||||
})
|
||||
.filter_map(|e| e.ok())
|
||||
.collect();
|
||||
if file_folder.len() == 0 {
|
||||
if file_folder.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
file_folder
|
||||
|
Loading…
Reference in New Issue
Block a user