#![feature(try_blocks)] #![feature(drain_filter)] mod app; use tokio::runtime::{Builder, Handle}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use crate::app::{ State, config::Config, user_config::UserConfig, }; use std::path::Path; use tokio::fs::OpenOptions; use futures::FutureExt; use std::sync::Arc; fn main() -> anyhow::Result<()> { let runtime = Builder::new_multi_thread() .enable_all() .build()?; let handle = runtime.handle().clone(); runtime.block_on(inner(handle)) } async fn inner(runtime: Handle) -> anyhow::Result<()> { let mut uc_toml = String::new(); tokio::fs::File::open("config.toml").await?.read_to_string(&mut uc_toml).await?; let user_config: UserConfig = toml::from_str(&uc_toml)?; let c_path = Path::new("data.json"); let config: Config = if c_path.exists() { let mut c_json = String::new(); tokio::fs::File::open(c_path).await?.read_to_string(&mut c_json).await?; serde_json::from_str(&c_json)? } else { Config::default() }; let state = State::new(runtime, user_config, config).await?; save_config(c_path, Arc::clone(&state)).await?; tokio::signal::ctrl_c() .then(|_| save_config(c_path, Arc::clone(&state))) .await?; Ok(()) } async fn save_config(path: &Path, state: Arc) -> anyhow::Result<()> { let mut config_file = OpenOptions::new() .create(true) .write(true) .truncate(true) .open(path) .await?; config_file.write_all(&serde_json::to_vec(&*state.config.read().await)?).await?; Ok(()) }