1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use async_trait::async_trait;
use chrono::prelude::*;
use chrono::Utc;

use crate::trigger;

#[derive(Clone, Debug)]
pub enum Day {
  Mon,
  Tue,
  Wed,
  Thu,
  Fri,
  Sat,
  Sun,
}

#[derive(Clone, Debug)]
pub struct Time(u32, u32);

fn day_to_chrono_day(day: &Day) -> Weekday {
  match day {
    Day::Mon => Weekday::Mon,
    Day::Tue => Weekday::Tue,
    Day::Wed => Weekday::Wed,
    Day::Thu => Weekday::Thu,
    Day::Fri => Weekday::Fri,
    Day::Sat => Weekday::Sat,
    Day::Sun => Weekday::Sun,
  }
}

#[derive(Clone, Debug)]
struct Trigger {
  interval: Option<i64>,
  day: Option<Day>,
  time: Option<Time>,
}

#[async_trait]
impl trigger::Fire for Trigger {
  async fn should_run(&mut self) -> bool {
    let now = Utc::now();
    let day_match = match &self.day {
      Some(d) => now.weekday() == day_to_chrono_day(d),
      None => true,
    };

    let time_match = match &self.time {
      Some(Time(h, m)) => {
        let hour = now.hour();
        let min = now.minute();

        &min == m && &hour == h
      }
      None => true,
    };

    day_match && time_match
  }

  async fn next(&mut self) -> Option<i64> {
    let run: bool = self.should_run().await;

    if run {
      let now = Utc::now().timestamp_nanos();
      match self.interval.clone() {
        Some(interval) => Some(now + interval),
        None => None
      }
    } else {
      None
    }
  }

  fn vclone(&self) -> Box<dyn trigger::Fire> {
    Box::new(self.clone())
  }
}