feat: Mise en place de cronjob fonctionne avec une logique concour qui fonctionne
This commit is contained in:
parent
9c21b0dfdf
commit
0e4a8ae580
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -690,6 +690,7 @@ dependencies = [
|
||||
"actix-cors",
|
||||
"actix-web",
|
||||
"chrono",
|
||||
"cron",
|
||||
"dotenvy",
|
||||
"once_cell",
|
||||
"openssl",
|
||||
@ -709,6 +710,7 @@ dependencies = [
|
||||
"surrealdb",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-cron",
|
||||
"tokio-cron-scheduler",
|
||||
"toml",
|
||||
"tracing",
|
||||
@ -4277,6 +4279,19 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-cron"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b29e8f172aedef409e518b9b88ea7aeb47fd6248cf7673f0a8991c0913601a55"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"cron",
|
||||
"futures",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-cron-scheduler"
|
||||
version = "0.10.2"
|
||||
|
@ -48,6 +48,8 @@ tokio-cron-scheduler = { version = "0.10", features = [
|
||||
"signal",
|
||||
] }
|
||||
serde_with = "3.8.1"
|
||||
tokio-cron = "0.1.3"
|
||||
cron = "0.12.1"
|
||||
|
||||
|
||||
[[bin]]
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::botv2::{
|
||||
domain::concour::{
|
||||
check_if_allowed::check_if_allowed,
|
||||
@ -5,11 +7,13 @@ use crate::botv2::{
|
||||
},
|
||||
init::{Context, Error},
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use cron::Schedule;
|
||||
use poise::{
|
||||
serenity_prelude::{model::colour, CreateEmbed, CreateEmbedFooter, Mentionable, RoleId},
|
||||
CreateReply,
|
||||
};
|
||||
use tracing::{info, instrument};
|
||||
use tracing::{info, instrument, warn};
|
||||
|
||||
/// Update the step duration of a concour (only for admin)
|
||||
#[instrument(skip(ctx), level = "info", fields(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get()))]
|
||||
@ -21,7 +25,8 @@ use tracing::{info, instrument};
|
||||
)]
|
||||
pub async fn period(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Dureer d'une étape du concours"] step: u64,
|
||||
#[description = "Dureer d'une étape du concours au format CRON (min: 6H d'interval)"]
|
||||
cron_schedule: String,
|
||||
) -> Result<(), Error> {
|
||||
let guild = match ctx.guild_id() {
|
||||
Some(guild) => guild,
|
||||
@ -59,12 +64,11 @@ pub async fn period(
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let duration = match step.try_into() {
|
||||
Ok(val) => time::Duration::new(val, 0),
|
||||
let schedule = match Schedule::from_str(&cron_schedule) {
|
||||
Ok(schedule) => schedule,
|
||||
Err(_) => {
|
||||
info!("Invalid Duration input");
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Invalid duration input")
|
||||
.title("Invalid CRON format")
|
||||
.color(colour::Color::RED)
|
||||
.footer(footer);
|
||||
if let Err(why) = ctx
|
||||
@ -76,7 +80,37 @@ pub async fn period(
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let concour = match set_periode(guild.get(), ctx.channel_id().get(), duration).await {
|
||||
let next_to_come = schedule.upcoming(Utc).take(10);
|
||||
// Check if the next_to_come has at least 6 hours of interval
|
||||
let mut last: Option<DateTime<Utc>> = None;
|
||||
for next in next_to_come {
|
||||
if let Some(last) = last {
|
||||
if next.timestamp() - last.timestamp() < 6 * 60 * 60 {
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Interval between steps is too short")
|
||||
.description("Please provide a CRON schedule with at least 6 hours of interval")
|
||||
.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);
|
||||
}
|
||||
warn!(
|
||||
cron_schedule = cron_schedule,
|
||||
"Interval between steps is too short"
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
last = Some(next);
|
||||
}
|
||||
info!(
|
||||
cron_schedule = cron_schedule.as_str(),
|
||||
"Setting concour periode"
|
||||
);
|
||||
let concour = match set_periode(guild.get(), ctx.channel_id().get(), cron_schedule).await {
|
||||
Ok(concour) => {
|
||||
if concour.is_none() {
|
||||
CreateEmbed::new()
|
||||
|
@ -57,7 +57,6 @@ pub async fn start(ctx: Context<'_>) -> Result<(), Error> {
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
let (concour, success) = match start_concour(
|
||||
guild.get(),
|
||||
ctx.channel_id().get(),
|
||||
@ -85,11 +84,11 @@ pub async fn start(ctx: Context<'_>) -> Result<(), Error> {
|
||||
concour.index_keyword + 1
|
||||
))
|
||||
.description(concour.description)
|
||||
.field("Mot du jours ", keyword.to_string(), false)
|
||||
.field("Word of the day ", keyword.to_string(), false)
|
||||
.field("Good luck !", "", false)
|
||||
.field(
|
||||
"Vous avez jusqu'a demain 17h",
|
||||
"HARD CODED FOR THE MOMENT",
|
||||
"Please see when the concour end in the concour get command",
|
||||
"",
|
||||
false,
|
||||
)
|
||||
.color(colour::Color::DARK_GREEN);
|
||||
@ -110,6 +109,9 @@ pub async fn start(ctx: Context<'_>) -> Result<(), Error> {
|
||||
StartConcourError::FinishedKeyWordList => CreateEmbed::new()
|
||||
.title("Finished keyword list, add new one")
|
||||
.color(colour::Color::RED),
|
||||
StartConcourError::RoleRecompenseEmpty => CreateEmbed::new()
|
||||
.title("Role recompense not defined")
|
||||
.color(colour::Color::RED),
|
||||
_ => CreateEmbed::new()
|
||||
.title("Error while creating concour")
|
||||
.field("Please contact your administrator", "", false)
|
||||
|
@ -14,7 +14,7 @@ pub enum SetPeriodeConcourError {
|
||||
pub async fn set_periode(
|
||||
server_id: u64,
|
||||
channel_id: u64,
|
||||
periode: time::Duration,
|
||||
periode: String,
|
||||
) -> Result<Option<Concour>, SetPeriodeConcourError> {
|
||||
let concour = match Concour::find_by_server_id_channel_id(&server_id, &channel_id).await {
|
||||
Ok(list_concour) => list_concour,
|
||||
|
@ -13,6 +13,7 @@ pub enum StartConcourError {
|
||||
DoesntExist,
|
||||
KeyWordListEmpty,
|
||||
FinishedKeyWordList,
|
||||
RoleRecompenseEmpty,
|
||||
FindError(String),
|
||||
UnknownError(String),
|
||||
}
|
||||
@ -39,6 +40,10 @@ pub async fn start_concour(
|
||||
return Err(StartConcourError::DoesntExist);
|
||||
}
|
||||
let mut concour = concour.unwrap();
|
||||
if concour.role_recompense == 0 {
|
||||
tracing::warn!("Role recompense is empty");
|
||||
return Err(StartConcourError::RoleRecompenseEmpty);
|
||||
}
|
||||
if concour.keywords.is_empty() {
|
||||
tracing::warn!("Keyword list is empty");
|
||||
return Err(StartConcourError::KeyWordListEmpty);
|
||||
@ -53,7 +58,7 @@ pub async fn start_concour(
|
||||
return Err(StartConcourError::AlreadyOnGoing);
|
||||
}
|
||||
match cron_scheduler
|
||||
.add_concour_cron_job(server_id, channel_id, "*/1 * * * * *".to_string(), http)
|
||||
.add_concour_cron_job(server_id, channel_id, concour.periode.clone(), http)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {}
|
||||
|
@ -4,8 +4,9 @@ use poise::serenity_prelude as serenity;
|
||||
use rand::Rng;
|
||||
use serenity::all::{CreateAttachment, CreateMessage};
|
||||
use tokio::fs::File;
|
||||
use tracing::info;
|
||||
use tracing::{info, instrument};
|
||||
|
||||
#[instrument(skip(ctx, _framework, data), err, level = "trace")]
|
||||
pub async fn event_handler(
|
||||
ctx: &serenity::Context,
|
||||
event: &serenity::FullEvent,
|
||||
|
@ -1,6 +1,5 @@
|
||||
use super::init::DB;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use surrealdb::opt::Resource;
|
||||
use surrealdb::sql::Thing;
|
||||
@ -34,6 +33,7 @@ pub struct ConcourRecord {
|
||||
pub struct ConcourWinner {
|
||||
pub user_id: u64,
|
||||
pub date: chrono::DateTime<chrono::Utc>,
|
||||
pub keyword: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
|
||||
@ -43,13 +43,13 @@ pub struct Concour {
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub start_date: chrono::DateTime<chrono::Utc>,
|
||||
pub periode: time::Duration,
|
||||
pub periode: String,
|
||||
pub role_recompense: u64,
|
||||
pub keywords: Vec<String>,
|
||||
pub banner: Option<String>,
|
||||
pub index_keyword: u64,
|
||||
pub status: ConcourStatus,
|
||||
pub winner: HashMap<String, ConcourWinner>,
|
||||
pub winner: Vec<ConcourWinner>,
|
||||
pub last_message_id: Option<u64>,
|
||||
}
|
||||
|
||||
@ -61,13 +61,13 @@ impl Default for Concour {
|
||||
title: String::new(),
|
||||
description: String::new(),
|
||||
start_date: chrono::Utc::now(),
|
||||
periode: time::Duration::days(1),
|
||||
periode: "0 0 17 * * * *".to_string(),
|
||||
role_recompense: 0,
|
||||
keywords: Vec::new(),
|
||||
banner: None,
|
||||
index_keyword: 0,
|
||||
status: ConcourStatus::Created,
|
||||
winner: HashMap::new(),
|
||||
winner: Vec::new(),
|
||||
last_message_id: None,
|
||||
}
|
||||
}
|
||||
@ -81,13 +81,13 @@ impl Concour {
|
||||
title: String::new(),
|
||||
description: String::new(),
|
||||
start_date: chrono::Utc::now(),
|
||||
periode: time::Duration::days(1),
|
||||
periode: "0 0 17 * * * *".to_string(),
|
||||
role_recompense: 0,
|
||||
keywords: Vec::new(),
|
||||
banner: None,
|
||||
index_keyword: 0,
|
||||
status: ConcourStatus::Created,
|
||||
winner: HashMap::new(),
|
||||
winner: Vec::new(),
|
||||
last_message_id: None,
|
||||
})
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1,2 +1 @@
|
||||
pub mod concour;
|
||||
pub mod schedule_job;
|
||||
|
@ -1,4 +1,6 @@
|
||||
use poise::serenity_prelude::Http;
|
||||
use poise::serenity_prelude::{
|
||||
Color, CreateEmbed, CreateMessage, Http, Mentionable, MessagePagination,
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::{self, Display},
|
||||
@ -6,10 +8,10 @@ use std::{
|
||||
};
|
||||
use tokio::sync::RwLock;
|
||||
use tokio_cron_scheduler::{Job, JobScheduler};
|
||||
use tracing::{error, info, instrument};
|
||||
use tracing::{error, info, info_span, instrument, Instrument};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::db::concour::{Concour, ConcourStatus};
|
||||
use crate::db::concour::{Concour, ConcourStatus, ConcourWinner};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StopScheduleJob {
|
||||
@ -23,12 +25,20 @@ impl Display for StopScheduleJob {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ScheduleJob {
|
||||
pub job_id: Arc<RwLock<HashMap<(u64, u64), Uuid>>>,
|
||||
pub scheduler: JobScheduler,
|
||||
}
|
||||
|
||||
impl Clone for ScheduleJob {
|
||||
fn clone(&self) -> Self {
|
||||
ScheduleJob {
|
||||
job_id: self.job_id.clone(),
|
||||
scheduler: self.scheduler.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ScheduleJob {
|
||||
#[instrument(level = "info")]
|
||||
pub async fn start_cron_scheduler() -> Result<Self, ()> {
|
||||
@ -72,12 +82,7 @@ impl ScheduleJob {
|
||||
};
|
||||
for concour in concours {
|
||||
match self
|
||||
.add_concour_cron_job(
|
||||
concour.server_id,
|
||||
concour.channel_id,
|
||||
"0 0 17 * * *".to_string(),
|
||||
http,
|
||||
)
|
||||
.add_concour_cron_job(concour.server_id, concour.channel_id, concour.periode, http)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
@ -124,30 +129,293 @@ impl ScheduleJob {
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, _http), level = "info")]
|
||||
#[instrument(skip(self, http), level = "info")]
|
||||
pub async fn add_concour_cron_job(
|
||||
&mut self,
|
||||
server_id: u64,
|
||||
channel_id: u64,
|
||||
cron_expression: String,
|
||||
_http: &Http,
|
||||
http: &Http,
|
||||
) -> Result<Uuid, ()> {
|
||||
let job = match Job::new_async(cron_expression.as_str(), |uuid, _l| {
|
||||
Box::pin(async move {
|
||||
// Send the message to announce the end of the concour
|
||||
// Get concour data
|
||||
// Get All message since the announcement
|
||||
// filter out the bot's message
|
||||
// count the number of reactions per message
|
||||
// get the user comment with the highest reaction
|
||||
// announce the winner
|
||||
// Give the winner the role reward
|
||||
// update concour with the winner and increment the index
|
||||
// Announce the next concour
|
||||
// Or not if there is no more keyword
|
||||
info!("Cron job fired: {:?}", uuid);
|
||||
})
|
||||
}) {
|
||||
let http = Arc::new(Http::new(http.token()));
|
||||
let job = match Job::new_cron_job_async_tz(
|
||||
cron_expression.as_str(),
|
||||
chrono::Local,
|
||||
move |uuid, _l| {
|
||||
Box::pin(
|
||||
{
|
||||
let http = http.clone();
|
||||
Box::pin(async move {
|
||||
info!(id = uuid.to_string(), "Cron job fired");
|
||||
// Get concour data
|
||||
let concour = match Concour::find_by_server_id_channel_id(
|
||||
&server_id,
|
||||
&channel_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(concour) => concour,
|
||||
Err(e) => {
|
||||
error!("Error getting concour: {:?}", e);
|
||||
// Disable the concour ?
|
||||
return;
|
||||
}
|
||||
};
|
||||
if concour.is_none() {
|
||||
error!("Concour not found");
|
||||
return;
|
||||
}
|
||||
let mut concour = concour.unwrap();
|
||||
// Send the message to announce the end of the concour
|
||||
let current_keyword = concour
|
||||
.keywords
|
||||
.get(concour.index_keyword as usize)
|
||||
.unwrap();
|
||||
let embed = CreateEmbed::default()
|
||||
.title(format!(
|
||||
"Concour has ended Day {} has ended",
|
||||
concour.index_keyword + 1
|
||||
))
|
||||
.description("Processing the results...")
|
||||
.field("Title", concour.title.clone(), false)
|
||||
.field("Description", concour.description.clone(), false)
|
||||
.field("Word of the day", current_keyword, false)
|
||||
.color(Color::DARK_GREEN);
|
||||
let reply = CreateMessage::default().embed(embed);
|
||||
let last_id =
|
||||
match http.send_message(channel_id.into(), vec![], &reply).await {
|
||||
Ok(message) => message.id,
|
||||
Err(e) => {
|
||||
error!("Error sending message: {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
// Check if the concour is still enabledl
|
||||
if concour.status != ConcourStatus::OnGoing
|
||||
|| concour.last_message_id.is_none()
|
||||
{
|
||||
info!("Concour is not enabled");
|
||||
return;
|
||||
}
|
||||
// Get All message since the announcement
|
||||
let message_pagination =
|
||||
MessagePagination::After(concour.last_message_id.unwrap().into());
|
||||
let mut messages = match http
|
||||
.get_messages(channel_id.into(), Some(message_pagination), None)
|
||||
.await
|
||||
{
|
||||
Ok(messages) => messages,
|
||||
Err(e) => {
|
||||
error!("Error getting messages: {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if messages.is_empty() {
|
||||
error!("No message found");
|
||||
let embed: CreateEmbed = CreateEmbed::default()
|
||||
.title("An error has occured while fetching the messages")
|
||||
.color(Color::DARK_RED);
|
||||
let reply = CreateMessage::default().embed(embed);
|
||||
if let Err(err) =
|
||||
http.send_message(channel_id.into(), vec![], &reply).await
|
||||
{
|
||||
error!("Error sending message: {:?}", err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if messages.last().unwrap().id != last_id {
|
||||
info!("Fetching more messages because last one is not the last id");
|
||||
loop {
|
||||
let message_pagination = MessagePagination::After(
|
||||
messages.last().unwrap().id.into(),
|
||||
);
|
||||
let mut new_messages = match http
|
||||
.get_messages(
|
||||
channel_id.into(),
|
||||
Some(message_pagination),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(messages) => messages,
|
||||
Err(e) => {
|
||||
error!("Error getting messages: {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if new_messages.is_empty() {
|
||||
info!("No more messages found");
|
||||
break;
|
||||
}
|
||||
messages.append(&mut new_messages);
|
||||
if messages.last().unwrap().id == last_id {
|
||||
info!("Last message found");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// filter out the bot's message
|
||||
messages.retain(|message| !message.author.bot);
|
||||
info!(
|
||||
nbr_message = messages.len(),
|
||||
"{} messages found",
|
||||
messages.len()
|
||||
);
|
||||
// count the number of reactions per message
|
||||
let mut max_reaction = 0;
|
||||
let mut max_winner = None;
|
||||
messages.into_iter().for_each(|msg| {
|
||||
// test
|
||||
let count = msg
|
||||
.reactions
|
||||
.into_iter()
|
||||
.fold(0, |acc, reaction| acc + reaction.count);
|
||||
if count > max_reaction {
|
||||
max_reaction = count;
|
||||
max_winner = Some(msg.author);
|
||||
}
|
||||
});
|
||||
// announce the winner
|
||||
let winner = match max_winner {
|
||||
Some(winner) => winner,
|
||||
None => {
|
||||
let embed = CreateEmbed::default()
|
||||
.title("No winner found, What happened ?")
|
||||
.color(Color::DARK_RED);
|
||||
let reply = CreateMessage::default().embed(embed);
|
||||
if let Err(err) =
|
||||
http.send_message(channel_id.into(), vec![], &reply).await
|
||||
{
|
||||
error!("Error sending message: {:?}", err);
|
||||
}
|
||||
error!("No winner found");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let embed = CreateEmbed::default()
|
||||
.title("Winner")
|
||||
.description(format!("The winner is {}", winner.mention()))
|
||||
.color(Color::DARK_GREEN);
|
||||
let reply = CreateMessage::default().embed(embed);
|
||||
if let Err(err) =
|
||||
http.send_message(channel_id.into(), vec![], &reply).await
|
||||
{
|
||||
error!("Error sending message: {:?}", err);
|
||||
}
|
||||
let (add, previous) = match concour.winner.last() {
|
||||
Some(previous_winner) => (
|
||||
previous_winner.user_id != winner.id.get(),
|
||||
previous_winner.user_id,
|
||||
),
|
||||
None => (true, 0),
|
||||
};
|
||||
// Remove the role from the previous winner
|
||||
// Give the winner the role reward
|
||||
if add {
|
||||
if previous != 0 {
|
||||
match http
|
||||
.remove_member_role(
|
||||
server_id.into(),
|
||||
previous.into(),
|
||||
concour.role_recompense.into(),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
info!("Role removed from the previous winner");
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Error removing role from the previous winner: {:?}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
match http
|
||||
.add_member_role(
|
||||
server_id.into(),
|
||||
winner.id,
|
||||
concour.role_recompense.into(),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
info!("Role added to the winner");
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error adding role to the winner: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update concour with the winner and increment the index
|
||||
concour.winner.push(ConcourWinner {
|
||||
user_id: winner.id.get(),
|
||||
date: chrono::Utc::now(),
|
||||
keyword: current_keyword.to_string(),
|
||||
});
|
||||
concour.index_keyword += 1;
|
||||
if concour.index_keyword as usize >= concour.keywords.len() {
|
||||
concour.status = ConcourStatus::Finished;
|
||||
let embed = CreateEmbed::default()
|
||||
.title("Concour has ended")
|
||||
.description("The concour has ended, no more keyword")
|
||||
.color(Color::DARK_GREEN);
|
||||
let reply = CreateMessage::default().embed(embed);
|
||||
if let Err(err) =
|
||||
http.send_message(channel_id.into(), vec![], &reply).await
|
||||
{
|
||||
error!("Error sending message: {:?}", err);
|
||||
}
|
||||
info!("Concour has ended, no more keyword");
|
||||
return;
|
||||
}
|
||||
let next_keyword = concour
|
||||
.keywords
|
||||
.get(concour.index_keyword as usize)
|
||||
.unwrap();
|
||||
let output = CreateEmbed::new()
|
||||
.title(format!(
|
||||
"Concour: {} Jour : {}",
|
||||
concour.title.clone(),
|
||||
concour.index_keyword + 1
|
||||
))
|
||||
.description(concour.description.clone())
|
||||
.field("Word of the day ", next_keyword.to_string(), false)
|
||||
.field("Good luck !", "", false)
|
||||
.field(
|
||||
"Please see when the concour end in the concour get command",
|
||||
"",
|
||||
false,
|
||||
)
|
||||
.color(Color::DARK_GREEN);
|
||||
let reply = CreateMessage::default().embed(output);
|
||||
let last_id =
|
||||
match http.send_message(channel_id.into(), vec![], &reply).await {
|
||||
Ok(message) => message.id,
|
||||
Err(e) => {
|
||||
error!("Error sending message: {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
concour.last_message_id = Some(last_id.get());
|
||||
match concour.update().await {
|
||||
Ok(_) => {
|
||||
info!("Concour updated");
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error updating concour: {:?}", e);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
.instrument(info_span!("ConcourJob", id = uuid.to_string())),
|
||||
)
|
||||
},
|
||||
) {
|
||||
Ok(job) => job,
|
||||
Err(e) => {
|
||||
error!("Error creating cron job: {:?}", e);
|
||||
|
Loading…
Reference in New Issue
Block a user