1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#![deny(missing_docs)]

/*!
Rust API client for the instances.social API
*/

#[macro_use]
extern crate serde_derive;

use std::error::Error;

use serde::{Deserialize, Serialize};
use tap_reader::Tap;
use url::{ParseError, Url};

pub mod instances;
pub mod versions;

fn url(path: &str) -> Result<Url, ParseError> {
    let url = format!("https://instances.social/api/1.0/{}", path);
    Url::parse(&url)
}

/// Instances.social client
///
/// requires an API token
pub struct Client {
    token: String,
    client: reqwest::Client,
}

impl Client {
    /// Create a new client from a token
    pub fn new(token: &str) -> Client {
        Client {
            token: token.into(),
            client: reqwest::Client::new(),
        }
    }

    fn token(&self) -> String {
        format!("Bearer {}", self.token)
    }

    /// Access the /versions/* API calls
    pub fn versions(&self) -> Versions {
        Versions(self)
    }

    /// Access the /instances/* API calls
    pub fn instances(&self) -> Instances {
        Instances(self)
    }

    fn get_qs<S: Serialize>(
        &self,
        path: &str,
        data: S,
    ) -> Result<reqwest::RequestBuilder, Box<Error>> {
        let mut url = url(path)?;
        let qs = serde_qs::to_string(&data)?;
        url.set_query(Some(qs.as_ref()));
        Ok(self
            .client
            .get(url.as_str())
            .header(reqwest::header::AUTHORIZATION, &self.token()[..]))
    }

    fn send<D>(&self, req: reqwest::RequestBuilder) -> Result<D, Box<Error>>
    where
        for<'de> D: Deserialize<'de>,
    {
        let mut resp = req.send()?;
        let text = resp.text()?;
        eprintln!("{}", text);
        Ok(serde_json::from_str(&text)?)
        /*
        let mut reader = Tap::new(resp);
        Ok(match serde_json::from_reader(&mut reader) {
            Ok(r) => r,
            Err(e) => {
                let err = String::from_utf8_lossy(&reader.bytes);
                eprintln!("error: {:?}\nsource: {}", e, err);
                return Err(e.into());
            }
        })
        */
    }
}

/// Container for the /versions/* API calls
pub struct Versions<'a>(&'a Client);
impl<'a> Versions<'a> {
    /// Starts build a versions/list call
    pub fn list(&self) -> versions::ListRequestBuilder {
        versions::ListRequestBuilder::new(self.0)
    }

    /// Starts building a versions/show call
    pub fn show(&self, name: &str) -> versions::ShowRequestBuilder {
        versions::ShowRequestBuilder::new(self.0, name)
    }
}

/// Container for the /instances/* API calls
pub struct Instances<'a>(&'a Client);
impl<'a> Instances<'a> {
    /// Starts building an instances/sample call
    pub fn sample(&self) -> instances::SampleRequestBuilder {
        instances::SampleRequestBuilder::new(self.0)
    }

    /// Starts building an instances/list call
    pub fn list(&self) -> instances::ListRequestBuilder {
        instances::ListRequestBuilder::new(self.0)
    }

    /// Starts building an instances/search call
    pub fn search(&self, q: &str) -> instances::SearchRequestBuilder {
        instances::SearchRequestBuilder::new(self.0, q)
    }

    /// Starts building an instances/show call
    pub fn show(&self, name: &str) -> instances::ShowRequestBuilder {
        instances::ShowRequestBuilder::new(self.0, name)
    }
}