From a3cb8b8e2019f07b1a8e2d20b342c07f845856e5 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Fri, 16 Jun 2023 00:15:07 +0200 Subject: [PATCH] feature (accounts): implemented an account manager --- .gitignore | 2 +- src/accounts.rs | 117 ++++++++++++++++++++++++++++++++++++++++++++ src/accounts/mod.rs | 59 ---------------------- src/app/mod.rs | 19 +++++++ src/main.rs | 10 ++-- 5 files changed, 143 insertions(+), 64 deletions(-) create mode 100644 src/accounts.rs delete mode 100644 src/accounts/mod.rs create mode 100644 src/app/mod.rs diff --git a/.gitignore b/.gitignore index 80b55f9..c1fc9e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ target/ -data/ +userdata/ # IDE stuff .idea diff --git a/src/accounts.rs b/src/accounts.rs new file mode 100644 index 0000000..038ab03 --- /dev/null +++ b/src/accounts.rs @@ -0,0 +1,117 @@ +use std::fs; +use std::path::Path; +use matrix_sdk::{Client, + config::SyncSettings, + ruma::{user_id, + events::room::message::SyncRoomMessageEvent, + exports::serde_json}, + Session}; +use anyhow::{Error, Result}; +use serde::{Deserialize, Serialize}; +use crate::app; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Account { + homeserver: String, + id: u32, + + session: Session, + sync_token: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct AccountManager { + selected_account_index: u32, + accounts: Vec, +} + +impl AccountManager { + pub fn new() -> Self { + let json_file: &Path = Path::new("userdata/accounts.json"); + return if json_file.exists() { + let serialized = fs::read_to_string(json_file).expect("ailed to read json"); + serde_json::from_str(&serialized).expect("failed to deserialize json") + } else { + Self { + selected_account_index: 0, + accounts: Vec::new(), + } + } + } + + pub async fn add(&mut self, homeserver: &str, username: &str, password: &str) -> Result { + let client = Client::builder() + .homeserver_url(homeserver) + .sled_store("userdata/data", Some("supersecure"))? + .build() + .await?; + + client + .login_username(username, password) + .initial_device_display_name("Trinitrix") + .send() + .await?; + + let session = client.session().expect("failed to get session"); + + println!("logged in as {username} device ID: {}", session.device_id.as_str()); + + + let account = Account { + homeserver: homeserver.to_string(), + id: self.accounts.len() as u32, + session, + sync_token: None + }; + + self.logout(&client).await?; + self.selected_account_index = account.id; + self.accounts.push(account); + + self.save()?; + + Ok(client) + } + + pub async fn login(&mut self, account_id:u32) -> Result { + let account = match self.get(account_id) { + None => return Err(Error::msg("Invalid account ID")), + Some(a) => a, + }; + + let client = Client::builder() + .homeserver_url(&account.homeserver) + .sled_store("userdata/data", Some("supersecure"))? + .build() + .await?; + + client.restore_login(account.session.clone()).await?; + + println!("restored account: {} device ID: {}", &account.session.user_id, &account.session.device_id); + + self.logout(&client).await?; + self.selected_account_index = account_id; + + Ok(client) + } + + pub async fn logout(&mut self, client: &Client) -> Result<()> { + // idk, do some matrix related stuff in here or something like that + Ok(()) + } + + pub fn get(&self, id: u32) -> Option<&Account> { + return self.accounts.get(id as usize); + } + + pub fn current(&self) -> Option<&Account> { + return self.accounts.get(self.selected_account_index as usize); + } + + pub fn save(&self) -> Result<()>{ + let serialized = serde_json::to_string(self as &AccountManager)?; + fs::write("userdata/accounts.json", serialized)?; + + Ok(()) + } +} \ No newline at end of file diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs deleted file mode 100644 index 4de215a..0000000 --- a/src/accounts/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -use matrix_sdk::{Client, config::SyncSettings, ruma::{user_id, events::room::message::SyncRoomMessageEvent}, Session}; -use anyhow::{Error, Result}; -use matrix_sdk::ruma::exports::serde_json; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize, Deserialize)] -pub struct Account { - homeserver: String, - - session: Session, - sync_token: Option, -} - -pub async fn account_add(homeserver:&str, username:&str, password:&str) -> anyhow::Result { - let client = Client::builder() - .homeserver_url(homeserver) - .sled_store("data", Some("supersecure"))? - .build() - .await?; - - client - .login_username(username, password) - .initial_device_display_name("Trinitrix") - .send() - .await?; - - let session = match client.session() { - None => return Err(Error::msg("session is None")), - Some(s) => s, - }; - - println!("logged in as {username} device ID: {}", session.device_id.as_str()); - - let account = Account { - homeserver: homeserver.to_string(), - session, - sync_token: None - }; - - let serialized_account = serde_json::to_string(&account)?; - println!("serialized account: {}", serialized_account); - // TODO: save serialized account info in userdata dir - - Ok(account) -} - -pub async fn account_login(account: Account) -> anyhow::Result<()> { - let client = Client::builder() - .homeserver_url(account.homeserver) - .sled_store("data", Some("supersecure"))? - .build() - .await?; - - client.restore_login(account.session.clone()).await?; - - println!("restored account: {} device ID: {}", &account.session.user_id, &account.session.device_id); - - Ok(()) -} \ No newline at end of file diff --git a/src/app/mod.rs b/src/app/mod.rs new file mode 100644 index 0000000..7f99ad4 --- /dev/null +++ b/src/app/mod.rs @@ -0,0 +1,19 @@ +use crate::accounts; + +use matrix_sdk::{Client}; +use accounts::Account; +use crate::accounts::AccountManager; + +pub struct App { + pub account_manager: accounts::AccountManager, + pub client: Option, +} + +impl App { + pub fn new() -> Self { + Self { + account_manager: AccountManager::new(), + client: None + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 292341d..00ba119 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod ui; mod accounts; +mod app; use matrix_sdk::ruma::exports::serde_json; use tokio::time::{sleep, Duration}; @@ -8,12 +9,13 @@ use tokio::time::{sleep, Duration}; async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); - // accounts::account_add("https://nerdcult.net", "test", "abcd1234").await?; + let mut app = app::App::new(); - let serialized_account = "{\"homeserver\":\"https://nerdcult.net\",\"session\":{\"access_token\":\"U2XH1vfu3dJTTPV7BIeZh2yGiMN49vBF\",\"user_id\":\"@test:nerdcult.net\",\"device_id\":\"UsdqFbcEC3\"},\"sync_token\":null}"; - let account: accounts::Account = serde_json::from_str(serialized_account)?; + let client = app.account_manager.add("https://nerdcult.net", "test", "abcd1234").await?; + app.client = Some(client); - accounts::account_login(account).await?; + // let client = app.account_manager.login(0).await?; + // app.client = Some(client); Ok(()) }