feat: Mise en place server_config et debut de concour

This commit is contained in:
Max batleforc 2024-06-20 00:27:31 +02:00
parent c8cc1dd39a
commit f043c99a4d
No known key found for this signature in database
GPG Key ID: 25D243AB4B6AC9E7
25 changed files with 898 additions and 15 deletions

View File

@ -8,7 +8,9 @@ Main lib used : [serenity-rs/serenity](https://github.com/serenity-rs/serenity)
## Feature expected
- ImageWareHouse (like TestDiscord)
- [DONE] ImageWareHouse (like TestDiscord)
- ImageWareHouse V2
- Mise en place d'autre source de gif OPT
- SoundBoard (like UnlabeledBot)
- Notification (read an event topic and send the message to the expected chan)
- Some Administration command
@ -20,13 +22,12 @@ Main lib used : [serenity-rs/serenity](https://github.com/serenity-rs/serenity)
- Have a web interface to manage the bot (like a dashboard)
- List of server
- Monitor the bot
- Integrate with the Opentelemetry project
- Authentification Discord
- Detecter controle
- [WIP] Integrate with the Opentelemetry project
- The bot has to be able to be deployed on a k8s cluster
- The bot has to be OPT-IN (the user has to enable the bot on his server with a command)
## Important to do
- Migrate to Trace
- Mise en place de metric OpenTelemetry
## previous project

View File

View File

@ -1,10 +1,10 @@
use crate::botv2::init::{Context, Error};
use poise::samples::HelpConfiguration;
use tracing::instrument;
use crate::botv2::init::{Context,Error};
/// Show help message
#[poise::command(prefix_command, track_edits, category = "Utility")]
#[instrument(skip(ctx),level="info")]
#[instrument(skip(ctx), level = "info")]
pub async fn help(
ctx: Context<'_>,
#[description = "Command to get help for"]
@ -22,7 +22,7 @@ pub async fn help(
};
}
let extra_text_at_bottom = "\
Provided by Batleforc with love and too much coffee ";
Provided by Batleforc with and too much ";
let config = HelpConfiguration {
show_subcommands: true,

View File

@ -5,6 +5,7 @@ use crate::botv2::{
use poise::CreateReply;
use tracing::instrument;
/// Answer keyword with a meme if it match a registered keyword
#[instrument(skip(ctx), level = "info", fields(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get()))]
#[poise::command(slash_command, prefix_command, category = "meme")]
pub async fn answer(

View File

@ -1,3 +1,5 @@
pub mod ping;
pub mod concour;
pub mod help;
pub mod meme;
pub mod ping;
pub mod server_config;

View File

@ -0,0 +1,81 @@
use crate::botv2::{
domain::server_config::change_enable_server::change_enable_server,
init::{Context, Error},
};
use poise::{
serenity_prelude::{model::colour, CreateEmbed, CreateEmbedFooter},
CreateReply,
};
use tracing::instrument;
/// Enable/Disable feature
#[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 feature(
ctx: Context<'_>,
#[description = "Enable/Disable the auto_meme feature"] auto_meme: Option<bool>,
#[description = "Enable/Disable the concour feature"] concour: Option<bool>,
) -> 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());
let answer_auto_meme = match auto_meme {
Some(enable) => match change_enable_server(guild.get(), enable).await {
Ok(_) => Some(
CreateEmbed::new()
.title(format!("Auto meme feature initialized: {}", enable))
.color(colour::Color::DARK_GREEN),
),
Err(_) => Some(
CreateEmbed::new()
.title("Error initializing auto meme feature")
.color(colour::Color::RED),
),
},
None => None,
};
let answer_enable_concour = match concour {
Some(enable) => match change_enable_server(guild.get(), enable).await {
Ok(_) => Some(
CreateEmbed::new()
.title(format!("Concour feature initialized: {}", enable))
.color(colour::Color::DARK_GREEN),
),
Err(_) => Some(
CreateEmbed::new()
.title("Error initializing concour feature")
.color(colour::Color::RED),
),
},
None => None,
};
let mut builder = CreateReply::default().ephemeral(true);
if answer_auto_meme.is_none() && answer_enable_concour.is_none() {
builder = builder.embed(
CreateEmbed::new()
.title("No feature initialized")
.color(colour::Color::RED)
.footer(footer.clone()),
);
}
if let Some(embed) = answer_auto_meme {
builder = builder.embed(embed.footer(footer.clone()));
}
if let Some(embed) = answer_enable_concour {
builder = builder.embed(embed.footer(footer));
}
if let Err(why) = ctx.send(builder).await {
tracing::error!("Error sending message: {:?}", why);
}
Ok(())
}

View File

@ -0,0 +1,46 @@
use crate::botv2::{
domain::server_config::change_enable_server::change_enable_server,
init::{Context, Error},
};
use poise::{
serenity_prelude::{model::colour, CreateEmbed, CreateEmbedFooter},
CreateReply,
};
use tracing::instrument;
/// Initialize server config
#[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,
owners_only = true
)]
pub async fn init(
ctx: Context<'_>,
#[description = "Enable the bot to answer to the server"] enable: bool,
) -> Result<(), Error> {
let guild = match ctx.guild_id() {
Some(guild) => guild,
None => return Ok(()),
};
ctx.author_member().await.unwrap();
let entity_name = ctx.data().entity_name.clone();
let footer = CreateEmbedFooter::new(entity_name.clone());
let answer = match change_enable_server(guild.get(), enable).await {
Ok(_) => CreateEmbed::new()
.title("Server config initialized")
.color(colour::Color::DARK_GREEN),
Err(_) => CreateEmbed::new()
.title("Error initializing server config")
.color(colour::Color::RED),
};
let builder = CreateReply::default()
.embed(answer.footer(footer))
.ephemeral(true);
if let Err(why) = ctx.send(builder).await {
tracing::error!("Error sending message: {:?}", why);
}
Ok(())
}

