use chrono::{DateTime, Duration, Timelike, Utc}; use once_cell::sync::Lazy; use reqwest::{Client}; use std::str::FromStr; use std::{collections::HashMap, error::Error, vec}; use std::fmt::Debug; use std::sync::{Arc}; use tokio::sync::{RwLock}; use std::thread::sleep; use dotenv::dotenv; use strum_macros::Display; use crate::config::Config; use crate::post_history::{SeriesHistory}; mod config; mod jnovel; mod bot; mod lemmy; mod tui; mod post_history; pub static HTTP_CLIENT: Lazy = Lazy::new(|| { let client = Client::builder() .timeout(Duration::seconds(30).to_std().unwrap()) .connect_timeout(Duration::seconds(30).to_std().unwrap()) .build() .expect("build client"); client }); #[derive(Clone, Debug)] pub(crate) struct SharedData { messages: Vec, config: Config, post_history: SeriesHistory, start: DateTime, } impl SharedData { pub(crate) fn new() -> Self { SharedData { messages: vec![], config: Config { instance: "".to_string(), status_post_url: None, config_reload_seconds: 0, series: vec![], }, post_history: SeriesHistory { series: HashMap::new(), }, start: Utc::now(), } } pub(crate) fn get_messages(&self, errors: bool, warnings: bool, infos: bool) -> Vec { self.messages.iter().filter(|msg| { match msg { Message::Error(_) => true && errors, Message::Warning(_) => true && warnings, Message::Info(_) => true && infos, } }).cloned().collect() } } #[derive(Clone, Debug, Display)] pub(crate) enum Message { Info(String), Warning(String), Error(String), } #[tokio::main] async fn main() { dotenv().ok(); let mut data = SharedData::new(); loop { let write_data = Arc::new(RwLock::new(data.clone())); let read_data = write_data.clone(); let persistent_data = write_data.clone(); let tui_thread = tokio::spawn(async move { tui::run(read_data).await }); let bot_thread = tokio::spawn(async move { bot::run(write_data).await }); let _ = bot_thread.await; tui_thread.abort(); data = persistent_data.read().await.clone(); data.messages.push(Message::Error(format!("Bot crashed due to unknown Error, restarting thread after wait..."))); sleep(Duration::seconds(5).to_std().expect("Conversion should always work since static")); } }