123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- use std::collections::*;
- use std::convert::TryFrom;
- use std::default::Default;
- use std::io;
- use std::path::PathBuf;
-
- use futures::prelude::*;
- use futures::stream::TryStreamExt;
-
- use tokio::fs as tokiofs;
- use tokio::io::{AsyncRead, AsyncReadExt};
- use toml;
-
- use serde::Deserialize;
-
- use matrix_sdk::identifiers::RoomId;
-
- // FIXME Some of these error types are only used in the main module.
- #[derive(Debug)]
- pub enum Error {
- // TODO Reconcile these different parse errors.
- ParseFile(PathBuf),
- ParseToml(toml::de::Error),
- ParseIdentifier,
- Io(io::Error),
- }
-
- impl From<io::Error> for Error {
- fn from(f: io::Error) -> Self {
- Self::Io(f)
- }
- }
-
- impl From<toml::de::Error> for Error {
- fn from(f: toml::de::Error) -> Self {
- Self::ParseToml(f)
- }
- }
-
- #[derive(Default, Debug)]
- pub struct Config {
- pub accounts: HashMap<String, Account>,
- pub spool_dirs: Vec<SpoolDir>,
- }
-
- #[derive(Clone, Debug)]
- pub struct Account {
- pub homeserver: String,
- pub display: Option<String>,
- pub device_id: Option<String>,
- pub auth: Auth,
- }
-
- #[derive(Clone, Debug)]
- pub enum Auth {
- UsernamePass(String, String),
- }
-
- #[derive(Debug)]
- pub struct SpoolDir {
- pub path: PathBuf,
- pub send_delay_sec: u32,
- pub sender_acct_label: String,
- pub dest_room_id: RoomId,
- }
-
- #[derive(Clone, Debug, Deserialize)]
- pub struct ConfigFile {
- acct: Vec<ConfigAccount>,
- watch: Vec<ConfigWatch>,
- }
-
- #[derive(Clone, Debug, Deserialize)]
- pub struct ConfigAccount {
- label: String,
- homeserver: String,
- username: String,
- password: String,
- }
-
- #[derive(Clone, Debug, Deserialize)]
- pub struct ConfigWatch {
- sender: String,
- path: String,
- destroom: String,
- }
-
- pub async fn find_configs(search_dir: &PathBuf) -> Result<Vec<PathBuf>, Error> {
- let mut items: Vec<tokiofs::DirEntry> = Vec::new();
- let mut rd = tokiofs::read_dir(search_dir).await?;
- while let Some(dent) = rd.next_entry().await? {
- items.push(dent);
- }
-
- Ok(items
- .into_iter()
- .filter(|de| {
- de.file_name()
- .to_str()
- .map(|s| s.ends_with(".toml"))
- .unwrap_or(false)
- })
- .map(|e| e.path())
- .collect())
- }
-
- pub async fn parse_configs(paths: &Vec<PathBuf>) -> Result<Config, Error> {
- let mut conf = Config::default();
-
- for p in paths {
- println!("Reading config: {}", p.to_str().unwrap_or("[non-UTF-8]"));
- let val = match load_toml(p).await {
- Ok(t) => t,
- Err(_) => {
- println!("warning: error loading config, skipping: {:?}", p);
- continue;
- }
- };
-
- // Ingest the accounts.
- for a in val.acct {
- if conf.accounts.contains_key(&a.label) {
- eprintln!("warning: ignoring duplicate account entry for {}", a.label);
- continue;
- }
-
- let acct = Account {
- homeserver: a.homeserver,
- auth: Auth::UsernamePass(a.username, a.password),
- device_id: None,
- display: None,
- };
-
- conf.accounts.insert(a.label, acct);
- }
-
- // Ingest the watches.
- for s in val.watch {
- let sd = SpoolDir {
- path: PathBuf::from(s.path),
- send_delay_sec: 0,
- sender_acct_label: s.sender,
- dest_room_id: RoomId::try_from(s.destroom.as_str())
- .map_err(|_| Error::ParseIdentifier)?,
- };
-
- conf.spool_dirs.push(sd);
- }
- }
-
- Ok(conf)
- }
-
- async fn load_toml(path: &PathBuf) -> Result<ConfigFile, Error> {
- let mut buf = Vec::new();
- let mut f = tokiofs::File::open(path).await?;
- let _ = f.read_to_end(&mut buf).await?;
- toml::from_slice(&buf).map_err(|e| {
- eprintln!("warning: parsing file {:?}", e);
- Error::ParseFile(path.clone())
- })
- }
|