136 lines
4.6 KiB
Rust
136 lines
4.6 KiB
Rust
use crate::{config::{Config}, HTTP_CLIENT};
|
|
use crate::lemmy::{Lemmy};
|
|
use crate::post_history::{SeriesHistory};
|
|
use chrono::{DateTime, Duration, Utc};
|
|
use std::sync::{Arc, RwLock};
|
|
use notify::{Event, EventKind, event::{AccessKind, AccessMode}, RecursiveMode, Watcher};
|
|
use tokio::time::sleep;
|
|
use systemd_journal_logger::connected_to_journal;
|
|
|
|
macro_rules! debug {
|
|
($msg:tt) => {
|
|
match connected_to_journal() {
|
|
true => log::debug!("[DEBUG] {}", $msg),
|
|
false => println!("[DEBUG] {}", $msg),
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! info {
|
|
($msg:tt) => {
|
|
match connected_to_journal() {
|
|
true => log::info!("[INFO] {}", $msg),
|
|
false => println!("[INFO] {}", $msg),
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! error {
|
|
($msg:tt) => {
|
|
match connected_to_journal() {
|
|
true => log::error!("[ERROR] {}", $msg),
|
|
false => eprintln!("[ERROR] {}", $msg),
|
|
}
|
|
};
|
|
}
|
|
|
|
pub(crate) struct Bot {
|
|
shared_config: Arc<RwLock<Config>>,
|
|
history: SeriesHistory,
|
|
run_start_time: DateTime<Utc>
|
|
}
|
|
|
|
enum Wait {
|
|
Absolute,
|
|
Buffer
|
|
}
|
|
|
|
impl Bot {
|
|
pub(crate) fn new() -> Self {
|
|
let config = Config::load();
|
|
let shared_config: Arc<RwLock<Config>> = Arc::new(RwLock::new(config));
|
|
|
|
let shared_config_copy = shared_config.clone();
|
|
let mut watcher = notify::recommended_watcher(move |res: Result<Event, notify::Error>| {
|
|
match res {
|
|
Ok(event) => {
|
|
if event.kind == EventKind::Access(AccessKind::Close(AccessMode::Write)) {
|
|
let mut write = shared_config_copy.write().expect("Write Lock Failed");
|
|
let new_config = Config::load();
|
|
write.series = new_config.series;
|
|
write.instance = new_config.instance;
|
|
write.protected_communities = new_config.protected_communities;
|
|
write.status_post_url = new_config.status_post_url;
|
|
info!("Reloaded Configuration");
|
|
}
|
|
},
|
|
Err(e) => {
|
|
let msg = format!("Error watching files: {e}");
|
|
error!(msg);
|
|
}
|
|
}
|
|
}).expect("Watcher Error");
|
|
|
|
watcher.watch(&Config::get_path(), RecursiveMode::NonRecursive).expect("Error in watcher");
|
|
|
|
let history: SeriesHistory = SeriesHistory::load_history();
|
|
|
|
Bot { shared_config, history, run_start_time: Utc::now() }
|
|
}
|
|
pub(crate) async fn run(&mut self) {
|
|
loop {
|
|
let mut lemmy = match Lemmy::new(&self.shared_config).await {
|
|
Ok(data) => data,
|
|
Err(_) => continue,
|
|
};
|
|
|
|
lemmy.get_communities().await;
|
|
|
|
self.history = SeriesHistory::load_history();
|
|
|
|
let start: DateTime<Utc> = Utc::now();
|
|
while Utc::now() - start <= Duration::minutes(60) {
|
|
self.run_start_time = Utc::now();
|
|
self.ping_status().await;
|
|
let read_copy = self.shared_config.read().expect("Read Lock Failed").clone();
|
|
for series in read_copy.series {
|
|
series.update(&mut self.history, &lemmy, &self.shared_config).await;
|
|
debug!("Done Updating Series");
|
|
self.wait(1, Wait::Absolute).await;
|
|
}
|
|
debug!("Awaiting Timeout");
|
|
self.wait(30, Wait::Buffer).await;
|
|
debug!("Pinging Server");
|
|
self.ping_status().await;
|
|
debug!("Awaiting Timeout 2");
|
|
self.wait(30, Wait::Absolute).await;
|
|
}
|
|
|
|
lemmy.logout().await;
|
|
}
|
|
}
|
|
|
|
async fn ping_status(&self) {
|
|
let read_config = &self.shared_config.read().expect("Read Lock Failed").clone();
|
|
if let Some(status_url) = &read_config.status_post_url {
|
|
match HTTP_CLIENT.get(status_url).send().await {
|
|
Ok(_) => {},
|
|
Err(e) => {
|
|
let err_msg = format!("While pinging status URL: {e}");
|
|
error!(err_msg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn wait(&self, seconds: i64, start_time: Wait) {
|
|
let duration: Duration = Duration::seconds(seconds);
|
|
let start_time: DateTime<Utc> = match start_time {
|
|
Wait::Absolute => Utc::now(),
|
|
Wait::Buffer => self.run_start_time,
|
|
};
|
|
while Utc::now() - start_time < duration {
|
|
sleep(Duration::milliseconds(100).to_std().unwrap()).await
|
|
}
|
|
}
|
|
}
|