Version 0.6

Added proper error handling
impl fmt::Display for apps::Scope
make StatusBuilder.status public
master
Aaron Power 7 years ago
parent 52f8d5e500
commit 39e539646b
  1. 2
      Cargo.toml
  2. 15
      src/apps.rs
  3. 123
      src/lib.rs
  4. 8
      src/registration.rs
  5. 2
      src/status_builder.rs

@ -1,6 +1,6 @@
[package]
name = "mammut"
version = "0.5.2"
version = "0.6.0"
description = "A wrapper around the Mastodon API."
authors = ["Aaron Power <theaaronepower@gmail.com>"]
license = "MIT/Apache-2.0"

@ -37,6 +37,21 @@ pub enum Scope {
WriteFollow,
}
impl ::std::fmt::Display for Scope {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
use self::Scope::*;
write!(f, "{}", match *self {
All => "read write follow",
Follow => "follow",
Read => "read",
ReadFollow => "read follow",
ReadWrite => "read write",
Write => "write",
WriteFollow => "write follow"
})
}
}
impl Default for Scope {
fn default() -> Self {
Scope::Read

@ -50,6 +50,7 @@ pub mod entities;
pub mod registration;
use std::ops;
use std::io::Error as IoError;
use json::Error as SerdeError;
use reqwest::Error as HttpError;
@ -57,7 +58,7 @@ use reqwest::Client;
use reqwest::header::{Authorization, Bearer, Headers};
use entities::prelude::*;
use status_builder::StatusBuilder;
pub use status_builder::StatusBuilder;
pub use registration::Registration;
pub type Result<T> = std::result::Result<T, Error>;
@ -72,11 +73,7 @@ macro_rules! methods {
.headers(self.headers.clone())
.send()?;
if let Ok(t) = response.json::<T>() {
Ok(t)
} else {
Err(Error::Api(response.json()?))
}
response.json()?
}
)+
};
@ -92,23 +89,24 @@ macro_rules! route {
#[doc = "# Errors"]
/// If `access_token` is not set.
pub fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
use std::io::Read;
let form_data = json!({
$(
stringify!($param): $param,
)*
)*
});
let mut response = self.client.post(&self.route(concat!("/api/v1/", $url)))
.headers(self.headers.clone())
.form(&form_data)
.send()?;
if let Ok(t) = response.json::<$ret>() {
Ok(t)
} else {
Err(Error::Api(response.json()?))
}
.headers(self.headers.clone())
.form(&form_data)
.send()?;
let mut vec = Vec::new();
response.read_to_end(&mut vec)?;
json::from_slice(&vec)?
}
route!{$($rest)*}
};
@ -167,13 +165,21 @@ pub struct Data {
pub token: String,
}
#[derive(Debug)]
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum Error {
Api(ApiError),
#[serde(skip_deserializing)]
Serde(SerdeError),
#[serde(skip_deserializing)]
Http(HttpError),
#[serde(skip_deserializing)]
Io(IoError),
#[serde(skip_deserializing)]
ClientIdRequired,
#[serde(skip_deserializing)]
ClientSecretRequired,
#[serde(skip_deserializing)]
AccessTokenRequired,
}
@ -183,7 +189,7 @@ pub struct ApiError {
/// The type of error.
pub error: String,
/// The description of the error.
pub error_description: String,
pub error_description: Option<String>,
}
impl Mastodon {
@ -194,25 +200,25 @@ impl Mastodon {
token: String,
client: Client)
-> Self
{
let data = Data {
base: base,
client_id: client_id,
client_secret: client_secret,
redirect: redirect,
token: token,
{
let data = Data {
base: base,
client_id: client_id,
client_secret: client_secret,
redirect: redirect,
token: token,
};
};
let mut headers = Headers::new();
headers.set(Authorization(Bearer { token: data.token.clone() }));
let mut headers = Headers::new();
headers.set(Authorization(Bearer { token: data.token.clone() }));
Mastodon {
client: client,
headers: headers,
data: data,
Mastodon {
client: client,
headers: headers,
data: data,
}
}
}
/// Creates a mastodon instance from the data struct.
pub fn from_data(data: Data) -> Result<Self> {
@ -242,7 +248,6 @@ impl Mastodon {
(post (account_id: u64, status_ids: Vec<u64>, comment: String,)) report:
"reports" => Report,
(post (q: String, resolve: bool,)) search: "search" => SearchResult,
(post (status: StatusBuilder,)) new_status: "statuses" => Status,
}
route_id! {
@ -268,6 +273,25 @@ impl Mastodon {
(delete) delete_status: "statuses/{}" => Empty,
}
pub fn new_status(&self, status: StatusBuilder) -> Result<Status> {
use std::io::Read;
let mut response = self.client.post(&self.route("/api/v1/statuses"))
.headers(self.headers.clone())
.json(&status)
.send().expect("STAUS BUILDER IS BAD");
let mut vec = Vec::new();
response.read_to_end(&mut vec)?;
if let Ok(t) = json::from_slice(&vec) {
Ok(t)
} else {
Err(Error::Api(json::from_slice(&vec)?))
}
}
pub fn get_public_timeline(&self, local: bool) -> Result<Vec<Status>> {
let mut url = self.route("/api/v1/timelines/public");
@ -291,25 +315,25 @@ impl Mastodon {
pub fn statuses(&self, id: u64, only_media: bool, exclude_replies: bool)
-> Result<Vec<Status>>
{
let mut url = format!("{}/api/v1/accounts/{}/statuses", self.base, id);
{
let mut url = format!("{}/api/v1/accounts/{}/statuses", self.base, id);
if only_media {
url += "?only_media=1";
}
if only_media {
url += "?only_media=1";
}
if exclude_replies {
url += if only_media {
"&"
} else {
"?"
};
if exclude_replies {
url += if only_media {
"&"
} else {
"?"
};
url += "exclude_replies=1";
}
url += "exclude_replies=1";
}
self.get(url)
}
self.get(url)
}
pub fn relationships(&self, ids: &[u64]) -> Result<Vec<Relationship>> {
@ -372,4 +396,5 @@ macro_rules! from {
from! {
SerdeError, Serde,
HttpError, Http,
IoError, Io,
}

@ -1,7 +1,7 @@
use reqwest::Client;
use super::{Error, Mastodon, Result};
use apps::AppBuilder;
use apps::{AppBuilder, Scope};
/// Handles registering your mastodon app to your instance. It is recommended
/// you cache your data struct to avoid registering on every run.
@ -11,6 +11,7 @@ pub struct Registration {
client_id: Option<String>,
client_secret: Option<String>,
redirect: Option<String>,
scopes: Scope,
}
#[derive(Deserialize)]
@ -33,6 +34,7 @@ impl Registration {
client_id: None,
client_secret: None,
redirect: None,
scopes: Scope::Read,
})
}
@ -68,6 +70,7 @@ impl Registration {
/// ```
pub fn register(&mut self, app_builder: AppBuilder) -> Result<()> {
let url = format!("{}/api/v1/apps", self.base);
self.scopes = app_builder.scopes;
let app: OAuth = self.client.post(&url).form(&app_builder).send()?.json()?;
@ -84,10 +87,11 @@ impl Registration {
self.is_registered()?;
let url = format!(
"{}/oauth/authorize?client_id={}&redirect_uri={}&response_type=code",
"{}/oauth/authorize?client_id={}&redirect_uri={}&scope={}&response_type=code",
self.base,
self.client_id.clone().unwrap(),
self.redirect.clone().unwrap(),
self.scopes,
);
Ok(url)

@ -1,6 +1,6 @@
#[derive(Debug, Default, Clone, Serialize)]
pub struct StatusBuilder {
status: String,
pub status: String,
/// User ids of those to reply to.
#[serde(skip_serializing_if="Option::is_none")]
pub in_reply_to_id: Option<u64>,

Loading…
Cancel
Save