feat: Start/Stop/Add keywords are working YIPEEE and update with surrealdb are fixed

This commit is contained in:
Max batleforc 2024-06-25 02:53:13 +02:00
parent c99692fbea
commit ecadf7a90d
No known key found for this signature in database
GPG Key ID: 25D243AB4B6AC9E7
15 changed files with 515 additions and 64 deletions

1
Cargo.lock generated
View File

@ -703,6 +703,7 @@ dependencies = [
"serde",
"serde_json",
"serde_repr",
"serde_with",
"serde_yaml",
"serial_test",
"surrealdb",

View File

@ -47,6 +47,7 @@ tokio-cron-scheduler = { version = "0.10", features = [
"tracing-subscriber",
"signal",
] }
serde_with = "3.8.1"
[[bin]]

View File

@ -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 {

View File

@ -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(

View File

@ -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;

View 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(())
}

View 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(())
}

View File

@ -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());

View File

@ -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<Option<Concour>, StartConcourError> {
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
Ok(list_concour) => list_concour,
@ -29,19 +36,76 @@ pub async fn start_concour(
info!("Concour doesn't exist");
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(_) => {}
// Err(err) => {
// tracing::error!(error = err.to_string(), "Error updating concour");
// return Err(StartConcourError::UnknownError(
// "Error updating concour".to_string(),
// ));
// }
// }
// Ok(Some(concour))
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(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(())
}

View File

@ -1,19 +1,25 @@
use serde::{Deserialize, Serialize};
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)]
pub enum StopConcourError {
DoesntExist,
AlreadyStopped,
NotScheduled,
FindError(String),
UnknownError(String),
}
#[instrument(level = "info")]
#[instrument(level = "info", skip(cron_scheduler))]
pub async fn stop_concour(
server_id: u64,
channel_id: u64,
cron_scheduler: &mut ScheduleJob,
) -> Result<Option<Concour>, StopConcourError> {
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
Ok(list_concour) => list_concour,
@ -29,19 +35,43 @@ pub async fn stop_concour(
info!("Concour doesn't exist");
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 {
// Ok(_) => {}
// Err(err) => {
// tracing::error!(error = err.to_string(), "Error updating concour");
// return Err(StopConcourError::UnknownError(
// "Error updating concour".to_string(),
// ));
// }
// }
// Ok(Some(concour))
match concour.update().await {
Ok(_) => {}
Err(err) => {
tracing::error!(error = err.to_string(), "Error updating concour");
return Err(StopConcourError::UnknownError(
"Error updating concour".to_string(),
));
}
}
Ok(Some(concour))
}

View File

@ -3,11 +3,13 @@ use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
use surrealdb::opt::Resource;
use surrealdb::sql::Thing;
use tracing::instrument;
use utoipa::ToSchema;
const CONCOUR: &str = "concour";
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema, PartialEq, Eq)]
pub enum ConcourStatus {
Created,
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)]
pub struct Concour {
pub server_id: u64,
@ -34,7 +49,8 @@ pub struct Concour {
pub banner: Option<String>,
pub index_keyword: u64,
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 {
@ -52,6 +68,7 @@ impl Default for Concour {
index_keyword: 0,
status: ConcourStatus::Created,
winner: HashMap::new(),
last_message_id: None,
}
}
}
@ -71,8 +88,10 @@ impl Concour {
index_keyword: 0,
status: ConcourStatus::Created,
winner: HashMap::new(),
last_message_id: None,
})
}
#[instrument(level = "info")]
pub async fn create(&self) -> Result<(), surrealdb::Error> {
match DB.create(Resource::from(CONCOUR)).content(&self).await {
Ok(_) => {}
@ -82,21 +101,61 @@ impl Concour {
};
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!(
"UPDATE {} SET title = '{}', description = '{}', start_date = '{}', periode = '{}', role_récompense = {}, keywords = '{:?}', banner = '{:?}', index_keyword = {}, status = '{}', winner = '{:?}' 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
"SELECT id,server_id,channel_id FROM {} WHERE server_id = {} AND channel_id = {}",
CONCOUR, server_id, channel_id
);
match DB.query(sql).await {
Ok(res) => {
println!("{:?}", res);
let mut results = match DB.query(&sql).await {
Ok(results) => results,
Err(e) => {
return Err(e);
}
};
let concour: ConcourRecord = match results.take(0) {
Ok(Some(concour)) => concour,
Ok(None) => {
return Ok(None);
}
Err(e) => {
return Err(e);
}
};
Ok(())
Ok(Some(concour))
}
#[instrument(level = "info")]
pub async fn find_by_server_id_channel_id(
server_id: &u64,
channel_id: &u64,
@ -122,6 +181,7 @@ impl Concour {
};
Ok(Some(concour))
}
#[instrument(level = "info")]
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 {
@ -136,7 +196,7 @@ impl Concour {
}
Ok(concours)
}
#[instrument(level = "info")]
pub async fn find_by_status(status: &ConcourStatus) -> Result<Vec<Concour>, surrealdb::Error> {
let sql = format!("SELECT * FROM {} WHERE status = '{}'", CONCOUR, status);
let mut results = match DB.query(&sql).await {

View File

@ -2,6 +2,7 @@ use super::init::DB;
use serde::{Deserialize, Serialize};
use std::fmt;
use surrealdb::opt::Resource;
use tracing::instrument;
use utoipa::ToSchema;
const SERVER_CONFIG: &str = "server_config";
@ -37,6 +38,7 @@ impl ServerConfig {
admin_role: Vec::new(),
})
}
#[instrument(level = "info")]
pub async fn create(&self) -> Result<(), surrealdb::Error> {
match DB
.create(Resource::from(SERVER_CONFIG))
@ -47,6 +49,7 @@ impl ServerConfig {
Err(e) => Err(e),
}
}
#[instrument(level = "info")]
pub async fn update(&self) -> Result<(), surrealdb::Error> {
let sql = format!(
"UPDATE {} SET enable = {}, auto_meme = {}, auto_concour = {}, admin_role = {:?} WHERE server_id = {}",
@ -62,6 +65,7 @@ impl ServerConfig {
Err(e) => Err(e),
}
}
#[instrument(level = "info")]
pub async fn find_by_server_id(
server_id: &u64,
) -> Result<Option<ServerConfig>, surrealdb::Error> {

View File

@ -1,5 +1,6 @@
use serde::{Deserialize, Serialize};
use surrealdb::opt::Resource;
use tracing::instrument;
use utoipa::ToSchema;
use super::init::DB;
@ -21,7 +22,7 @@ impl User {
enable,
})
}
#[instrument(level = "info")]
pub async fn create(&self) -> Result<(), surrealdb::Error> {
match DB.create(Resource::from(USERIMAGE)).content(&self).await {
Ok(_) => {}
@ -31,7 +32,7 @@ impl User {
};
Ok(())
}
#[instrument(level = "info")]
pub async fn update(&self) -> Result<(), surrealdb::Error> {
let sql = format!(
"UPDATE {} SET enable = {} WHERE server_id = {} AND user_id = {}",
@ -47,7 +48,7 @@ impl User {
};
Ok(())
}
#[instrument(level = "info")]
pub async fn find_by_server_id_user_id(
server_id: &u64,
user_id: &u64,

View File

@ -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 tracing::{error, info, instrument};
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)]
pub struct ScheduleJob {
pub job_id: HashMap<(u64, u64), Uuid>,
pub job_id: Arc<RwLock<HashMap<(u64, u64), Uuid>>>,
pub scheduler: JobScheduler,
}
impl ScheduleJob {
#[instrument()]
#[instrument(level = "info")]
pub async fn start_cron_scheduler() -> Result<Self, ()> {
let scheduler = JobScheduler::new().await;
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 {
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
.scheduler
.remove(self.job_id.get(&(*server_id, *channel_id)).unwrap())
.remove(job_id.get(&(*server_id, *channel_id)).unwrap())
.await
{
Ok(_) => {
@ -57,6 +76,8 @@ impl ScheduleJob {
}
}
}
drop(job_id);
match self.scheduler.shutdown().await {
Ok(_) => {
info!("Cron scheduler stopped");
@ -69,8 +90,8 @@ impl ScheduleJob {
}
}
#[instrument(skip(self))]
pub async fn add_cron_job(
#[instrument(skip(self), level = "info")]
pub async fn add_concour_cron_job(
&mut self,
server_id: u64,
channel_id: u64,
@ -91,7 +112,10 @@ impl ScheduleJob {
match self.scheduler.add(job).await {
Ok(job_uid) => {
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)
}
Err(e) => {
@ -100,19 +124,30 @@ impl ScheduleJob {
}
}
}
#[instrument(skip(self))]
pub async fn stop_scheduled_job(&mut self, server_id: u64, channel_id: u64) {
match self.job_id.remove(&(server_id, channel_id)) {
#[instrument(skip(self), level = "info")]
pub async fn stop_scheduled_job(
&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 {
Ok(_) => {
info!("Cron job removed");
Ok(())
}
Err(e) => {
error!("Error removing cron job: {:?}", e);
Err(StopScheduleJob::RemoveFailed)
}
},
None => {
error!("Cron job not found");
Err(StopScheduleJob::JobNotFound)
}
}
}

View File

@ -79,7 +79,6 @@ async fn main() -> std::io::Result<()> {
.bind(("0.0.0.0", port))?
.run()
.await?;
cron_scheduler.stop_scheduled_job(123, 123).await;
info!("API Server stopped.");
tx_bot.send(()).unwrap();
cron_scheduler.stop_cron_scheduler().await;