use crate::HandlerConfig; use anyhow::{anyhow, Context as _, Result}; use serenity::all::{Context, MessageBuilder}; use std::{sync::Arc, time::Duration}; use time::{Date, OffsetDateTime, Weekday}; use tokio::{ fs::{self, create_dir_all, File}, time::{interval, MissedTickBehavior}, }; static REACTS: &[char] = &['✅', '❌', '❔']; pub async fn start(config: Arc, ctx: Context) { let mut timer = interval(Duration::from_secs(1)); timer.set_missed_tick_behavior(MissedTickBehavior::Skip); loop { timer.tick().await; if let Err(err) = tick(&*config, &ctx).await { log::error!("{err:?}"); } } } async fn tick(config: &HandlerConfig, ctx: &Context) -> Result<()> { let now = OffsetDateTime::now_local().context("Failed to get current time")?; if now.weekday() != Weekday::Sunday { // Wait to post 'till Sunday. return Ok(()); } let mut now_path = config.db_dir.join("labwatch"); create_dir_all(&now_path) .await .with_context(|| anyhow!("Failed to create {now_path:?}"))?; now_path.push(date_name(now.date())); if fs::try_exists(&now_path) .await .with_context(|| anyhow!("Failed to check if {now_path:?} exists"))? { // Already posted this week. return Ok(()); } let mut date = now.date(); for _ in 1..=5 { date = date.next_day().context("Reached the end of times")?; let msg = MessageBuilder::new().push(date_name(date)).build(); let msg = config .labwatch_channel_id .say(&ctx.http, &msg) .await .with_context(|| anyhow!("Failed to send message for {date}"))?; for &react in REACTS { msg.react(&ctx.http, react).await.with_context(|| { anyhow!("Failed to react with {react} on the message for {date}") })?; } } File::create(&now_path) .await .with_context(|| anyhow!("Failed to create {now_path:?}"))?; Ok(()) } fn date_name(date: Date) -> String { format!("{}, {} {}", date.weekday(), date.month(), date.day()) }