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.
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 {
}
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
+ }
}
--- /dev/null
+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())
+ }
+}
+
pub mod scan_re;
pub mod coloured_string;
pub mod text;
-
-#[derive(Debug)]
-pub enum OurError {
- Fatal(String),
-}
+pub mod client;
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::{
};
use std::io::stdout;
+/*
#[allow(unused)]
fn streaming() -> Result<(), mastodonochrome::OurError> {
let auth = AuthConfig::load()?;
Ok(())
}
+*/
#[allow(unused)]
fn tui() -> std::io::Result<()> {
// 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)
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,
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,
#[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,
#[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,
pub description: Option<String>,
}
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct StatusMention {
pub id: String,
pub username: String,
pub acct: String,
}
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Status {
pub id: String,
pub uri: String,