feat: Start/Stop/Add keywords are working YIPEEE and update with surrealdb are fixed
This commit is contained in:
parent
c99692fbea
commit
ecadf7a90d
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -703,6 +703,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
|
"serde_with",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"serial_test",
|
"serial_test",
|
||||||
"surrealdb",
|
"surrealdb",
|
||||||
|
@ -47,6 +47,7 @@ tokio-cron-scheduler = { version = "0.10", features = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"signal",
|
"signal",
|
||||||
] }
|
] }
|
||||||
|
serde_with = "3.8.1"
|
||||||
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -75,17 +75,22 @@ pub async fn keyword(
|
|||||||
.color(colour::Color::RED)
|
.color(colour::Color::RED)
|
||||||
} else {
|
} else {
|
||||||
let concour = concour.unwrap();
|
let concour = concour.unwrap();
|
||||||
CreateEmbed::new()
|
let output = CreateEmbed::new()
|
||||||
.title(concour.title)
|
.title(concour.title)
|
||||||
.description(concour.description)
|
.description(concour.description)
|
||||||
.field("Start date", concour.start_date.to_string(), false)
|
.field("Start date", concour.start_date.to_string(), false)
|
||||||
.field("Periode", concour.periode.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",
|
"Role récompense",
|
||||||
RoleId::new(concour.role_recompense).mention().to_string(),
|
RoleId::new(concour.role_recompense).mention().to_string(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.field("keyword", concour.keywords.len().to_string(), true)
|
} else {
|
||||||
|
output
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => match err {
|
Err(err) => match err {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use crate::botv2::{
|
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::{
|
domain::concour::{
|
||||||
check_if_allowed::check_if_concour_allowed, get_channel_concour::get_channel_concour,
|
check_if_allowed::check_if_concour_allowed, get_channel_concour::get_channel_concour,
|
||||||
},
|
},
|
||||||
@ -17,7 +20,9 @@ use tracing::instrument;
|
|||||||
slash_command,
|
slash_command,
|
||||||
prefix_command,
|
prefix_command,
|
||||||
category = "concour",
|
category = "concour",
|
||||||
subcommands("get", "list", "update", "create", "keyword", "period"),
|
subcommands(
|
||||||
|
"get", "list", "update", "create", "keyword", "period", "start", "stop"
|
||||||
|
),
|
||||||
guild_only = true
|
guild_only = true
|
||||||
)]
|
)]
|
||||||
pub async fn concour(
|
pub async fn concour(
|
||||||
|
@ -3,4 +3,6 @@ pub mod keyword;
|
|||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod main;
|
pub mod main;
|
||||||
pub mod period;
|
pub mod period;
|
||||||
|
pub mod start;
|
||||||
|
pub mod stop;
|
||||||
pub mod update;
|
pub mod update;
|
||||||
|
137
src/botv2/cmd/concour/start.rs
Normal file
137
src/botv2/cmd/concour/start.rs
Normal file
@ -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(())
|
||||||
|
}
|
108
src/botv2/cmd/concour/stop.rs
Normal file
108
src/botv2/cmd/concour/stop.rs
Normal file
@ -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(())
|
||||||
|
}
|
@ -51,7 +51,7 @@ pub async fn add_keyword_concour(
|
|||||||
let text = res.text().await.unwrap();
|
let text = res.text().await.unwrap();
|
||||||
let split_delimiter = delimiter.unwrap_or("\n".to_string());
|
let split_delimiter = delimiter.unwrap_or("\n".to_string());
|
||||||
text.split(&split_delimiter).for_each(|x| {
|
text.split(&split_delimiter).for_each(|x| {
|
||||||
concour.keywords.push(x.to_string());
|
concour.keywords.push(x.to_string().replace('\r', ""));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -61,7 +61,6 @@ pub async fn add_keyword_concour(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
concour.keywords.push(url);
|
|
||||||
}
|
}
|
||||||
KeyWordSource::Text(text, delimiter) => {
|
KeyWordSource::Text(text, delimiter) => {
|
||||||
let split_delimiter = delimiter.unwrap_or("\n".to_string());
|
let split_delimiter = delimiter.unwrap_or("\n".to_string());
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::{info, instrument};
|
use tracing::{info, instrument};
|
||||||
|
|
||||||
use crate::db::concour::Concour;
|
use crate::{
|
||||||
|
db::concour::{Concour, ConcourStatus},
|
||||||
|
event::schedule_job::ScheduleJob,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum StartConcourError {
|
pub enum StartConcourError {
|
||||||
|
AlreadyOnGoing,
|
||||||
DoesntExist,
|
DoesntExist,
|
||||||
|
KeyWordListEmpty,
|
||||||
|
FinishedKeyWordList,
|
||||||
FindError(String),
|
FindError(String),
|
||||||
UnknownError(String),
|
UnknownError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "info")]
|
#[instrument(level = "info", skip(cron_scheduler))]
|
||||||
pub async fn start_concour(
|
pub async fn start_concour(
|
||||||
server_id: u64,
|
server_id: u64,
|
||||||
channel_id: u64,
|
channel_id: u64,
|
||||||
|
cron_scheduler: &mut ScheduleJob,
|
||||||
) -> Result<Option<Concour>, StartConcourError> {
|
) -> Result<Option<Concour>, StartConcourError> {
|
||||||
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
|
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
|
||||||
Ok(list_concour) => list_concour,
|
Ok(list_concour) => list_concour,
|
||||||
@ -29,19 +36,76 @@ pub async fn start_concour(
|
|||||||
info!("Concour doesn't exist");
|
info!("Concour doesn't exist");
|
||||||
return Err(StartConcourError::DoesntExist);
|
return Err(StartConcourError::DoesntExist);
|
||||||
}
|
}
|
||||||
todo!("Setup logic to start the waiting period for the concour");
|
let mut concour = concour.unwrap();
|
||||||
// let mut concour = concour.unwrap();
|
if concour.keywords.is_empty() {
|
||||||
|
tracing::warn!("Keyword list is empty");
|
||||||
|
return Err(StartConcourError::KeyWordListEmpty);
|
||||||
|
}
|
||||||
|
let keyword_len = concour.keywords.len() as u64;
|
||||||
|
if concour.index_keyword.gt(&keyword_len) {
|
||||||
|
tracing::warn!(keyword_len, concour.index_keyword, "Finished keyword list");
|
||||||
|
return Err(StartConcourError::FinishedKeyWordList);
|
||||||
|
}
|
||||||
|
if concour.status == ConcourStatus::OnGoing {
|
||||||
|
tracing::warn!("Concour already OnGoing");
|
||||||
|
return Err(StartConcourError::AlreadyOnGoing);
|
||||||
|
}
|
||||||
|
match cron_scheduler
|
||||||
|
.add_concour_cron_job(server_id, channel_id, "*/1 * * * * *".to_string())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(_) => {
|
||||||
|
tracing::error!("Error starting cron job");
|
||||||
|
return Err(StartConcourError::UnknownError(
|
||||||
|
"Error starting cron job".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
concour.status = ConcourStatus::OnGoing;
|
||||||
|
|
||||||
// // Update status to started
|
match concour.update().await {
|
||||||
|
Ok(_) => {}
|
||||||
// match concour.update().await {
|
Err(err) => {
|
||||||
// Ok(_) => {}
|
tracing::error!(error = err.to_string(), "Error updating concour");
|
||||||
// Err(err) => {
|
return Err(StartConcourError::UnknownError(
|
||||||
// tracing::error!(error = err.to_string(), "Error updating concour");
|
"Error updating concour".to_string(),
|
||||||
// return Err(StartConcourError::UnknownError(
|
));
|
||||||
// "Error updating concour".to_string(),
|
}
|
||||||
// ));
|
}
|
||||||
// }
|
Ok(Some(concour))
|
||||||
// }
|
}
|
||||||
// Ok(Some(concour))
|
|
||||||
|
#[instrument(level = "info")]
|
||||||
|
pub async fn start_concour_step2(
|
||||||
|
server_id: u64,
|
||||||
|
channel_id: u64,
|
||||||
|
message_id: u64,
|
||||||
|
) -> Result<(), StartConcourError> {
|
||||||
|
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(StartConcourError::UnknownError(
|
||||||
|
"Error finding concour".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if concour.is_none() {
|
||||||
|
info!("Concour doesn't exist");
|
||||||
|
return Err(StartConcourError::DoesntExist);
|
||||||
|
}
|
||||||
|
let mut concour = concour.unwrap();
|
||||||
|
concour.last_message_id = Some(message_id);
|
||||||
|
match concour.update().await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!(error = err.to_string(), "Error updating concour");
|
||||||
|
return Err(StartConcourError::UnknownError(
|
||||||
|
"Error updating concour".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::{info, instrument};
|
use tracing::{info, instrument};
|
||||||
|
|
||||||
use crate::db::concour::Concour;
|
use crate::{
|
||||||
|
db::concour::{Concour, ConcourStatus},
|
||||||
|
event::schedule_job::{ScheduleJob, StopScheduleJob},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum StopConcourError {
|
pub enum StopConcourError {
|
||||||
DoesntExist,
|
DoesntExist,
|
||||||
|
AlreadyStopped,
|
||||||
|
NotScheduled,
|
||||||
FindError(String),
|
FindError(String),
|
||||||
UnknownError(String),
|
UnknownError(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "info")]
|
#[instrument(level = "info", skip(cron_scheduler))]
|
||||||
pub async fn stop_concour(
|
pub async fn stop_concour(
|
||||||
server_id: u64,
|
server_id: u64,
|
||||||
channel_id: u64,
|
channel_id: u64,
|
||||||
|
cron_scheduler: &mut ScheduleJob,
|
||||||
) -> Result<Option<Concour>, StopConcourError> {
|
) -> Result<Option<Concour>, StopConcourError> {
|
||||||
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
|
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
|
||||||
Ok(list_concour) => list_concour,
|
Ok(list_concour) => list_concour,
|
||||||
@ -29,19 +35,43 @@ pub async fn stop_concour(
|
|||||||
info!("Concour doesn't exist");
|
info!("Concour doesn't exist");
|
||||||
return Err(StopConcourError::DoesntExist);
|
return Err(StopConcourError::DoesntExist);
|
||||||
}
|
}
|
||||||
todo!("Setup logic to stop the waiting period for the concour");
|
let mut concour = concour.unwrap();
|
||||||
// let mut concour = concour.unwrap();
|
|
||||||
|
|
||||||
// // Update status to Paused
|
if concour.status == ConcourStatus::Paused {
|
||||||
|
return Err(StopConcourError::AlreadyStopped);
|
||||||
|
}
|
||||||
|
match cron_scheduler
|
||||||
|
.stop_scheduled_job(server_id, channel_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!(err = e.to_string(), "Error stopping cron job");
|
||||||
|
match e {
|
||||||
|
StopScheduleJob::JobNotFound => {
|
||||||
|
tracing::error!("Job not found");
|
||||||
|
return Err(StopConcourError::NotScheduled);
|
||||||
|
}
|
||||||
|
StopScheduleJob::RemoveFailed => {
|
||||||
|
tracing::error!("Remove failed");
|
||||||
|
return Err(StopConcourError::UnknownError(
|
||||||
|
"Error stopping cron job".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
concour.status = ConcourStatus::Paused;
|
||||||
|
concour.last_message_id = None;
|
||||||
|
|
||||||
// match concour.update().await {
|
match concour.update().await {
|
||||||
// Ok(_) => {}
|
Ok(_) => {}
|
||||||
// Err(err) => {
|
Err(err) => {
|
||||||
// tracing::error!(error = err.to_string(), "Error updating concour");
|
tracing::error!(error = err.to_string(), "Error updating concour");
|
||||||
// return Err(StopConcourError::UnknownError(
|
return Err(StopConcourError::UnknownError(
|
||||||
// "Error updating concour".to_string(),
|
"Error updating concour".to_string(),
|
||||||
// ));
|
));
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// Ok(Some(concour))
|
Ok(Some(concour))
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,13 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use surrealdb::opt::Resource;
|
use surrealdb::opt::Resource;
|
||||||
|
use surrealdb::sql::Thing;
|
||||||
|
use tracing::instrument;
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
const CONCOUR: &str = "concour";
|
const CONCOUR: &str = "concour";
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema, PartialEq, Eq)]
|
||||||
pub enum ConcourStatus {
|
pub enum ConcourStatus {
|
||||||
Created,
|
Created,
|
||||||
Paused,
|
Paused,
|
||||||
@ -21,6 +23,19 @@ impl fmt::Display for ConcourStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||||
|
pub struct ConcourRecord {
|
||||||
|
pub id: Thing,
|
||||||
|
pub server_id: u64,
|
||||||
|
pub channel_id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||||
|
pub struct ConcourWinner {
|
||||||
|
pub user_id: u64,
|
||||||
|
pub date: chrono::DateTime<chrono::Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||||
pub struct Concour {
|
pub struct Concour {
|
||||||
pub server_id: u64,
|
pub server_id: u64,
|
||||||
@ -34,7 +49,8 @@ pub struct Concour {
|
|||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
pub index_keyword: u64,
|
pub index_keyword: u64,
|
||||||
pub status: ConcourStatus,
|
pub status: ConcourStatus,
|
||||||
pub winner: HashMap<String, (u64, chrono::DateTime<chrono::Utc>)>,
|
pub winner: HashMap<String, ConcourWinner>,
|
||||||
|
pub last_message_id: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Concour {
|
impl Default for Concour {
|
||||||
@ -52,6 +68,7 @@ impl Default for Concour {
|
|||||||
index_keyword: 0,
|
index_keyword: 0,
|
||||||
status: ConcourStatus::Created,
|
status: ConcourStatus::Created,
|
||||||
winner: HashMap::new(),
|
winner: HashMap::new(),
|
||||||
|
last_message_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,8 +88,10 @@ impl Concour {
|
|||||||
index_keyword: 0,
|
index_keyword: 0,
|
||||||
status: ConcourStatus::Created,
|
status: ConcourStatus::Created,
|
||||||
winner: HashMap::new(),
|
winner: HashMap::new(),
|
||||||
|
last_message_id: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn create(&self) -> Result<(), surrealdb::Error> {
|
pub async fn create(&self) -> Result<(), surrealdb::Error> {
|
||||||
match DB.create(Resource::from(CONCOUR)).content(&self).await {
|
match DB.create(Resource::from(CONCOUR)).content(&self).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@ -82,21 +101,61 @@ impl Concour {
|
|||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn update(&self) -> Result<(), surrealdb::Error> {
|
#[instrument(level = "info")]
|
||||||
|
pub async fn update(&self) -> Result<bool, surrealdb::Error> {
|
||||||
|
let id = match Concour::get_records(&self.server_id, &self.channel_id).await {
|
||||||
|
Ok(Some(concour)) => concour.id,
|
||||||
|
Ok(None) => return Ok(false),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("Error getting concour id: {:?}", e);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match DB
|
||||||
|
.update::<Option<Concour>>((CONCOUR.to_string(), id))
|
||||||
|
.merge(self)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(concour) => {
|
||||||
|
if concour.is_none() {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
tracing::info!("Concour updated: {:?}", concour);
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("Error updating concour: {:?}", e);
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
|
pub async fn get_records(
|
||||||
|
server_id: &u64,
|
||||||
|
channel_id: &u64,
|
||||||
|
) -> Result<Option<ConcourRecord>, surrealdb::Error> {
|
||||||
let sql = format!(
|
let sql = format!(
|
||||||
"UPDATE {} SET title = '{}', description = '{}', start_date = '{}', periode = '{}', role_récompense = {}, keywords = '{:?}', banner = '{:?}', index_keyword = {}, status = '{}', winner = '{:?}' WHERE server_id = {} and channel_id = {}",
|
"SELECT id,server_id,channel_id FROM {} WHERE server_id = {} AND channel_id = {}",
|
||||||
CONCOUR, self.title, self.description, self.start_date, self.periode, self.role_recompense, self.keywords, self.banner, self.index_keyword, self.status, self.winner, self.server_id, self.channel_id
|
CONCOUR, server_id, channel_id
|
||||||
);
|
);
|
||||||
match DB.query(sql).await {
|
let mut results = match DB.query(&sql).await {
|
||||||
Ok(res) => {
|
Ok(results) => results,
|
||||||
println!("{:?}", res);
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let concour: ConcourRecord = match results.take(0) {
|
||||||
|
Ok(Some(concour)) => concour,
|
||||||
|
Ok(None) => {
|
||||||
|
return Ok(None);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(Some(concour))
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn find_by_server_id_channel_id(
|
pub async fn find_by_server_id_channel_id(
|
||||||
server_id: &u64,
|
server_id: &u64,
|
||||||
channel_id: &u64,
|
channel_id: &u64,
|
||||||
@ -122,6 +181,7 @@ impl Concour {
|
|||||||
};
|
};
|
||||||
Ok(Some(concour))
|
Ok(Some(concour))
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn find_by_server_id(server_id: &u64) -> Result<Vec<Concour>, surrealdb::Error> {
|
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 sql = format!("SELECT * FROM {} WHERE server_id = {}", CONCOUR, server_id);
|
||||||
let mut results = match DB.query(&sql).await {
|
let mut results = match DB.query(&sql).await {
|
||||||
@ -136,7 +196,7 @@ impl Concour {
|
|||||||
}
|
}
|
||||||
Ok(concours)
|
Ok(concours)
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn find_by_status(status: &ConcourStatus) -> Result<Vec<Concour>, surrealdb::Error> {
|
pub async fn find_by_status(status: &ConcourStatus) -> Result<Vec<Concour>, surrealdb::Error> {
|
||||||
let sql = format!("SELECT * FROM {} WHERE status = '{}'", CONCOUR, status);
|
let sql = format!("SELECT * FROM {} WHERE status = '{}'", CONCOUR, status);
|
||||||
let mut results = match DB.query(&sql).await {
|
let mut results = match DB.query(&sql).await {
|
||||||
|
@ -2,6 +2,7 @@ use super::init::DB;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use surrealdb::opt::Resource;
|
use surrealdb::opt::Resource;
|
||||||
|
use tracing::instrument;
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
const SERVER_CONFIG: &str = "server_config";
|
const SERVER_CONFIG: &str = "server_config";
|
||||||
@ -37,6 +38,7 @@ impl ServerConfig {
|
|||||||
admin_role: Vec::new(),
|
admin_role: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn create(&self) -> Result<(), surrealdb::Error> {
|
pub async fn create(&self) -> Result<(), surrealdb::Error> {
|
||||||
match DB
|
match DB
|
||||||
.create(Resource::from(SERVER_CONFIG))
|
.create(Resource::from(SERVER_CONFIG))
|
||||||
@ -47,6 +49,7 @@ impl ServerConfig {
|
|||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn update(&self) -> Result<(), surrealdb::Error> {
|
pub async fn update(&self) -> Result<(), surrealdb::Error> {
|
||||||
let sql = format!(
|
let sql = format!(
|
||||||
"UPDATE {} SET enable = {}, auto_meme = {}, auto_concour = {}, admin_role = {:?} WHERE server_id = {}",
|
"UPDATE {} SET enable = {}, auto_meme = {}, auto_concour = {}, admin_role = {:?} WHERE server_id = {}",
|
||||||
@ -62,6 +65,7 @@ impl ServerConfig {
|
|||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn find_by_server_id(
|
pub async fn find_by_server_id(
|
||||||
server_id: &u64,
|
server_id: &u64,
|
||||||
) -> Result<Option<ServerConfig>, surrealdb::Error> {
|
) -> Result<Option<ServerConfig>, surrealdb::Error> {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use surrealdb::opt::Resource;
|
use surrealdb::opt::Resource;
|
||||||
|
use tracing::instrument;
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
use super::init::DB;
|
use super::init::DB;
|
||||||
@ -21,7 +22,7 @@ impl User {
|
|||||||
enable,
|
enable,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn create(&self) -> Result<(), surrealdb::Error> {
|
pub async fn create(&self) -> Result<(), surrealdb::Error> {
|
||||||
match DB.create(Resource::from(USERIMAGE)).content(&self).await {
|
match DB.create(Resource::from(USERIMAGE)).content(&self).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@ -31,7 +32,7 @@ impl User {
|
|||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn update(&self) -> Result<(), surrealdb::Error> {
|
pub async fn update(&self) -> Result<(), surrealdb::Error> {
|
||||||
let sql = format!(
|
let sql = format!(
|
||||||
"UPDATE {} SET enable = {} WHERE server_id = {} AND user_id = {}",
|
"UPDATE {} SET enable = {} WHERE server_id = {} AND user_id = {}",
|
||||||
@ -47,7 +48,7 @@ impl User {
|
|||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
#[instrument(level = "info")]
|
||||||
pub async fn find_by_server_id_user_id(
|
pub async fn find_by_server_id_user_id(
|
||||||
server_id: &u64,
|
server_id: &u64,
|
||||||
user_id: &u64,
|
user_id: &u64,
|
||||||
|
@ -1,16 +1,33 @@
|
|||||||
use std::collections::HashMap;
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
fmt::{self, Display},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
use tokio::sync::RwLock;
|
||||||
use tokio_cron_scheduler::{Job, JobScheduler};
|
use tokio_cron_scheduler::{Job, JobScheduler};
|
||||||
use tracing::{error, info, instrument};
|
use tracing::{error, info, instrument};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum StopScheduleJob {
|
||||||
|
JobNotFound,
|
||||||
|
RemoveFailed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for StopScheduleJob {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ScheduleJob {
|
pub struct ScheduleJob {
|
||||||
pub job_id: HashMap<(u64, u64), Uuid>,
|
pub job_id: Arc<RwLock<HashMap<(u64, u64), Uuid>>>,
|
||||||
pub scheduler: JobScheduler,
|
pub scheduler: JobScheduler,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScheduleJob {
|
impl ScheduleJob {
|
||||||
#[instrument()]
|
#[instrument(level = "info")]
|
||||||
pub async fn start_cron_scheduler() -> Result<Self, ()> {
|
pub async fn start_cron_scheduler() -> Result<Self, ()> {
|
||||||
let scheduler = JobScheduler::new().await;
|
let scheduler = JobScheduler::new().await;
|
||||||
let mut future_self = match scheduler {
|
let mut future_self = match scheduler {
|
||||||
@ -41,12 +58,14 @@ impl ScheduleJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self), level = "info")]
|
||||||
pub async fn stop_cron_scheduler(&mut self) -> &mut Self {
|
pub async fn stop_cron_scheduler(&mut self) -> &mut Self {
|
||||||
for (server_id, channel_id) in self.job_id.keys() {
|
let job_id = self.job_id.write().await;
|
||||||
|
|
||||||
|
for (server_id, channel_id) in job_id.keys() {
|
||||||
match self
|
match self
|
||||||
.scheduler
|
.scheduler
|
||||||
.remove(self.job_id.get(&(*server_id, *channel_id)).unwrap())
|
.remove(job_id.get(&(*server_id, *channel_id)).unwrap())
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
@ -57,6 +76,8 @@ impl ScheduleJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop(job_id);
|
||||||
match self.scheduler.shutdown().await {
|
match self.scheduler.shutdown().await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
info!("Cron scheduler stopped");
|
info!("Cron scheduler stopped");
|
||||||
@ -69,8 +90,8 @@ impl ScheduleJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self), level = "info")]
|
||||||
pub async fn add_cron_job(
|
pub async fn add_concour_cron_job(
|
||||||
&mut self,
|
&mut self,
|
||||||
server_id: u64,
|
server_id: u64,
|
||||||
channel_id: u64,
|
channel_id: u64,
|
||||||
@ -91,7 +112,10 @@ impl ScheduleJob {
|
|||||||
match self.scheduler.add(job).await {
|
match self.scheduler.add(job).await {
|
||||||
Ok(job_uid) => {
|
Ok(job_uid) => {
|
||||||
info!("Cron job added");
|
info!("Cron job added");
|
||||||
self.job_id.insert((server_id, channel_id), job_uid);
|
{
|
||||||
|
let mut job_id = self.job_id.write().await;
|
||||||
|
job_id.insert((server_id, channel_id), job_uid);
|
||||||
|
}
|
||||||
Ok(job_uid)
|
Ok(job_uid)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -100,19 +124,30 @@ impl ScheduleJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self), level = "info")]
|
||||||
pub async fn stop_scheduled_job(&mut self, server_id: u64, channel_id: u64) {
|
pub async fn stop_scheduled_job(
|
||||||
match self.job_id.remove(&(server_id, channel_id)) {
|
&mut self,
|
||||||
|
server_id: u64,
|
||||||
|
channel_id: u64,
|
||||||
|
) -> Result<(), StopScheduleJob> {
|
||||||
|
let remove_job = {
|
||||||
|
let mut job_id = self.job_id.write().await;
|
||||||
|
job_id.remove(&(server_id, channel_id))
|
||||||
|
};
|
||||||
|
match remove_job {
|
||||||
Some(job_uid) => match self.scheduler.remove(&job_uid).await {
|
Some(job_uid) => match self.scheduler.remove(&job_uid).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
info!("Cron job removed");
|
info!("Cron job removed");
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error removing cron job: {:?}", e);
|
error!("Error removing cron job: {:?}", e);
|
||||||
|
Err(StopScheduleJob::RemoveFailed)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
error!("Cron job not found");
|
error!("Cron job not found");
|
||||||
|
Err(StopScheduleJob::JobNotFound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,6 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.bind(("0.0.0.0", port))?
|
.bind(("0.0.0.0", port))?
|
||||||
.run()
|
.run()
|
||||||
.await?;
|
.await?;
|
||||||
cron_scheduler.stop_scheduled_job(123, 123).await;
|
|
||||||
info!("API Server stopped.");
|
info!("API Server stopped.");
|
||||||
tx_bot.send(()).unwrap();
|
tx_bot.send(()).unwrap();
|
||||||
cron_scheduler.stop_cron_scheduler().await;
|
cron_scheduler.stop_cron_scheduler().await;
|
||||||
|
Loading…
Reference in New Issue
Block a user