diff --git a/src/reminder.rs b/src/reminder.rs index 7a599e0..6388997 100644 --- a/src/reminder.rs +++ b/src/reminder.rs @@ -24,10 +24,10 @@ pub async fn remind_all_tasks(ctx: &crate::Context, tasks: &[task::Task]) -> any }; let batching_interval = find_batching_interval(ctx, &info.due_date, task); - log::debug!("Reminding {task} with interval {batching_interval:?}."); + log::debug!("Reminder interval for {task} is {batching_interval:?}."); if !is_time_to_remind(ctx, &info.due_date, batching_interval) { - log::debug!("Not yet time, skipping."); + log::debug!("Not yet time to remind, skipping."); continue; } @@ -35,21 +35,27 @@ pub async fn remind_all_tasks(ctx: &crate::Context, tasks: &[task::Task]) -> any log::debug!("Task {task} is already overdue!"); } - if let Some((reminded_date, reminder_type)) = check_task_reminded(ctx, task).await? { - if reminder_type == ReminderType::Urgent { + match &info.reminded { + task::ReminderState::RemindedUrgently { .. } => { log::debug!("Was already reminded urgently, skipping."); - } else if &reminded_date < &info.due_date && is_overdue(ctx, &info.due_date) { - log::info!("Task {task} is now overdue, reminding again urgently..."); - remind_task(ctx, task, ReminderType::Urgent, batching_interval).await?; - } else { - log::debug!("Was already reminded, skipping."); } - continue; - } - log::info!("Reminding {task} ..."); - remind_task(ctx, task, ReminderType::Basic, batching_interval).await?; - reminded += 1; + task::ReminderState::Reminded { date } => { + if date < info.due_date && is_overdue(ctx, &info.due_date) { + log::info!("Task {task} is now overdue, reminding again urgently..."); + remind_task(ctx, task, ReminderType::Urgent, batching_interval).await?; + reminded += 1; + } else { + log::debug!("Was already reminded, skipping."); + } + } + + task::ReminderState::NotReminded => { + log::info!("Reminding {task} ..."); + remind_task(ctx, task, ReminderType::Basic, batching_interval).await?; + reminded += 1; + } + } } if reminded == 0 { @@ -64,62 +70,6 @@ pub async fn remind_all_tasks(ctx: &crate::Context, tasks: &[task::Task]) -> any pub const SIGNATURE_BASIC: &'static str = "\\[TaskBot Comment\\]"; pub const SIGNATURE_URGENT: &'static str = "\\[TaskBot Comment (Urgent)\\]"; -async fn check_task_reminded( - ctx: &crate::Context, - task: &task::Task, -) -> anyhow::Result> { - let mut timeline = ctx - .forgejo - .issue_get_comments_and_timeline( - &ctx.owner, - &ctx.repo, - task.issue_number.into(), - forgejo_api::structs::IssueGetCommentsAndTimelineQuery { - ..Default::default() - }, - ) - .all() - .await - .with_context(|| format!("Failed to fetch timeline for {task}"))?; - - // Should not be necessary, but let's be safe. - timeline.sort_by_key(|event| event.created_at); - - let mut has_reminder = None; - let mut has_urgent_reminder = None; - for event in timeline.iter().rev() { - match (event.r#type.as_deref(), &event.body) { - (Some("reopen"), _) => { - // When we find the event where the issue was last reopened, we stop. - break; - } - (Some("comment"), Some(body)) => { - if body.contains(SIGNATURE_URGENT) { - log::debug!("Found urgent reminder for issue #{}.", task.issue_number); - has_urgent_reminder = Some(created_at_time(event)?); - } else if body.contains(SIGNATURE_BASIC) { - log::debug!("Found reminder for issue #{}.", task.issue_number); - has_reminder = Some(created_at_time(event)?); - } - } - // Ignore all other events. - _ => (), - } - } - - let res = has_urgent_reminder - .map(|t| (t, ReminderType::Urgent)) - .or_else(|| has_reminder.map(|t| (t, ReminderType::Basic))); - - Ok(res) -} - -fn created_at_time(ev: &forgejo_api::structs::TimelineComment) -> anyhow::Result { - Ok(util::time_to_jiff(ev.created_at.with_context(|| { - format!("Timeline event {:?} without created_at time", ev.r#type,) - })?)) -} - async fn remind_task( ctx: &crate::Context, task: &task::Task,