You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

config.rs 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. use std::collections::*;
  2. use std::convert::TryFrom;
  3. use std::default::Default;
  4. use std::io;
  5. use std::path::PathBuf;
  6. use futures::prelude::*;
  7. use ruma_identifiers::{self, RoomId};
  8. use tokio::fs as tokiofs;
  9. use tokio::prelude::*;
  10. use toml;
  11. // FIXME Some of these error types are only used in the main module.
  12. #[derive(Debug)]
  13. pub enum Error {
  14. // TODO Reconcile these different parse errors.
  15. ParseFile(PathBuf),
  16. ParseToml(toml::de::Error),
  17. ParseMalformed,
  18. ParseIdentifier,
  19. Io(io::Error),
  20. }
  21. impl From<io::Error> for Error {
  22. fn from(f: io::Error) -> Self {
  23. Self::Io(f)
  24. }
  25. }
  26. impl From<toml::de::Error> for Error {
  27. fn from(f: toml::de::Error) -> Self {
  28. Self::ParseToml(f)
  29. }
  30. }
  31. #[derive(Default, Debug)]
  32. pub struct Config {
  33. pub accounts: HashMap<String, Account>,
  34. pub spool_dirs: Vec<SpoolDir>,
  35. }
  36. #[derive(Clone, Debug)]
  37. pub struct Account {
  38. pub homeserver: String,
  39. pub display: Option<String>,
  40. pub device_id: Option<String>,
  41. pub auth: Auth,
  42. }
  43. #[derive(Clone, Debug)]
  44. pub enum Auth {
  45. UsernamePass(String, String),
  46. }
  47. #[derive(Debug)]
  48. pub struct SpoolDir {
  49. pub path: PathBuf,
  50. pub send_delay_sec: u32,
  51. pub sender_acct_label: String,
  52. pub dest_room_id: RoomId,
  53. }
  54. pub async fn find_configs(search_dir: &PathBuf) -> Result<Vec<PathBuf>, Error> {
  55. let items: Vec<tokiofs::DirEntry> = tokiofs::read_dir(search_dir).await?.try_collect().await?;
  56. Ok(items
  57. .into_iter()
  58. .filter(|de| {
  59. de.file_name()
  60. .to_str()
  61. .map(|s| s.ends_with(".toml"))
  62. .unwrap_or(false)
  63. })
  64. .map(|e| e.path())
  65. .collect())
  66. }
  67. pub async fn parse_configs(paths: Vec<PathBuf>) -> Result<Config, Error> {
  68. let mut conf = Config::default();
  69. for p in &paths {
  70. println!("Reading config: {}", p.to_str().unwrap_or("[non-UTF-8]"));
  71. let val = match load_toml(p).await {
  72. Ok(t) => t,
  73. Err(_) => {
  74. println!("Error loading config, skipping");
  75. continue;
  76. }
  77. };
  78. match parse_toml(&val) {
  79. Ok((accts, spools)) => {
  80. conf.accounts.extend(accts);
  81. conf.spool_dirs.extend(spools);
  82. }
  83. Err(_) => {
  84. println!("Error processing config, skipping");
  85. continue;
  86. }
  87. }
  88. }
  89. Ok(conf)
  90. }
  91. async fn load_toml(path: &PathBuf) -> Result<toml::Value, Error> {
  92. let mut buf = Vec::new();
  93. let mut f = tokiofs::File::open(path).await?;
  94. let _ = f.read_to_end(&mut buf).await?;
  95. toml::de::from_slice(buf.as_slice()).map_err(|_| Error::ParseFile(path.clone()))
  96. }
  97. fn parse_toml(val: &toml::Value) -> Result<(Vec<(String, Account)>, Vec<SpoolDir>), Error> {
  98. use toml::Value::*;
  99. let mut accts = Vec::new();
  100. let mut spools = Vec::new();
  101. match val {
  102. Table(tab) => {
  103. let acct_ents = tab.get("acct").cloned();
  104. let watch_ents = tab.get("watch").cloned();
  105. match acct_ents {
  106. Some(Array(entries)) => {
  107. for acct in &entries {
  108. accts.push(parse_acct_entry(&acct)?);
  109. }
  110. }
  111. // TODO
  112. Some(_) => {}
  113. _ => {}
  114. }
  115. match watch_ents {
  116. Some(Array(entries)) => {
  117. for wd in &entries {
  118. spools.push(parse_watch_entry(&wd)?);
  119. }
  120. }
  121. // TODO
  122. Some(_) => {}
  123. _ => {}
  124. }
  125. }
  126. _ => {}
  127. }
  128. Ok((accts, spools))
  129. }
  130. fn parse_acct_entry(ent: &toml::Value) -> Result<(String, Account), Error> {
  131. use toml::Value::*;
  132. type StdString = ::std::string::String;
  133. let label = ent.get("label");
  134. let homeserver = ent.get("homeserver");
  135. let display = ent.get("display");
  136. let dev_id = ent.get("deviceid");
  137. let username = ent.get("username");
  138. let password = ent.get("password");
  139. // This is gross and I don't like it, but ok.
  140. match (label, homeserver, username, password) {
  141. (Some(String(l)), Some(String(s)), Some(String(u)), Some(String(p))) => {
  142. let auth = Auth::UsernamePass(u.clone(), p.clone());
  143. Ok((
  144. l.clone(),
  145. Account {
  146. homeserver: s.clone(),
  147. display: display
  148. .cloned()
  149. .map(|v| v.try_into::<StdString>())
  150. .transpose()?,
  151. device_id: dev_id
  152. .cloned()
  153. .map(|v| v.try_into::<StdString>())
  154. .transpose()?,
  155. auth: auth,
  156. },
  157. ))
  158. }
  159. _ => Err(Error::ParseMalformed),
  160. }
  161. }
  162. fn parse_watch_entry(ent: &toml::Value) -> Result<SpoolDir, Error> {
  163. use toml::Value::*;
  164. let sender = ent.get("sender");
  165. let path = ent.get("path");
  166. let dest = ent.get("destroom");
  167. let delay = ent.get("delay");
  168. // Again this is gross, but whatever.
  169. match (path, sender, dest) {
  170. (Some(String(p)), Some(String(s)), Some(String(d))) => Ok(SpoolDir {
  171. path: PathBuf::from(p.clone()),
  172. send_delay_sec: delay
  173. .cloned()
  174. .map(|v| v.try_into::<u32>())
  175. .transpose()?
  176. .unwrap_or(0),
  177. sender_acct_label: s.clone(),
  178. dest_room_id: RoomId::try_from(d.as_str()).map_err(|_| Error::ParseIdentifier)?,
  179. }),
  180. _ => Err(Error::ParseMalformed),
  181. }
  182. }