View File

@ -0,0 +1,3 @@
pub mod feature;
pub mod init_server;
pub mod server;

View File

@ -0,0 +1,104 @@
use crate::botv2::{
cmd::server_config::{feature::feature, init_server::init},
domain::server_config::get_server_config::get_server_config,
init::{Context, Error},
};
use poise::{
serenity_prelude::{model::colour, CreateEmbed, CreateEmbedFooter, RoleId},
CreateReply,
};
use tracing::instrument;
/// Show server config (alias of info)
#[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",
subcommands("init", "info", "feature"),
guild_only = true
)]
pub async fn server(
ctx: Context<'_>,
#[description = "Reponse cacher ?"] ephemeral: Option<bool>,
) -> Result<(), Error> {
server_info(ctx, ephemeral).await
}
/// Show server config
#[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 info(
ctx: Context<'_>,
#[description = "Reponse cacher ?"] ephemeral: Option<bool>,
) -> Result<(), Error> {
server_info(ctx, ephemeral).await
}
#[instrument(skip(ctx), level = "info")]
async fn server_info(ctx: Context<'_>, ephemeral: Option<bool>) -> 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());
let answer = match get_server_config(guild.get()).await {
Ok(config) => match config {
Some(server_config) => {
let mut embed = CreateEmbed::new()
.title(format!(
"Server config found: {}",
ctx.guild().unwrap().name
))
.field("Enabled", server_config.enable.to_string(), true)
.field(
"Feature Auto_meme",
server_config.auto_meme.to_string(),
true,
)
.field(
"Feature Concour",
server_config.auto_concour.to_string(),
true,
)
.color(colour::Color::DARK_GREEN);
let role_list: Vec<String> = server_config
.admin_role
.iter()
.map(|role_id| {
ctx.guild().unwrap().roles[&RoleId::new(*role_id)]
.name
.clone()
})
.collect();
if !role_list.is_empty() {
embed = embed.field("Admin role", role_list.join(", "), false);
} else {
embed = embed.field("Admin role", "No role found", false);
}
embed
}
None => CreateEmbed::new()
.title("Server config not found")
.color(colour::Color::RED),
},
Err(_) => CreateEmbed::new()
.title("Error fetching server config")
.color(colour::Color::RED),
};
let mut builder = CreateReply::default().embed(answer.footer(footer));
if ephemeral.unwrap_or(true) {
builder = builder.ephemeral(true);
}
if let Err(why) = ctx.send(builder).await {
tracing::error!("Error sending message: {:?}", why);
}
Ok(())
}

View File

