Version 0.6
Added proper error handling impl fmt::Display for apps::Scope make StatusBuilder.status public
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mammut"
|
name = "mammut"
|
||||||
version = "0.5.2"
|
version = "0.6.0"
|
||||||
description = "A wrapper around the Mastodon API."
|
description = "A wrapper around the Mastodon API."
|
||||||
authors = ["Aaron Power <theaaronepower@gmail.com>"]
|
authors = ["Aaron Power <theaaronepower@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
|
|||||||
+15
@@ -37,6 +37,21 @@ pub enum Scope {
|
|||||||
WriteFollow,
|
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 {
|
impl Default for Scope {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Scope::Read
|
Scope::Read
|
||||||
|
|||||||
+75
-50
@@ -50,6 +50,7 @@ pub mod entities;
|
|||||||
pub mod registration;
|
pub mod registration;
|
||||||
|
|
||||||
use std::ops;
|
use std::ops;
|
||||||
|
use std::io::Error as IoError;
|
||||||
|
|
||||||
use json::Error as SerdeError;
|
use json::Error as SerdeError;
|
||||||
use reqwest::Error as HttpError;
|
use reqwest::Error as HttpError;
|
||||||
@@ -57,7 +58,7 @@ use reqwest::Client;
|
|||||||
use reqwest::header::{Authorization, Bearer, Headers};
|
use reqwest::header::{Authorization, Bearer, Headers};
|
||||||
|
|
||||||
use entities::prelude::*;
|
use entities::prelude::*;
|
||||||
use status_builder::StatusBuilder;
|
pub use status_builder::StatusBuilder;
|
||||||
|
|
||||||
pub use registration::Registration;
|
pub use registration::Registration;
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
@@ -72,11 +73,7 @@ macro_rules! methods {
|
|||||||
.headers(self.headers.clone())
|
.headers(self.headers.clone())
|
||||||
.send()?;
|
.send()?;
|
||||||
|
|
||||||
if let Ok(t) = response.json::<T>() {
|
response.json()?
|
||||||
Ok(t)
|
|
||||||
} else {
|
|
||||||
Err(Error::Api(response.json()?))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
@@ -92,23 +89,24 @@ macro_rules! route {
|
|||||||
#[doc = "# Errors"]
|
#[doc = "# Errors"]
|
||||||
/// If `access_token` is not set.
|
/// If `access_token` is not set.
|
||||||
pub fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
|
pub fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
let form_data = json!({
|
let form_data = json!({
|
||||||
$(
|
$(
|
||||||
stringify!($param): $param,
|
stringify!($param): $param,
|
||||||
)*
|
)*
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut response = self.client.post(&self.route(concat!("/api/v1/", $url)))
|
let mut response = self.client.post(&self.route(concat!("/api/v1/", $url)))
|
||||||
.headers(self.headers.clone())
|
.headers(self.headers.clone())
|
||||||
.form(&form_data)
|
.form(&form_data)
|
||||||
.send()?;
|
.send()?;
|
||||||
|
|
||||||
if let Ok(t) = response.json::<$ret>() {
|
let mut vec = Vec::new();
|
||||||
Ok(t)
|
|
||||||
} else {
|
response.read_to_end(&mut vec)?;
|
||||||
Err(Error::Api(response.json()?))
|
|
||||||
}
|
json::from_slice(&vec)?
|
||||||
}
|
}
|
||||||
route!{$($rest)*}
|
route!{$($rest)*}
|
||||||
};
|
};
|
||||||
@@ -167,13 +165,21 @@ pub struct Data {
|
|||||||
pub token: String,
|
pub token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
Api(ApiError),
|
Api(ApiError),
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
Serde(SerdeError),
|
Serde(SerdeError),
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
Http(HttpError),
|
Http(HttpError),
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
Io(IoError),
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
ClientIdRequired,
|
ClientIdRequired,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
ClientSecretRequired,
|
ClientSecretRequired,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
AccessTokenRequired,
|
AccessTokenRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +189,7 @@ pub struct ApiError {
|
|||||||
/// The type of error.
|
/// The type of error.
|
||||||
pub error: String,
|
pub error: String,
|
||||||
/// The description of the error.
|
/// The description of the error.
|
||||||
pub error_description: String,
|
pub error_description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mastodon {
|
impl Mastodon {
|
||||||
@@ -194,25 +200,25 @@ impl Mastodon {
|
|||||||
token: String,
|
token: String,
|
||||||
client: Client)
|
client: Client)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
let data = Data {
|
let data = Data {
|
||||||
base: base,
|
base: base,
|
||||||
client_id: client_id,
|
client_id: client_id,
|
||||||
client_secret: client_secret,
|
client_secret: client_secret,
|
||||||
redirect: redirect,
|
redirect: redirect,
|
||||||
token: token,
|
token: token,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut headers = Headers::new();
|
let mut headers = Headers::new();
|
||||||
headers.set(Authorization(Bearer { token: data.token.clone() }));
|
headers.set(Authorization(Bearer { token: data.token.clone() }));
|
||||||
|
|
||||||
Mastodon {
|
Mastodon {
|
||||||
client: client,
|
client: client,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
data: data,
|
data: data,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a mastodon instance from the data struct.
|
/// Creates a mastodon instance from the data struct.
|
||||||
pub fn from_data(data: Data) -> Result<Self> {
|
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:
|
(post (account_id: u64, status_ids: Vec<u64>, comment: String,)) report:
|
||||||
"reports" => Report,
|
"reports" => Report,
|
||||||
(post (q: String, resolve: bool,)) search: "search" => SearchResult,
|
(post (q: String, resolve: bool,)) search: "search" => SearchResult,
|
||||||
(post (status: StatusBuilder,)) new_status: "statuses" => Status,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
route_id! {
|
route_id! {
|
||||||
@@ -268,6 +273,25 @@ impl Mastodon {
|
|||||||
(delete) delete_status: "statuses/{}" => Empty,
|
(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>> {
|
pub fn get_public_timeline(&self, local: bool) -> Result<Vec<Status>> {
|
||||||
let mut url = self.route("/api/v1/timelines/public");
|
let mut url = self.route("/api/v1/timelines/public");
|
||||||
|
|
||||||
@@ -291,26 +315,26 @@ impl Mastodon {
|
|||||||
|
|
||||||
pub fn statuses(&self, id: u64, only_media: bool, exclude_replies: bool)
|
pub fn statuses(&self, id: u64, only_media: bool, exclude_replies: bool)
|
||||||
-> Result<Vec<Status>>
|
-> 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 {
|
if only_media {
|
||||||
url += "?only_media=1";
|
url += "?only_media=1";
|
||||||
|
}
|
||||||
|
|
||||||
|
if exclude_replies {
|
||||||
|
url += if only_media {
|
||||||
|
"&"
|
||||||
|
} else {
|
||||||
|
"?"
|
||||||
|
};
|
||||||
|
|
||||||
|
url += "exclude_replies=1";
|
||||||
|
}
|
||||||
|
|
||||||
|
self.get(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
if exclude_replies {
|
|
||||||
url += if only_media {
|
|
||||||
"&"
|
|
||||||
} else {
|
|
||||||
"?"
|
|
||||||
};
|
|
||||||
|
|
||||||
url += "exclude_replies=1";
|
|
||||||
}
|
|
||||||
|
|
||||||
self.get(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn relationships(&self, ids: &[u64]) -> Result<Vec<Relationship>> {
|
pub fn relationships(&self, ids: &[u64]) -> Result<Vec<Relationship>> {
|
||||||
let mut url = self.route("/api/v1/accounts/relationships?");
|
let mut url = self.route("/api/v1/accounts/relationships?");
|
||||||
@@ -372,4 +396,5 @@ macro_rules! from {
|
|||||||
from! {
|
from! {
|
||||||
SerdeError, Serde,
|
SerdeError, Serde,
|
||||||
HttpError, Http,
|
HttpError, Http,
|
||||||
|
IoError, Io,
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -1,7 +1,7 @@
|
|||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
|
||||||
use super::{Error, Mastodon, Result};
|
use super::{Error, Mastodon, Result};
|
||||||
use apps::AppBuilder;
|
use apps::{AppBuilder, Scope};
|
||||||
|
|
||||||
/// Handles registering your mastodon app to your instance. It is recommended
|
/// Handles registering your mastodon app to your instance. It is recommended
|
||||||
/// you cache your data struct to avoid registering on every run.
|
/// you cache your data struct to avoid registering on every run.
|
||||||
@@ -11,6 +11,7 @@ pub struct Registration {
|
|||||||
client_id: Option<String>,
|
client_id: Option<String>,
|
||||||
client_secret: Option<String>,
|
client_secret: Option<String>,
|
||||||
redirect: Option<String>,
|
redirect: Option<String>,
|
||||||
|
scopes: Scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@@ -33,6 +34,7 @@ impl Registration {
|
|||||||
client_id: None,
|
client_id: None,
|
||||||
client_secret: None,
|
client_secret: None,
|
||||||
redirect: None,
|
redirect: None,
|
||||||
|
scopes: Scope::Read,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +70,7 @@ impl Registration {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn register(&mut self, app_builder: AppBuilder) -> Result<()> {
|
pub fn register(&mut self, app_builder: AppBuilder) -> Result<()> {
|
||||||
let url = format!("{}/api/v1/apps", self.base);
|
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()?;
|
let app: OAuth = self.client.post(&url).form(&app_builder).send()?.json()?;
|
||||||
|
|
||||||
@@ -84,10 +87,11 @@ impl Registration {
|
|||||||
self.is_registered()?;
|
self.is_registered()?;
|
||||||
|
|
||||||
let url = format!(
|
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.base,
|
||||||
self.client_id.clone().unwrap(),
|
self.client_id.clone().unwrap(),
|
||||||
self.redirect.clone().unwrap(),
|
self.redirect.clone().unwrap(),
|
||||||
|
self.scopes,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(url)
|
Ok(url)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#[derive(Debug, Default, Clone, Serialize)]
|
#[derive(Debug, Default, Clone, Serialize)]
|
||||||
pub struct StatusBuilder {
|
pub struct StatusBuilder {
|
||||||
status: String,
|
pub status: String,
|
||||||
/// User ids of those to reply to.
|
/// User ids of those to reply to.
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
pub in_reply_to_id: Option<u64>,
|
pub in_reply_to_id: Option<u64>,
|
||||||
|
|||||||
Reference in New Issue
Block a user