Compare commits

...

3 Commits

Author SHA1 Message Date
f5edc44717 config: Make error handling a little bit nicer
* Implement the std::error::Error trait and add a Result type
 * Propagate generic io::Error and serde_yaml::Error using From
 * Move the Result and Error types to the bottom of the module
2025-05-15 21:27:57 +00:00
73ee8114ca matrix: login_and_sync does not need to be generic 2025-05-15 21:06:54 +00:00
3fee20f0cf main: Panic explicitely when failing to initialize the state db 2025-05-15 21:01:59 +00:00
3 changed files with 42 additions and 20 deletions

View File

@ -18,16 +18,7 @@
*/ */
use serde::Deserialize; use serde::Deserialize;
use std::{fs, io}; use std::{fs, io, fmt};
#[derive(Debug)]
#[allow(dead_code)]
pub enum Error {
FileNotFoundError(String),
PermissionDeniedError(),
InvalidFormatError(serde_yaml::Error),
IoError(io::Error),
}
#[derive(Deserialize, Clone, Debug)] #[derive(Deserialize, Clone, Debug)]
pub struct FeedConfig { pub struct FeedConfig {
@ -46,19 +37,49 @@ pub struct Config {
} }
impl Config { impl Config {
pub fn load(config_file: &str) -> Result<Self, Error> { pub fn load(config_file: &str) -> Result<Self> {
let serialized_config = fs::read_to_string(config_file).map_err(|e| { let serialized_config = fs::read_to_string(config_file).map_err(|e| {
match e.kind() { match e.kind() {
io::ErrorKind::NotFound => Error::FileNotFoundError(config_file.into()), io::ErrorKind::NotFound => Error::FileNotFoundError(config_file.into()),
io::ErrorKind::PermissionDenied => Error::PermissionDeniedError(), io::ErrorKind::PermissionDenied => Error::PermissionDeniedError(),
_ => Error::IoError(e), _ => e.into(),
} }
})?; })?;
let config: Config = serde_yaml::from_str(&serialized_config) let config: Config = serde_yaml::from_str(&serialized_config)?;
.map_err(|e| Error::InvalidFormatError(e))?;
Ok(config) Ok(config)
} }
} }
#[derive(Debug)]
#[allow(dead_code)] // we use Debug, so inner fields are never read
pub enum Error {
FileNotFoundError(String),
PermissionDeniedError(),
InvalidFormatError(serde_yaml::Error),
IoError(io::Error),
}
impl From<serde_yaml::Error> for Error {
fn from(e: serde_yaml::Error) -> Self {
Self::InvalidFormatError(e)
}
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
Self::IoError(e)
}
}
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
write!(fmt, "{self:?}")
}
}
pub type Result<T> = std::result::Result<T, Error>;

View File

@ -51,12 +51,13 @@ async fn main() -> anyhow::Result<()> {
}); });
let config = Arc::new(config); let config = Arc::new(config);
let state_db = FeedReaderStateDb::new("state.yaml").await.unwrap_or_else(|e| {
panic!("Failed to initialize feed reader state db: {e:?}")
});
// This message passing channel is used for sending messages to the matrix module, // This message passing channel is used for sending messages to the matrix module,
// it holds a tuple with an HTML message and a list of rooms to post to // it holds a tuple with an HTML message and a list of rooms to post to
let (bcast_tx, bcast_rx) = broadcast::channel(1024); let (bcast_tx, bcast_rx) = broadcast::channel::<(String, Vec<String>)>(1024);
let state_db = FeedReaderStateDb::new("state.yaml").await
.expect("Failed to initialize feed reader state db");
let handles: Vec<JoinHandle<_>> = config.feeds.clone().into_iter().map(|feed_config| { let handles: Vec<JoinHandle<_>> = config.feeds.clone().into_iter().map(|feed_config| {
let state_db = Arc::clone(&state_db); let state_db = Arc::clone(&state_db);
@ -130,7 +131,7 @@ async fn main() -> anyhow::Result<()> {
}) })
}).collect(); }).collect();
login_and_sync::<(String, Vec<String>)>( login_and_sync(
config.homeserver_uri.clone().into(), config.homeserver_uri.clone().into(),
&config.username, &config.username,
&config.password, &config.password,

View File

@ -85,7 +85,7 @@ async fn send_to_room(
}; };
} }
pub async fn login_and_sync<T: Clone>( pub async fn login_and_sync(
homeserver_url: String, homeserver_url: String,
username: &str, username: &str,
password: &str, password: &str,