From 192f17a4190a839006b7e0fc538cad48fa734392 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 26 Dec 2023 17:17:21 +0000 Subject: [PATCH] Half-arsed attempt to set up a Client type. It _compiles_, but I'm not at all sure the API is what it ought to be. Still, I'll press on with it for the moment and figure out how it's wrong later. --- src/auth.rs | 18 +++++++++++++----- src/client.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 6 +----- src/main.rs | 5 ++--- src/text.rs | 1 - src/types.rs | 16 ++++++++-------- 6 files changed, 72 insertions(+), 22 deletions(-) create mode 100644 src/client.rs diff --git a/src/auth.rs b/src/auth.rs index 18baae7..1e0ea7e 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,7 +1,11 @@ use serde::{Deserialize, Serialize}; use xdg::BaseDirectories; -use super::OurError; +#[derive(Debug)] +pub enum AuthError { + Nonexistent(String), + Bad(String), +} #[derive(Serialize, Deserialize, Debug)] pub struct AuthConfig { @@ -15,26 +19,30 @@ pub struct AuthConfig { } impl AuthConfig { - pub fn load() -> Result { + pub fn load() -> Result { let xdg_dirs = match BaseDirectories::with_prefix("mastodonochrome") { - Err(e) => Err(OurError::Fatal( + Err(e) => Err(AuthError::Nonexistent( format!("unable to get config directory: {}", e))), Ok(d) => Ok(d), }?; let authfile = xdg_dirs.get_config_file("auth"); let authdata = match std::fs::read_to_string(&authfile) { - Err(e) => Err(OurError::Fatal( + Err(e) => Err(AuthError::Nonexistent( format!("unable to read config file '{}': {}", authfile.display(), e))), Ok(d) => Ok(d), }?; let auth: Self = match serde_json::from_str(&authdata) { - Err(e) => Err(OurError::Fatal( + Err(e) => Err(AuthError::Bad( format!("unable to parse config file '{}': {}", authfile.display(), e))), Ok(d) => Ok(d), }?; Ok(auth) } + + pub fn fqaccount(&self) -> String { + self.username.to_owned() + "@" + &self.instance_domain + } } diff --git a/src/client.rs b/src/client.rs new file mode 100644 index 0000000..2c91b86 --- /dev/null +++ b/src/client.rs @@ -0,0 +1,48 @@ +use std::collections::HashMap; + +use super::auth::{AuthConfig,AuthError}; +use super::types::*; + +pub struct Client { + auth: AuthConfig, + client: reqwest::blocking::Client, + statuses: HashMap, +} + +impl Client { + pub fn new() -> Result { + Ok(Client { + auth: AuthConfig::load()?, + client: reqwest::blocking::Client::new(), + statuses: HashMap::new(), + }) + } + + fn api_request(&self, method: reqwest::Method, url_suffix: &str) + -> reqwest::blocking::RequestBuilder { + let url = reqwest::Url::parse( + &(self.auth.instance_url.clone() + "/api/v1/" + url_suffix)); + // FIXME: add params to that + + let url = url.unwrap(); // FIXME: handle url::parser::ParseError + + self.client.request(method, url) + .bearer_auth(&self.auth.user_token) + } + + pub fn status_by_id(&mut self, id: &str) -> Option { + if let Some(st) = self.statuses.get(id) { + return Some(st.clone()); + } + + let req = self.api_request(reqwest::Method::GET, + &("statuses/".to_owned() + id)); + // FIXME: if this goes wrong, log it + let body = req.send().unwrap().text().unwrap(); + dbg!(&body); + let st: Status = serde_json::from_str(&body).unwrap(); + self.statuses.insert(id.to_string(), st); + Some(self.statuses.get(id).unwrap().clone()) + } +} + diff --git a/src/lib.rs b/src/lib.rs index 25e9acd..50b086d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,8 +7,4 @@ pub mod html; pub mod scan_re; pub mod coloured_string; pub mod text; - -#[derive(Debug)] -pub enum OurError { - Fatal(String), -} +pub mod client; diff --git a/src/main.rs b/src/main.rs index f2beb3f..76c85d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,7 @@ use mastodonochrome::types::*; -use mastodonochrome::OurError; -use mastodonochrome::auth::AuthConfig; use mastodonochrome::html::{render}; use mastodonochrome::html; use std::collections::HashMap; -use std::io::Read; use std::io::Write; use crossterm::{ @@ -21,6 +18,7 @@ use ratatui::{ }; use std::io::stdout; +/* #[allow(unused)] fn streaming() -> Result<(), mastodonochrome::OurError> { let auth = AuthConfig::load()?; @@ -63,6 +61,7 @@ fn streaming() -> Result<(), mastodonochrome::OurError> { Ok(()) } +*/ #[allow(unused)] fn tui() -> std::io::Result<()> { diff --git a/src/text.rs b/src/text.rs index d3bed53..1cd40b4 100644 --- a/src/text.rs +++ b/src/text.rs @@ -13,7 +13,6 @@ pub trait TextFragment { // Some indication of how many usernames are in here and how many statuses // Some means of passing a flag to render() that says which username or // status is to be highlighted - // Some means of having ExtendableIndicator flag itself as active fn render(&self, width: usize) -> Vec; fn as_extendable_indicator_mut(&mut self) diff --git a/src/types.rs b/src/types.rs index bedb692..b5c357f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -3,14 +3,14 @@ use serde::{Deserialize, Serialize}; use std::boxed::Box; use std::option::Option; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct AccountField { pub name: String, pub value: String, pub verified_at: Option>, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Account { pub id: String, pub username: String, @@ -40,13 +40,13 @@ pub struct Account { pub following_count: u64, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Application { pub name: String, pub website: Option, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum Visibility { #[serde(rename = "public")] Public, #[serde(rename = "unlisted")] Unlisted, @@ -54,7 +54,7 @@ pub enum Visibility { #[serde(rename = "direct")] Direct, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum MediaType { #[serde(rename = "unknown")] Unknown, #[serde(rename = "image")] Image, @@ -63,7 +63,7 @@ pub enum MediaType { #[serde(rename = "audio")] Audio, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct MediaAttachment { pub id: String, #[serde(rename="type")] pub mediatype: MediaType, @@ -73,7 +73,7 @@ pub struct MediaAttachment { pub description: Option, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct StatusMention { pub id: String, pub username: String, @@ -81,7 +81,7 @@ pub struct StatusMention { pub acct: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Status { pub id: String, pub uri: String, -- 2.30.2