chiark / gitweb /
Half-arsed attempt to set up a Client type.
authorSimon Tatham <anakin@pobox.com>
Tue, 26 Dec 2023 17:17:21 +0000 (17:17 +0000)
committerSimon Tatham <anakin@pobox.com>
Tue, 26 Dec 2023 22:08:00 +0000 (22:08 +0000)
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
src/client.rs [new file with mode: 0644]
src/lib.rs
src/main.rs
src/text.rs
src/types.rs

index 18baae745195b5cd762108687e6fe83a54b2bebd..1e0ea7e53328e3df6293ac2f783b0e1c4a4cd7be 100644 (file)
@@ -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<Self, OurError> {
+    pub fn load() -> Result<Self, AuthError> {
         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 (file)
index 0000000..2c91b86
--- /dev/null
@@ -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<String, Status>,
+}
+
+impl Client {
+    pub fn new() -> Result<Self, AuthError> {
+        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<Status> {
+        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())
+    }
+}
+
index 25e9acd0e2b7f4af2d907b6263471126ed7da90f..50b086db1ab00761f2260da970b4c9d6e1d78e35 100644 (file)
@@ -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;
index f2beb3f5c9800ef05a324e095ee29c07b2a17fe9..76c85d8bc5829ca9e990793cbbf00d197a3f5a32 100644 (file)
@@ -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<()> {
index d3bed53e3f9ed73a190609b6fb9439a2c383abd7..1cd40b48b728e4e3db73d15b9dec57c8744c633b 100644 (file)
@@ -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<ColouredString>;
 
     fn as_extendable_indicator_mut(&mut self)
index bedb6923aa1a9e4945332a06374ff461eff17d20..b5c357f2fb40c4eab81afa42bed5dfea64af9bfc 100644 (file)
@@ -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<DateTime<Utc>>,
 }
 
-#[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<String>,
 }
 
-#[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<String>,
 }
 
-#[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,