@ -0,0 +1,57 @@
use poise::serenity_prelude;
use serde::{Deserialize, Serialize};
use tracing::instrument;
use crate::{
botv2::domain::server_config::{
check_if_server_enable::check_if_server_enable,
check_if_server_enable_and_admin::check_if_server_enable_and_user_admin,
},
db::server_config::ServerConfig,
};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum CheckIfConcourEnable {
UnknownError(String),
}
// Check :
// - if the user is admin or owner of the server
// - if the server enabled the concour feature
// - if the user has a role allowed to handle concour
/// Check if the concour is allowed on the server
#[instrument(level = "info")]
pub async fn check_if_concour_allowed(
server_id: u64,
) -> Result<(bool, Option<ServerConfig>), CheckIfConcourEnable> {
if let Ok((enable, server_config)) = check_if_server_enable(server_id).await {
if !enable {
return Ok((false, None));
}
if let Some(server_config) = server_config {
return Ok((server_config.auto_concour, Some(server_config)));
}
}
Ok((false, None))
}
/// Check if the concour is allowed on the server and if the user has a role allowed to handle concour
#[instrument(level = "info", skip(http))]
pub async fn check_if_allowed(
server_id: u64,
user_id: u64,
http: serenity_prelude::Http,
) -> Result<bool, CheckIfConcourEnable> {
if let Ok((enable, server_config)) =
check_if_server_enable_and_user_admin(server_id, user_id, http).await
{
if !enable {
return Ok(false);
}
if let Some(server_config) = server_config {
return Ok(server_config.auto_concour);
}
}
Ok(false)
}

View File

@ -0,0 +1,29 @@
use serde::{Deserialize, Serialize};
use tracing::{info, instrument};
use crate::db::concour::Concour;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum ListConcourError {
FindError(String),
UnknownError(String),
}
#[instrument(level = "info")]
pub async fn list_concour(server_id: u64) -> Result<Vec<Concour>, ListConcourError> {
let list_concour = match Concour::find_by_server_id(&server_id).await {
Ok(list_concour) => list_concour,
Err(err) => {
tracing::error!(error = err.to_string(), "Error finding concour");
return Err(ListConcourError::UnknownError(
"Error finding concour".to_string(),
));
}
};
if list_concour.is_empty() {
info!("No concour found");
return Err(ListConcourError::FindError("No concour found".to_string()));
}
Ok(list_concour)
}

View File

@ -0,0 +1,2 @@
pub mod check_if_allowed;
pub mod list_concour;

View File

@ -0,0 +1,53 @@
# Concour
## Kind Popularity
- Titre
- Théme
- Date debut/fin
- Récompense
- Manuelle
- Automatique
- Role
- Message personalisé contenant ce que tu veux
### Déclarer un concour de popularité
1. Creer un channel
2. Préparer la récompense
3. Creer et configuré le concours de popularité dans le channel cible
1. Creer : /concours-create kind:(string) title:(string) description:(string) fin:(date) (retourne l'id du concours)
2. Changer les info : /concours-edit id:(object-id) banniere:(opt,string-url) title:(opt,string) description:(opt,string) fin:(date)
3. Annoncer le concours : /concours-promo id:(object-id)
4. Definir la récompense : /concours-set-recompense id:(object-id) kind:(string) content:(string,opt)
5. Definir le channel : /concours-set-channel id:(object-id) channel-id:(u64)
6. Cloturer le concours : /concours-end id:(object-id) fin:(date,opt)
7. Annoncer le vainqueur : /concours-win id:(object-id) (si non finis, cloture le concours immédiatement)
### Sélectionner un vainqueur ?
Toute personne qui aura le plus d'émoji sur un message contenant une image
## Kind Automated Popularity
- Titre => String
- Description => String
- Date début => Date
- Periode (1 Semaine ?) => Duration
- CurrentWinner => Option<u64>
- RoleRécompense => u64
- KeyWordList => Vec<String>
- Banniére => Option<String>
- CurrentKeyWord => String
- Status => Enum<Created,Paused,OnGoing,Finished>
- HistoriqueWinner => HashMap<String,Option<(u64,Date)>>
### Command
- Creation /concours-create kind:(string) title:(string) description:(string) periode:(date)
- Start /concours-start
- List concours /concours-list
## Kind Check-in
Bot de concours avec participation reaction emoji

View File

@ -1 +1,3 @@
pub mod concour;
pub mod meme;
pub mod server_config;

View File

@ -0,0 +1,60 @@
use serde::{Deserialize, Serialize};
use tracing::instrument;
use crate::db::server_config::ServerConfig;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum ChangeEnableServerError {
UnknownError(String),
}
#[instrument(level = "info")]
pub async fn change_enable_server(
server_id: u64,
enable: bool,
) -> Result<(), ChangeEnableServerError> {
let server_config =
match crate::db::server_config::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(ChangeEnableServerError::UnknownError(
"Error finding server config".to_string(),
));
}
};
match server_config {
None => {
tracing::info!("Server config not found, creating one");
let mut server_config = ServerConfig::new(server_id).unwrap();
server_config.enable = enable;
match server_config.create().await {
Ok(_) => Ok(()),
Err(err) => {
tracing::error!(error = err.to_string(), "Error creating server config");
return Err(ChangeEnableServerError::UnknownError(
"Error creating server config".to_string(),
));
}
}
}
Some(mut server_config) => {
if server_config.enable == enable {
tracing::info!("Server config already enabled/disabled");
return Ok(());
} else {
tracing::info!("Updating server config");
server_config.enable = enable;
match server_config.update().await {
Ok(_) => Ok(()),
Err(err) => {
tracing::error!(error = err.to_string(), "Error updating server config");
return Err(ChangeEnableServerError::UnknownError(
"Error updating server config".to_string(),
));
}
}
}
}
}
}

