diff --git a/Cargo.lock b/Cargo.lock
index 81135b4..80e1c73 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -703,6 +703,7 @@ dependencies = [
"serde",
"serde_json",
"serde_repr",
+ "serde_with",
"serde_yaml",
"serial_test",
"surrealdb",
diff --git a/Cargo.toml b/Cargo.toml
index fd70d16..0ce854b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -47,6 +47,7 @@ tokio-cron-scheduler = { version = "0.10", features = [
"tracing-subscriber",
"signal",
] }
+serde_with = "3.8.1"
[[bin]]
diff --git a/src/botv2/cmd/concour/keyword.rs b/src/botv2/cmd/concour/keyword.rs
index 9d31a8c..ea89305 100644
--- a/src/botv2/cmd/concour/keyword.rs
+++ b/src/botv2/cmd/concour/keyword.rs
@@ -75,17 +75,22 @@ pub async fn keyword(
.color(colour::Color::RED)
} else {
let concour = concour.unwrap();
- CreateEmbed::new()
+ let output = CreateEmbed::new()
.title(concour.title)
.description(concour.description)
.field("Start date", concour.start_date.to_string(), false)
.field("Periode", concour.periode.to_string(), false)
- .field(
+ .field("keyword", concour.keywords.len().to_string(), true);
+
+ if concour.role_recompense != 0 {
+ output.field(
"Role récompense",
RoleId::new(concour.role_recompense).mention().to_string(),
false,
)
- .field("keyword", concour.keywords.len().to_string(), true)
+ } else {
+ output
+ }
}
}
Err(err) => match err {
diff --git a/src/botv2/cmd/concour/main.rs b/src/botv2/cmd/concour/main.rs
index 2559553..da2e186 100644
--- a/src/botv2/cmd/concour/main.rs
+++ b/src/botv2/cmd/concour/main.rs
@@ -1,5 +1,8 @@
use crate::botv2::{
- cmd::concour::{create::create, keyword::keyword, list::list, period::period, update::update},
+ cmd::concour::{
+ create::create, keyword::keyword, list::list, period::period, start::start, stop::stop,
+ update::update,
+ },
domain::concour::{
check_if_allowed::check_if_concour_allowed, get_channel_concour::get_channel_concour,
},
@@ -17,7 +20,9 @@ use tracing::instrument;
slash_command,
prefix_command,
category = "concour",
- subcommands("get", "list", "update", "create", "keyword", "period"),
+ subcommands(
+ "get", "list", "update", "create", "keyword", "period", "start", "stop"
+ ),
guild_only = true
)]
pub async fn concour(
diff --git a/src/botv2/cmd/concour/mod.rs b/src/botv2/cmd/concour/mod.rs
index 2909a5f..c68c9bf 100644
--- a/src/botv2/cmd/concour/mod.rs
+++ b/src/botv2/cmd/concour/mod.rs
@@ -3,4 +3,6 @@ pub mod keyword;
pub mod list;
pub mod main;
pub mod period;
+pub mod start;
+pub mod stop;
pub mod update;
diff --git a/src/botv2/cmd/concour/start.rs b/src/botv2/cmd/concour/start.rs
new file mode 100644
index 0000000..fbad844
--- /dev/null
+++ b/src/botv2/cmd/concour/start.rs
@@ -0,0 +1,137 @@
+use crate::botv2::{
+ domain::concour::{
+ check_if_allowed::check_if_allowed,
+ start_concour::{start_concour, start_concour_step2, StartConcourError},
+ },
+ init::{Context, Error},
+};
+use poise::{
+ serenity_prelude::{model::colour, CreateEmbed, CreateEmbedFooter},
+ CreateReply,
+};
+use tracing::instrument;
+
+/// Start concour (only for admin)
+#[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 start(ctx: Context<'_>) -> Result<(), Error> {
+ let guild = match ctx.guild_id() {
+ Some(guild) => guild,
+ None => return Ok(()),
+ };
+ let entity_name = ctx.data().entity_name.clone();
+ let mut cron_schedule = ctx.data().scheduler.clone();
+ let footer = CreateEmbedFooter::new(entity_name.clone());
+ match check_if_allowed(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 (concour, success) =
+ match start_concour(guild.get(), ctx.channel_id().get(), &mut cron_schedule).await {
+ Ok(concour) => {
+ if concour.is_none() {
+ (
+ CreateEmbed::new()
+ .title("No concour created")
+ .color(colour::Color::RED),
+ false,
+ )
+ } else {
+ let concour = concour.unwrap();
+ let keyword_index = concour.index_keyword as usize;
+ let keyword = concour.keywords.get(keyword_index).unwrap();
+ let output = CreateEmbed::new()
+ .title(format!(
+ "Concour: {} Jour : {}",
+ concour.title,
+ concour.index_keyword + 1
+ ))
+ .description(concour.description)
+ .field("Mot du jours ", keyword.to_string(), false)
+ .field("Good luck !", "", false)
+ .field(
+ "Vous avez jusqu'a demain 17h",
+ "HARD CODED FOR THE MOMENT",
+ false,
+ )
+ .color(colour::Color::DARK_GREEN);
+ (output, true)
+ }
+ }
+ Err(err) => (
+ match err {
+ StartConcourError::AlreadyOnGoing => CreateEmbed::new()
+ .title("Concour already OnGoing")
+ .color(colour::Color::RED),
+ StartConcourError::DoesntExist => CreateEmbed::new()
+ .title("Concour doesn't exist")
+ .color(colour::Color::RED),
+ StartConcourError::KeyWordListEmpty => CreateEmbed::new()
+ .title("Keyword list empty")
+ .color(colour::Color::RED),
+ StartConcourError::FinishedKeyWordList => CreateEmbed::new()
+ .title("Finished keyword list, add new one")
+ .color(colour::Color::RED),
+ _ => CreateEmbed::new()
+ .title("Error while creating concour")
+ .field("Please contact your administrator", "", false)
+ .field("Your concour is possibly not initied correctly", "", false)
+ .color(colour::Color::RED),
+ },
+ false,
+ ),
+ };
+ let mut builder = CreateReply::default().ephemeral(!success);
+ builder = builder.embed(concour.footer(footer));
+ match ctx.send(builder).await {
+ Ok(handler) => {
+ if success {
+ let message_id = handler.message().await.unwrap().id.get();
+ tracing::info!(msg_id = message_id, "Concour started");
+ match start_concour_step2(guild.get(), ctx.channel_id().get(), message_id).await {
+ Ok(_) => {}
+ Err(err) => {
+ tracing::error!("Error starting concour step 2: {:?}", err);
+ }
+ }
+ }
+ }
+ Err(why) => {
+ tracing::error!("Error sending message: {:?}", why);
+ }
+ }
+
+ Ok(())
+}
diff --git a/src/botv2/cmd/concour/stop.rs b/src/botv2/cmd/concour/stop.rs
new file mode 100644
index 0000000..3d89fed
--- /dev/null
+++ b/src/botv2/cmd/concour/stop.rs
@@ -0,0 +1,108 @@
+use crate::botv2::{
+ domain::concour::{
+ check_if_allowed::check_if_allowed,
+ stop_concour::{stop_concour, StopConcourError},
+ },
+ init::{Context, Error},
+};
+use poise::{
+ serenity_prelude::{model::colour, CreateEmbed, CreateEmbedFooter},
+ CreateReply,
+};
+use tracing::instrument;
+
+/// Stop concour (only for admin)
+#[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 stop(ctx: Context<'_>) -> Result<(), Error> {
+ let guild = match ctx.guild_id() {
+ Some(guild) => guild,
+ None => return Ok(()),
+ };
+ let entity_name = ctx.data().entity_name.clone();
+ let mut cron_schedule = ctx.data().scheduler.clone();
+ let footer = CreateEmbedFooter::new(entity_name.clone());
+ match check_if_allowed(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 (concour, success) =
+ match stop_concour(guild.get(), ctx.channel_id().get(), &mut cron_schedule).await {
+ Ok(concour) => {
+ if concour.is_none() {
+ (
+ CreateEmbed::new()
+ .title("No concour created")
+ .color(colour::Color::RED),
+ false,
+ )
+ } else {
+ let concour = concour.unwrap();
+ let output = CreateEmbed::new()
+ .title(format!("Concour: {}", concour.title))
+ .description(concour.description)
+ .field("Concour mis en pause ", "", false)
+ .color(colour::Color::DARK_GREEN);
+ (output, true)
+ }
+ }
+ Err(err) => (
+ match err {
+ StopConcourError::AlreadyStopped => CreateEmbed::new()
+ .title("Concour already Stopped")
+ .color(colour::Color::RED),
+ StopConcourError::DoesntExist => CreateEmbed::new()
+ .title("Concour doesn't exist")
+ .color(colour::Color::RED),
+ StopConcourError::NotScheduled => CreateEmbed::new()
+ .title("Concour not scheduled")
+ .color(colour::Color::RED),
+ _ => CreateEmbed::new()
+ .title("Error while creating concour")
+ .field("Please contact your administrator", "", false)
+ .field("Your concour is possibly not initied correctly", "", false)
+ .color(colour::Color::RED),
+ },
+ false,
+ ),
+ };
+ let mut builder = CreateReply::default().ephemeral(!success);
+ builder = builder.embed(concour.footer(footer));
+ if let Err(why) = ctx.send(builder).await {
+ tracing::error!("Error sending message: {:?}", why);
+ }
+
+ Ok(())
+}
diff --git a/src/botv2/domain/concour/add_keyword.rs b/src/botv2/domain/concour/add_keyword.rs
index eb723d3..a6f8807 100644
--- a/src/botv2/domain/concour/add_keyword.rs
+++ b/src/botv2/domain/concour/add_keyword.rs
@@ -51,7 +51,7 @@ pub async fn add_keyword_concour(
let text = res.text().await.unwrap();
let split_delimiter = delimiter.unwrap_or("\n".to_string());
text.split(&split_delimiter).for_each(|x| {
- concour.keywords.push(x.to_string());
+ concour.keywords.push(x.to_string().replace('\r', ""));
});
}
Err(err) => {
@@ -61,7 +61,6 @@ pub async fn add_keyword_concour(
));
}
}
- concour.keywords.push(url);
}
KeyWordSource::Text(text, delimiter) => {
let split_delimiter = delimiter.unwrap_or("\n".to_string());
diff --git a/src/botv2/domain/concour/start_concour.rs b/src/botv2/domain/concour/start_concour.rs
index 0118166..74785f9 100644
--- a/src/botv2/domain/concour/start_concour.rs
+++ b/src/botv2/domain/concour/start_concour.rs
@@ -1,19 +1,26 @@
use serde::{Deserialize, Serialize};
use tracing::{info, instrument};
-use crate::db::concour::Concour;
+use crate::{
+ db::concour::{Concour, ConcourStatus},
+ event::schedule_job::ScheduleJob,
+};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum StartConcourError {
+ AlreadyOnGoing,
DoesntExist,
+ KeyWordListEmpty,
+ FinishedKeyWordList,
FindError(String),
UnknownError(String),
}
-#[instrument(level = "info")]
+#[instrument(level = "info", skip(cron_scheduler))]
pub async fn start_concour(
server_id: u64,
channel_id: u64,
+ cron_scheduler: &mut ScheduleJob,
) -> Result