use std::path::{Path, PathBuf}; use matrix_sdk::{ config::ClientConfig, reqwest::Url, ruma::{DeviceIdBox, UserId}, Client, }; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Session { /// The homeserver URL pub homeserver: Url, /// Access token for authentication pub access_token: String, /// The user's mxid. pub user_id: UserId, /// The user's device ID. pub device_id: DeviceIdBox, } /// Create a matrix client and log it in to the server at the given URL with the /// given credentials. pub fn login(url: &str, user: &str, password: &str) -> Result { let url: Url = if !url.contains("://") { format!("https://{}", url).parse() } else { url.parse() }?; let client = Client::new_with_config(url.clone(), config()?)?; let rt = tokio::runtime::Runtime::new().unwrap(); let response = rt.block_on(client.login(user, password, None, None))?; let session = Session { homeserver: url, access_token: response.access_token, user_id: response.user_id, device_id: response.device_id, }; Ok(client) } /// Errors that can happen when logging in #[derive(Debug)] pub enum LoginError { /// Invalid URL Url(url::ParseError), /// Matrix SDK error Sdk(matrix_sdk::Error), /// I/O error Io(std::io::Error), } impl std::fmt::Display for LoginError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { LoginError::Url(_) => write!(f, "Invalid homeserver address"), LoginError::Sdk(e) => write!(f, "{}", e), LoginError::Io(e) => write!(f, "Filesystem error: {}", e), } } } impl std::error::Error for LoginError {} impl From for LoginError { fn from(e: url::ParseError) -> Self { LoginError::Url(e) } } impl From for LoginError { fn from(e: matrix_sdk::Error) -> Self { LoginError::Sdk(e) } } impl From for LoginError { fn from(e: std::io::Error) -> Self { LoginError::Io(e) } } /// Configuration for `Clients`. fn config() -> Result { Ok(ClientConfig::new().store_path(&path()?)) } /// The path the the sdk store should be put in. fn path() -> Result { let path = Path::new(&std::env::var_os("HOME").unwrap()) .join(".config") .join("retrix"); std::fs::create_dir_all(&path)?; Ok(path) }