View File

@ -0,0 +1,32 @@
use serde::{Deserialize, Serialize};
use tracing::instrument;
use crate::db::server_config::ServerConfig;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum CheckIfServerEnableError {
UnknownError(String),
}
#[instrument(level = "info")]
pub async fn check_if_server_enable(
server_id: u64,
) -> Result<(bool, Option<ServerConfig>), CheckIfServerEnableError> {
let server_config =
match crate::db::server_config::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(CheckIfServerEnableError::UnknownError(
"Error finding server config".to_string(),
));
}
};
match server_config {
None => {
tracing::info!("Server config not found");
return Ok((false, None));
}
Some(server_config) => Ok((server_config.enable, Some(server_config))),
}
}

View File

@ -0,0 +1,49 @@
use super::check_if_server_enable::{check_if_server_enable, CheckIfServerEnableError};
use crate::db::server_config::ServerConfig;
use poise::serenity_prelude::{self, RoleId, UserId};
use tracing::instrument;
#[instrument(level = "info", skip(http))]
pub async fn check_if_server_enable_and_user_admin(
server_id: u64,
user_id: u64,
http: serenity_prelude::Http,
) -> Result<(bool, Option<ServerConfig>), CheckIfServerEnableError> {
let server_config = match check_if_server_enable(server_id).await {
Ok((status, config)) => {
if !status {
return Ok((false, None));
}
config.unwrap()
}
Err(err) => return Err(err),
};
let guild = match http.get_guild(server_id.into()).await {
Ok(guild) => guild,
Err(err) => {
tracing::error!(error = err.to_string(), "Error getting guild");
return Err(CheckIfServerEnableError::UnknownError(
"Error getting guild".to_string(),
));
}
};
if guild.owner_id.get() == user_id {
return Ok((true, Some(server_config)));
}
match guild.member(http, UserId::new(user_id)).await {
Ok(member) => Ok((
server_config
.clone()
.admin_role
.into_iter()
.any(|role_id| member.roles.contains(&RoleId::new(role_id))),
Some(server_config),
)),
Err(err) => {
tracing::error!(error = err.to_string(), "Error getting member");
return Err(CheckIfServerEnableError::UnknownError(
"Error getting member".to_string(),
));
}
}
}

View File

@ -0,0 +1,58 @@
use serde::{Deserialize, Serialize};
use tracing::instrument;
use crate::db::server_config::ServerConfig;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum EnableFeatureMemeError {
UnknownError(String),
}
#[instrument(level = "info")]
pub async fn enable_feature_meme(
server_id: u64,
enable: bool,
) -> Result<(), EnableFeatureMemeError> {
let server_config =
match crate::db::server_config::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(EnableFeatureMemeError::UnknownError(
"Error finding server config".to_string(),
));
}
};
match server_config {
None => {
tracing::info!("Server config not found, creating it");
let mut server_config = ServerConfig::new(server_id).unwrap();
server_config.auto_meme = enable;
match server_config.create().await {
Ok(_) => Ok(()),
Err(err) => {
tracing::error!(error = err.to_string(), "Error creating server config");
return Err(EnableFeatureMemeError::UnknownError(
"Error creating server config".to_string(),
));
}
}
}
Some(mut server_config) => {
if server_config.auto_meme == enable {
return Ok(());
} else {
server_config.auto_meme = enable;
match server_config.update().await {
Ok(_) => Ok(()),
Err(err) => {
tracing::error!(error = err.to_string(), "Error updating server config");
return Err(EnableFeatureMemeError::UnknownError(
"Error updating server config".to_string(),
));
}
}
}
}
}
}

