forked from trinitrix/core
fix (accounts): caching clients to fix the 'Session IDs were already set' bug
This commit is contained in:
parent
a3cb8b8e20
commit
c5742e66f4
113
src/accounts.rs
113
src/accounts.rs
|
@ -1,5 +1,5 @@
|
||||||
|
use std::borrow::{Borrow, BorrowMut};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
|
||||||
use matrix_sdk::{Client,
|
use matrix_sdk::{Client,
|
||||||
config::SyncSettings,
|
config::SyncSettings,
|
||||||
ruma::{user_id,
|
ruma::{user_id,
|
||||||
|
@ -8,9 +8,8 @@ use matrix_sdk::{Client,
|
||||||
Session};
|
Session};
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::app;
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
homeserver: String,
|
homeserver: String,
|
||||||
id: u32,
|
id: u32,
|
||||||
|
@ -20,29 +19,48 @@ pub struct Account {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct AccountManager {
|
struct AccountsData {
|
||||||
selected_account_index: u32,
|
current_account: u32,
|
||||||
accounts: Vec<Account>,
|
accounts: Vec<Account>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountManager {
|
pub struct AccountsManager {
|
||||||
pub fn new() -> Self {
|
current_account: u32,
|
||||||
let json_file: &Path = Path::new("userdata/accounts.json");
|
num_accounts: u32,
|
||||||
return if json_file.exists() {
|
accounts: Vec<Account>,
|
||||||
let serialized = fs::read_to_string(json_file).expect("ailed to read json");
|
clients: Vec<Option<Client>>,
|
||||||
serde_json::from_str(&serialized).expect("failed to deserialize json")
|
}
|
||||||
} else {
|
|
||||||
|
impl AccountsManager {
|
||||||
|
pub fn new(config:Option<String>) -> Self {
|
||||||
|
return match config {
|
||||||
|
Some(s) => {
|
||||||
|
let accounts_data:AccountsData = serde_json::from_str(&s).expect("failed to deserialize json");
|
||||||
|
let mut clients = Vec::new();
|
||||||
|
clients.resize(accounts_data.accounts.len(), None);
|
||||||
Self {
|
Self {
|
||||||
selected_account_index: 0,
|
current_account: accounts_data.current_account,
|
||||||
accounts: Vec::new(),
|
num_accounts: accounts_data.accounts.len() as u32,
|
||||||
|
accounts: accounts_data.accounts,
|
||||||
|
clients,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
None => Self {
|
||||||
|
current_account: 0,
|
||||||
|
num_accounts: 0,
|
||||||
|
accounts: Vec::new(),
|
||||||
|
clients: Vec::new(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add(&mut self, homeserver: &str, username: &str, password: &str) -> Result<Client> {
|
pub async fn add(&mut self, homeserver: &str, username: &str, password: &str) -> Result<u32> {
|
||||||
|
let id = self.num_accounts;
|
||||||
|
self.num_accounts += 1;
|
||||||
|
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.homeserver_url(homeserver)
|
.homeserver_url(homeserver)
|
||||||
.sled_store("userdata/data", Some("supersecure"))?
|
.sled_store(format!("userdata/{id}"), Some("supersecure"))?
|
||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -54,62 +72,77 @@ impl AccountManager {
|
||||||
|
|
||||||
let session = client.session().expect("failed to get session");
|
let session = client.session().expect("failed to get session");
|
||||||
|
|
||||||
println!("logged in as {username} device ID: {}", session.device_id.as_str());
|
println!("logged in as '{username}' device ID: {}", session.device_id.as_str());
|
||||||
|
|
||||||
|
|
||||||
let account = Account {
|
let account = Account {
|
||||||
homeserver: homeserver.to_string(),
|
homeserver: homeserver.to_string(),
|
||||||
id: self.accounts.len() as u32,
|
id,
|
||||||
session,
|
session,
|
||||||
sync_token: None
|
sync_token: None
|
||||||
};
|
};
|
||||||
|
|
||||||
self.logout(&client).await?;
|
self.logout().await?;
|
||||||
self.selected_account_index = account.id;
|
self.current_account = id;
|
||||||
self.accounts.push(account);
|
self.accounts.push(account);
|
||||||
|
self.clients.push(Some(client));
|
||||||
|
|
||||||
self.save()?;
|
self.save()?;
|
||||||
|
|
||||||
Ok(client)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn login(&mut self, account_id:u32) -> Result<Client> {
|
pub async fn login(&mut self, account_id:u32) -> Result<()> {
|
||||||
let account = match self.get(account_id) {
|
self.logout().await?; // log out the current account
|
||||||
None => return Err(Error::msg("Invalid account ID")),
|
|
||||||
Some(a) => a,
|
let account = if account_id >= self.num_accounts {
|
||||||
|
return Err(Error::msg("Invalid account ID"));
|
||||||
|
} else {
|
||||||
|
self.accounts.get(account_id as usize).expect("Account lookup failed")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if self.clients.get(account_id as usize).expect("client lookup failed").is_none() {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.homeserver_url(&account.homeserver)
|
.homeserver_url(&account.homeserver)
|
||||||
.sled_store("userdata/data", Some("supersecure"))?
|
.sled_store(format!("userdata/{account_id}"), Some("supersecure")) ?
|
||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
client.restore_login(account.session.clone()).await?;
|
client.restore_login(account.session.clone()).await?;
|
||||||
|
|
||||||
println!("restored account: {} device ID: {}", &account.session.user_id, &account.session.device_id);
|
println!("restored account: '{}' device ID: {}", &account.session.user_id, &account.session.device_id);
|
||||||
|
} else {
|
||||||
|
println!("using cached client for account: '{}' device ID: {}", &account.session.user_id, &account.session.device_id);
|
||||||
|
};
|
||||||
|
|
||||||
self.logout(&client).await?;
|
self.current_account = account_id;
|
||||||
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, id: u32) -> Option<&Account> {
|
pub async fn logout(&mut self) -> Result<()> {
|
||||||
return self.accounts.get(id as usize);
|
// idk, do some matrix related stuff in here or something like that
|
||||||
|
if self.clients.get(self.current_account as usize).is_none() {
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
let client = match self.clients.get(self.current_account as usize).unwrap() {
|
||||||
|
None => return Ok(()),
|
||||||
|
Some(c) => c,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn current(&self) -> Option<&Account> {
|
println!("logged out {}", client.session().unwrap().user_id);
|
||||||
return self.accounts.get(self.selected_account_index as usize);
|
client.logout().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&self) -> Result<()>{
|
pub fn save(&self) -> Result<()>{
|
||||||
let serialized = serde_json::to_string(self as &AccountManager)?;
|
let accounts_data = AccountsData {
|
||||||
|
current_account: self.current_account,
|
||||||
|
accounts: self.accounts.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let serialized = serde_json::to_string(&accounts_data)?;
|
||||||
fs::write("userdata/accounts.json", serialized)?;
|
fs::write("userdata/accounts.json", serialized)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,18 +1,26 @@
|
||||||
|
use std::path::Path;
|
||||||
use crate::accounts;
|
use crate::accounts;
|
||||||
|
|
||||||
use matrix_sdk::{Client};
|
use matrix_sdk::{Client};
|
||||||
use accounts::Account;
|
use accounts::Account;
|
||||||
use crate::accounts::AccountManager;
|
use accounts::AccountsManager;
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
pub account_manager: accounts::AccountManager,
|
pub accounts_manager: accounts::AccountsManager,
|
||||||
pub client: Option<Client>,
|
pub client: Option<Client>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
let path:&std::path::Path = Path::new("userdata/accounts.json");
|
||||||
|
let config = if path.exists() {
|
||||||
|
Some(std::fs::read_to_string(path).expect("failed to read accounts config"))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
account_manager: AccountManager::new(),
|
accounts_manager: AccountsManager::new(config),
|
||||||
client: None
|
client: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,9 @@ async fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
let mut app = app::App::new();
|
let mut app = app::App::new();
|
||||||
|
|
||||||
let client = app.account_manager.add("https://nerdcult.net", "test", "abcd1234").await?;
|
let account = app.accounts_manager.add("https://nerdcult.net", "test", "abcd1234").await?;
|
||||||
app.client = Some(client);
|
|
||||||
|
|
||||||
// let client = app.account_manager.login(0).await?;
|
app.accounts_manager.login(0).await?;
|
||||||
// app.client = Some(client);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue