|  |  |  | @ -32,6 +32,9 @@ pub struct StoreOptions { | 
			
		
	
		
			
				
					|  |  |  |  |     pub store_dir: String, | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const DEFAULT_LOCALE_NAME : &str = "en"; | 
			
		
	
		
			
				
					|  |  |  |  | const DEFAULT_LOCALE_JSON : &str = include_str!("../../locales/en.json"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl ConfigStore { | 
			
		
	
		
			
				
					|  |  |  |  |     /// Create a new instance of the store.
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// If a path is given, it will try to load the content from a file.
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -76,13 +79,30 @@ impl ConfigStore { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         debug!("Using common config:\n{:#?}", config); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let groups_path = base_dir.join("groups"); | 
			
		
	
		
			
				
					|  |  |  |  |         let groups_path = if config.groups_dir.starts_with('/') { | 
			
		
	
		
			
				
					|  |  |  |  |             PathBuf::from(&config.groups_dir) | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             base_dir.join(&config.groups_dir) | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if !groups_path.exists() { | 
			
		
	
		
			
				
					|  |  |  |  |             debug!("Creating groups directory"); | 
			
		
	
		
			
				
					|  |  |  |  |             tokio::fs::create_dir_all(&groups_path).await?; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let locales_path = base_dir.join("locales"); | 
			
		
	
		
			
				
					|  |  |  |  |         let locales_path = if config.locales_dir.starts_with('/') { | 
			
		
	
		
			
				
					|  |  |  |  |             PathBuf::from(&config.locales_dir) | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             base_dir.join(&config.locales_dir) | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // warn, this is usually not a good idea beside for testing
 | 
			
		
	
		
			
				
					|  |  |  |  |         if config.max_catchup_notifs == 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             warn!("Missed notifications catch-up is disabled!"); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         if config.max_catchup_statuses == 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             warn!("Missed statuses catch-up is disabled!"); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(Self { | 
			
		
	
		
			
				
					|  |  |  |  |             store_path: base_dir.to_owned(), | 
			
		
	
	
		
			
				
					|  |  |  | @ -107,7 +127,7 @@ impl ConfigStore { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let group_dir = self.groups_path.join(&opts.acct); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let data = GroupConfig::from_appdata(opts.acct.clone(), appdata, group_dir).await?; | 
			
		
	
		
			
				
					|  |  |  |  |         let _data = GroupConfig::from_appdata(opts.acct.clone(), appdata, group_dir).await?; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // save & persist
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -149,7 +169,7 @@ impl ConfigStore { | 
			
		
	
		
			
				
					|  |  |  |  |         config.set_appdata(appdata); | 
			
		
	
		
			
				
					|  |  |  |  |         config.save_if_needed(true).await?; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let group_account = match client.verify_credentials().await { | 
			
		
	
		
			
				
					|  |  |  |  |         let _group_account = match client.verify_credentials().await { | 
			
		
	
		
			
				
					|  |  |  |  |             Ok(account) => { | 
			
		
	
		
			
				
					|  |  |  |  |                 info!( | 
			
		
	
		
			
				
					|  |  |  |  |                     "Group account verified: @{}, \"{}\"", | 
			
		
	
	
		
			
				
					|  |  |  | @ -167,6 +187,9 @@ impl ConfigStore { | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub async fn find_locales(&mut self) { | 
			
		
	
		
			
				
					|  |  |  |  |         // Load the default locale, it will be used as fallback to fill-in missing keys
 | 
			
		
	
		
			
				
					|  |  |  |  |         self.load_locale(DEFAULT_LOCALE_NAME, DEFAULT_LOCALE_JSON, true); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if !self.locales_path.is_dir() { | 
			
		
	
		
			
				
					|  |  |  |  |             debug!("No locales path set!"); | 
			
		
	
		
			
				
					|  |  |  |  |             return; | 
			
		
	
	
		
			
				
					|  |  |  | @ -175,7 +198,7 @@ impl ConfigStore { | 
			
		
	
		
			
				
					|  |  |  |  |         let entries = match std::fs::read_dir(&self.locales_path) { | 
			
		
	
		
			
				
					|  |  |  |  |             Ok(ee) => ee, | 
			
		
	
		
			
				
					|  |  |  |  |             Err(e) => { | 
			
		
	
		
			
				
					|  |  |  |  |                 warn!("Error listing locales"); | 
			
		
	
		
			
				
					|  |  |  |  |                 warn!("Error listing locales: {}", e); | 
			
		
	
		
			
				
					|  |  |  |  |                 return; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
	
		
			
				
					|  |  |  | @ -189,13 +212,8 @@ impl ConfigStore { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                     match tokio::fs::read(&path).await { | 
			
		
	
		
			
				
					|  |  |  |  |                         Ok(f) => { | 
			
		
	
		
			
				
					|  |  |  |  |                             if let Ok(tr) = serde_json::from_slice::<TranslationTable>(&f) { | 
			
		
	
		
			
				
					|  |  |  |  |                                 let locale_name = path.file_stem().unwrap_or_default().to_string_lossy().to_string(); | 
			
		
	
		
			
				
					|  |  |  |  |                                 debug!("Loaded locale: {}", locale_name); | 
			
		
	
		
			
				
					|  |  |  |  |                                 self.config.tr.insert(locale_name, tr); | 
			
		
	
		
			
				
					|  |  |  |  |                             } else { | 
			
		
	
		
			
				
					|  |  |  |  |                                 error!("Failed to parse locale file {}", path.display()); | 
			
		
	
		
			
				
					|  |  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |  |                             let locale_name = path.file_stem().unwrap_or_default().to_string_lossy(); | 
			
		
	
		
			
				
					|  |  |  |  |                             self.load_locale(&locale_name, &String::from_utf8_lossy(&f), false); | 
			
		
	
		
			
				
					|  |  |  |  |                         }, | 
			
		
	
		
			
				
					|  |  |  |  |                         Err(e) => { | 
			
		
	
		
			
				
					|  |  |  |  |                             error!("Failed to read locale file {}: {}", path.display(), e); | 
			
		
	
	
		
			
				
					|  |  |  | @ -206,6 +224,31 @@ impl ConfigStore { | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn load_locale(&mut self, locale_name: &str, locale_json: &str, is_default: bool) { | 
			
		
	
		
			
				
					|  |  |  |  |         if let Ok(mut tr) = serde_json::from_str::<TranslationTable>(locale_json) { | 
			
		
	
		
			
				
					|  |  |  |  |             debug!("Loaded locale: {}", locale_name); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if !is_default { | 
			
		
	
		
			
				
					|  |  |  |  |                 let def_tr = self.config.tr.get(DEFAULT_LOCALE_NAME).expect("Default locale not loaded!"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 for (k, v) in def_tr.entries() { | 
			
		
	
		
			
				
					|  |  |  |  |                     if !tr.translation_exists(k) { | 
			
		
	
		
			
				
					|  |  |  |  |                         warn!("locale \"{}\" is missing \"{}\", default: {:?}", | 
			
		
	
		
			
				
					|  |  |  |  |                             locale_name, | 
			
		
	
		
			
				
					|  |  |  |  |                             k, | 
			
		
	
		
			
				
					|  |  |  |  |                             def_tr.get_translation_raw(k).unwrap()); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                         tr.add_translation(k, v); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             self.config.tr.insert(locale_name.to_owned(), tr); | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             error!("Failed to parse locale {}", locale_name); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Spawn existing group using saved creds
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub async fn spawn_groups(self) -> Result<Vec<GroupHandle>, GroupError> { | 
			
		
	
		
			
				
					|  |  |  |  |         info!("Starting group services for groups in {}", self.groups_path.display()); | 
			
		
	
	
		
			
				
					|  |  |  | 
 |