View File

@ -0,0 +1,58 @@
use serde::{Deserialize, Serialize};
use tracing::instrument;
use crate::db::server_config::ServerConfig;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum EnableFeatureConcourError {
UnknownError(String),
}
#[instrument(level = "info")]
pub async fn enable_feature_concour(
server_id: u64,
enable: bool,
) -> Result<(), EnableFeatureConcourError> {
let server_config =
match crate::db::server_config::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(EnableFeatureConcourError::UnknownError(
"Error finding server config".to_string(),
));
}
};
match server_config {
None => {
tracing::info!("Server config not found, creating it");
let mut server_config = ServerConfig::new(server_id).unwrap();
server_config.auto_concour = enable;
match server_config.create().await {
Ok(_) => Ok(()),
Err(err) => {
tracing::error!(error = err.to_string(), "Error creating server config");
return Err(EnableFeatureConcourError::UnknownError(
"Error creating server config".to_string(),
));
}
}
}
Some(mut server_config) => {
if server_config.auto_concour == enable {
return Ok(());
} else {
server_config.auto_concour = enable;
match server_config.update().await {
Ok(_) => Ok(()),
Err(err) => {
tracing::error!(error = err.to_string(), "Error updating server config");
return Err(EnableFeatureConcourError::UnknownError(
"Error updating server config".to_string(),
));
}
}
}
}
}
}

View File

@ -0,0 +1,26 @@
use serde::{Deserialize, Serialize};
use tracing::instrument;
use crate::db::server_config::ServerConfig;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum GetServerConfigError {
UnknownError(String),
}
#[instrument(level = "info")]
pub async fn get_server_config(
server_id: u64,
) -> Result<Option<ServerConfig>, GetServerConfigError> {
let server_config =
match crate::db::server_config::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(GetServerConfigError::UnknownError(
"Error finding server config".to_string(),
));
}
};
Ok(server_config)
}

View File

@ -0,0 +1,6 @@
pub mod change_enable_server;
pub mod check_if_server_enable;
pub mod check_if_server_enable_and_admin;
pub mod enable_feature_auto_meme;
pub mod enable_feature_concour;
pub mod get_server_config;

View File

