1use std::{
2 collections::{BTreeMap, HashSet},
3 fs::File,
4 io::{BufReader, Read},
5 path::Path,
6 sync::{Arc, Mutex},
7 time::{SystemTime, UNIX_EPOCH},
8};
9
10use file_lock::{FileLock, FileOptions};
11use notify::{event::ModifyKind::Data, EventKind, RecommendedWatcher, Watcher};
12use serde::{Deserialize, Serialize};
13use tokio::{
14 sync::mpsc,
15 time::{interval, Duration},
16};
17
18use super::{Database, EventId, UserId};
19
20#[derive(Debug, Serialize, Deserialize, Clone)]
21pub struct Event {
22 pub id: EventId,
23 pub name: String,
24 pub description: String,
25 pub next_occurence: u64,
26 pub users: HashSet<UserId>,
27 pub repeats: Repeatability,
28 pub priority: Priority,
29}
30impl Event {
31 pub fn save_to_db(self, db: &Database) {
32 db.add_event(self);
33 }
34}
35impl PartialEq for Event {
36 fn eq(&self, other: &Self) -> bool {
37 self.id == other.id
38 }
39}
40impl Eq for Event {}
41
42#[derive(Debug, Default, Serialize, Deserialize, Clone)]
43pub enum Repeatability {
44 Yearly,
45 Biyearly,
46 Quarterly,
47 Monthly,
48 Bimonthly,
49 Weekly,
50 Daily,
51 Hourly,
52 #[default]
53 Never,
54}
55
56#[derive(Debug, Default, Serialize, Deserialize, Clone)]
57pub enum Priority {
58 Urgent,
59 VeryHigh,
60 High,
61 Medium,
62 #[default]
63 Low,
64 Minimal,
65}
66
67#[derive(Debug, Default)]
68pub struct EventBuilder {
69 id: EventId,
70 name: String,
71 description: String,
72 next_occurence: u64,
73 users: HashSet<UserId>,
74 repeats: Repeatability,
75 priority: Priority,
76}
77impl EventBuilder {
78 pub fn new(id: EventId, name: &str, next_occurence: u64) -> Self {
79 Self {
80 id,
81 name: String::from(name),
82 next_occurence,
83 ..Self::default()
84 }
85 }
86 pub fn description(mut self, desc: &str) -> Self {
87 self.description = String::from(desc);
88 self
89 }
90 pub fn users<I>(mut self, users: I) -> Self
91 where
92 I: IntoIterator<Item = UserId>,
93 {
94 for user in users {
95 self.users.insert(user);
96 }
97 self
98 }
99 pub fn repeats(mut self, repeats: Repeatability) -> Self {
100 self.repeats = repeats;
101 self
102 }
103 pub fn priority(mut self, priority: Priority) -> Self {
104 self.priority = priority;
105 self
106 }
107 pub fn build(self) -> Event {
108 Event {
109 id: self.id,
110 name: self.name,
111 description: self.description,
112 next_occurence: self.next_occurence,
113 users: self.users,
114 repeats: self.repeats,
115 priority: self.priority,
116 }
117 }
118}
119#[non_exhaustive]
120#[derive(Debug)]
121pub struct EventListener {
122 sender: mpsc::Sender<Event>,
123 refresh_rate: u64,
124}
125impl EventListener {
126 pub fn new(sender: mpsc::Sender<Event>, refresh_rate: u64) -> Self {
127 Self {
128 sender,
129 refresh_rate,
130 }
131 }
132 pub async fn start(self) {
133 let options = FileOptions::new().read(true).write(true).create(true);
135 let mut filelock = FileLock::lock("./db/event_cache.ron", true, options).unwrap();
136 let mut bytes = vec![];
137 filelock.file.read_to_end(&mut bytes).unwrap();
138 let event_cache: BTreeMap<u64, u64> = ron::de::from_bytes(&bytes).unwrap();
139 let event_cache = Arc::new(Mutex::new(event_cache));
140 let copy = Arc::clone(&event_cache);
141
142 let _watcher = tokio::spawn(async move {
143 let event_cache = Arc::clone(&event_cache);
144
145 let (tx, rx) = std::sync::mpsc::channel();
146 let mut w = RecommendedWatcher::new(tx, notify::Config::default()).unwrap();
147 w.watch(
148 Path::new("./db/event_cache.ron"),
149 notify::RecursiveMode::Recursive,
150 )
151 .unwrap();
152 while let Ok(f_ev) = rx.recv() {
153 if let Ok(file_event) = f_ev {
154 match file_event.kind {
155 EventKind::Modify(Data(_)) => {
156 let options = FileOptions::new().read(true).write(true).create(true);
157 let mut filelock =
158 FileLock::lock("./db/event_cache.ron", true, options).unwrap();
159 let mut bytes = vec![];
160 filelock.file.read_to_end(&mut bytes).unwrap();
161 let mut event_cache = event_cache.lock().unwrap();
162 *event_cache =
163 ron::de::from_bytes::<BTreeMap<u64, u64>>(&bytes).unwrap();
164 }
165 _ => (),
166 }
167 }
168 }
169 });
170 let mut interval = interval(Duration::from_millis(self.refresh_rate));
171 let mut ids: Vec<u64> = vec![];
172 loop {
173 let now = SystemTime::now()
174 .duration_since(UNIX_EPOCH)
175 .unwrap()
176 .as_secs();
177 if Self::has_passed_event(now, ©.lock().unwrap()) {
178 let mut lock = copy.lock().unwrap();
179 for (_, id) in lock.range(..now) {
180 ids.push(*id);
181 }
182 lock.retain(|k, _| *k >= now);
183 let writer = File::create("./db/event_cache.ron").unwrap();
184 ron::ser::to_writer(writer, &*lock).unwrap();
185 drop(lock);
186 }
187 if !ids.is_empty() {
188 for id in &ids {
189 let buf = BufReader::new(File::open(format!("./db/events/{id}.ron")).unwrap());
190 let e: Event = ron::de::from_reader(buf).unwrap();
191 self.sender.send(e.clone()).await.unwrap();
192 }
193 ids.clear();
194 }
195 interval.tick().await;
196 }
197 }
198 fn has_passed_event(now: u64, events: &BTreeMap<u64, u64>) -> bool {
199 if let Some((k, _)) = events.first_key_value() {
200 *k <= now
201 } else {
202 false
203 }
204 }
205}