@ -1,4 +1,5 @@
use crate::botv2::cmd::meme::{answer::answer, enable::enable, list::list};
use crate::botv2::cmd::server_config::server::server;
use crate::botv2::cmd::{help::help, ping::ping};
use crate::config::Config;
use crate::{botv2::handler::event_handler, img::config_file::ConfigFile};
@ -58,7 +59,7 @@ pub async fn start_bot(config: Config, rx: oneshot::Receiver<()>) -> Arc<Http> {
let prefix = config.prefix.clone();
let framework = poise::Framework::builder()
.options(poise::FrameworkOptions {
commands: vec![age(), ping(), help(), list(), enable(), answer()],
commands: vec![age(), ping(), help(), list(), enable(), answer(), server()],
prefix_options: poise::PrefixFrameworkOptions {
prefix: Some(prefix.into()),
..Default::default()

121
src/db/concour.rs Normal file
View File

@ -0,0 +1,121 @@
use super::init::DB;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
use surrealdb::opt::Resource;
const CONCOUR: &str = "concour";
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum ConcourStatus {
Created,
Paused,
OnGoing,
Finished,
}
impl fmt::Display for ConcourStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Concour {
pub server_id: u64,
pub enable: bool,
pub channel_id: u64,
pub title: String,
pub description: String,
pub start_date: chrono::DateTime<chrono::Utc>,
pub periode: time::Duration,
pub role_récompense: u64,
pub keywords: Vec<String>,
pub banner: Option<String>,
pub index_keyword: u64,
pub status: ConcourStatus,
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,
title: String::new(),
description: String::new(),
start_date: chrono::Utc::now(),
periode: time::Duration::days(0),
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> {
match DB.create(Resource::from(CONCOUR)).content(&self).await {
Ok(_) => {}
Err(e) => {
return Err(e);
}
};
Ok(())
}
pub async fn update(&self) -> Result<(), surrealdb::Error> {
let sql = format!(
"UPDATE {} SET enable = {}, title = '{}', description = '{}', start_date = '{}', periode = '{}', role_récompense = {}, keywords = '{:?}', banner = '{:?}', index_keyword = {}, status = '{}', winner = '{:?}' WHERE server_id = {} and channel_id = {}",
CONCOUR, self.enable, self.title, self.description, self.start_date, self.periode, self.role_récompense, self.keywords, self.banner, self.index_keyword, self.status, self.winner, self.server_id, self.channel_id
);
match DB.query(sql).await {
Ok(res) => {
println!("{:?}", res);
}
Err(e) => {
return Err(e);
}
};
Ok(())
}
pub async fn find_by_server_id_channel_id(
server_id: &u64,
channel_id: &u64,
) -> Result<Option<Concour>, surrealdb::Error> {
let sql = format!(
"SELECT * FROM {} WHERE server_id = {} AND channel_id = {}",
CONCOUR, server_id, channel_id
);
let mut results = match DB.query(&sql).await {
Ok(results) => results,
Err(e) => {
return Err(e);
}
};
let concour: Concour = match results.take(0) {
Ok(Some(concour)) => concour,
Ok(None) => {
return Ok(None);
}
Err(e) => {
return Err(e);
}
};
Ok(Some(concour))
}
pub async fn find_by_server_id(server_id: &u64) -> Result<Vec<Concour>, surrealdb::Error> {
let sql = format!("SELECT * FROM {} WHERE server_id = {}", CONCOUR, server_id);
let mut results = match DB.query(&sql).await {
Ok(results) => results,
Err(e) => {
return Err(e);
}
};
let mut concours = Vec::new();
while let Ok(Some(concour)) = results.take(0) {
concours.push(concour);
}
Ok(concours)
}
}

View File

@ -1,2 +1,4 @@
pub mod user_image;
pub mod concour;
pub mod init;
pub mod server_config;
pub mod user_image;

89
src/db/server_config.rs Normal file
View File

@ -0,0 +1,89 @@
use super::init::DB;
use serde::{Deserialize, Serialize};
use std::fmt;
use surrealdb::opt::Resource;
const SERVER_CONFIG: &str = "server_config";
const fn default_false() -> bool {
false
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ServerConfig {
#[serde(default = "default_false")]
pub enable: bool,
pub server_id: u64,
#[serde(default = "default_false")]
pub auto_meme: bool,
#[serde(default = "default_false")]
pub auto_concour: bool,
pub admin_role: Vec<u64>,
}
impl fmt::Display for ServerConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl ServerConfig {
pub fn new(server_id: u64) -> Result<Self, surrealdb::Error> {
Ok(Self {
enable: false,
server_id,
auto_meme: false,
auto_concour: false,
admin_role: Vec::new(),
})
}
pub async fn create(&self) -> Result<(), surrealdb::Error> {
match DB
.create(Resource::from(SERVER_CONFIG))
.content(&self)
.await
{
Ok(_) => Ok(()),
Err(e) => Err(e),
}
}
pub async fn update(&self) -> Result<(), surrealdb::Error> {
let sql = format!(
"UPDATE {} SET enable = {}, auto_meme = {}, auto_concour = {}, admin_role = '{:?}' WHERE server_id = {}",
SERVER_CONFIG,
self.enable,
self.auto_meme,
self.auto_concour,
self.admin_role,
self.server_id
);
match DB.query(&sql).await {
Ok(_) => Ok(()),
Err(e) => Err(e),
}
}
pub async fn find_by_server_id(
server_id: &u64,
) -> Result<Option<ServerConfig>, surrealdb::Error> {
let sql = format!(
"SELECT * FROM {} WHERE server_id = {}",
SERVER_CONFIG, server_id
);
let mut results = match DB.query(&sql).await {
Ok(results) => results,
Err(e) => {
return Err(e);
}
};
let server_config: ServerConfig = match results.take(0) {
Ok(Some(server_config)) => server_config,
Ok(None) => {
return Ok(None);
}
Err(e) => {
return Err(e);
}
};
Ok(Some(server_config))
}
}