updated reqwest and fixed media route

reqwest updated to 0.8
removed Result for creating Mastodon client as result of reqwest update
added Meta and ImageDetails struct for Attachment
Changed Attachment.id to String
Added test for media route.
Changed paramaters for media from Vec<u8> of image data to String of
file path.
Added dotenv for testing
master
Aaron Power 7 years ago
parent a0c69aac43
commit b6d350f29e
  1. 5
      .env.sample
  2. 1
      .gitignore
  3. 21
      src/entities/attachment.rs
  4. 82
      src/lib.rs
  5. 10
      src/registration.rs
  6. BIN
      tests/test.png
  7. 29
      tests/upload_photo.rs

@ -0,0 +1,5 @@
export TOKEN='snakeoil'
export CLIENT_ID=''
export CLIENT_SECRET=''
export REDIRECT=''
export BASE='https://mastodon.social'

1
.gitignore vendored

@ -1,2 +1,3 @@
target
Cargo.lock
.env

@ -1,12 +1,29 @@
#[derive(Debug, Clone, Deserialize)]
pub struct Attachment {
pub id: u64,
pub id: String,
#[serde(rename="type")]
pub media_type: MediaType,
pub url: String,
pub remote_url: String,
pub remote_url: Option<String>,
pub preview_url: String,
pub text_url: Option<String>,
pub meta: Option<Meta>,
pub description: Option<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Meta {
original: ImageDetails,
small: ImageDetails,
}
#[derive(Debug, Deserialize, Clone)]
pub struct ImageDetails {
width: u64,
height: u64,
size: String,
aspect: f64,
}
#[derive(Debug, Deserialize, Clone, Copy)]

@ -19,7 +19,7 @@
//! website: None,
//! };
//!
//! let mut registration = Registration::new("https://mastodon.social")?;
//! let mut registration = Registration::new("https://mastodon.social");
//! registration.register(app)?;
//! let url = registration.authorise()?;
//! // Here you now need to open the url in the browser
@ -56,7 +56,7 @@ use std::io::Error as IoError;
use json::Error as SerdeError;
use reqwest::Error as HttpError;
use reqwest::Client;
use reqwest::{Client, StatusCode};
use reqwest::header::{Authorization, Bearer, Headers};
use entities::prelude::*;
@ -92,6 +92,49 @@ macro_rules! methods {
macro_rules! route {
((post multipart ($($param:ident: $typ:ty,)*)) $name:ident: $url:expr => $ret:ty, $($rest:tt)*) => {
/// Equivalent to `/api/v1/
#[doc = $url]
/// `
///
#[doc = "# Errors"]
/// If `access_token` is not set.
pub fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
use std::io::Read;
use reqwest::multipart::Form;
let form_data = Form::new()
$(
.file(stringify!($param), $param)?
)*;
let mut response = self.client.post(&self.route(concat!("/api/v1/", $url)))
.headers(self.headers.clone())
.multipart(form_data)
.send()?;
let status = response.status().clone();
if status.is_client_error() {
return Err(Error::Client(status));
} else if status.is_server_error() {
return Err(Error::Server(status));
}
let mut vec = Vec::new();
response.read_to_end(&mut vec)?;
match json::from_slice::<$ret>(&vec) {
Ok(res) => Ok(res),
Err(_) => Err(Error::Api(json::from_slice(&vec)?)),
}
}
route!{$($rest)*}
};
((post ($($param:ident: $typ:ty,)*)) $name:ident: $url:expr => $ret:ty, $($rest:tt)*) => {
/// Equivalent to `/api/v1/
#[doc = $url]
@ -110,19 +153,27 @@ macro_rules! route {
let mut response = self.client.post(&self.route(concat!("/api/v1/", $url)))
.headers(self.headers.clone())
.form(&form_data)
.json(&form_data)
.send()?;
let status = response.status().clone();
if status.is_client_error() {
return Err(Error::Client(status));
} else if status.is_server_error() {
return Err(Error::Server(status));
}
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)?))
match json::from_slice(&vec) {
Ok(res) => Ok(res),
Err(_) => Err(Error::Api(json::from_slice(&vec)?)),
}
}
route!{$($rest)*}
};
@ -196,6 +247,10 @@ pub enum Error {
ClientSecretRequired,
#[serde(skip_deserializing)]
AccessTokenRequired,
#[serde(skip_deserializing)]
Client(StatusCode),
#[serde(skip_deserializing)]
Server(StatusCode),
}
impl fmt::Display for Error {
@ -211,6 +266,9 @@ impl StdError for Error {
Error::Serde(ref e) => e.description(),
Error::Http(ref e) => e.description(),
Error::Io(ref e) => e.description(),
Error::Client(ref status) | Error::Server(ref status) => {
status.canonical_reason().unwrap_or("Unknown Status code")
},
Error::ClientIdRequired => "ClientIdRequired",
Error::ClientSecretRequired => "ClientSecretRequired",
Error::AccessTokenRequired => "AccessTokenRequired",
@ -256,15 +314,15 @@ impl Mastodon {
}
/// Creates a mastodon instance from the data struct.
pub fn from_data(data: Data) -> Result<Self> {
pub fn from_data(data: Data) -> Self {
let mut headers = Headers::new();
headers.set(Authorization(Bearer { token: data.token.clone() }));
Ok(Mastodon {
client: Client::new()?,
Mastodon {
client: Client::new(),
headers: headers,
data: data,
})
}
}
route! {
@ -279,7 +337,7 @@ impl Mastodon {
(post (id: u64,)) reject_follow_request: "accounts/follow_requests/reject" => Empty,
(post (uri: String,)) follows: "follows" => Account,
(post) clear_notifications: "notifications/clear" => Empty,
(post (file: Vec<u8>,)) media: "media" => Attachment,
(post multipart (file: String,)) media: "media" => Attachment,
(post (account_id: u64, status_ids: Vec<u64>, comment: String,)) report:
"reports" => Report,
(post (q: String, resolve: bool,)) search: "search" => SearchResult,

@ -27,15 +27,15 @@ struct AccessToken {
}
impl Registration {
pub fn new<I: Into<String>>(base: I) -> Result<Self> {
Ok(Registration {
pub fn new<I: Into<String>>(base: I) -> Self {
Registration {
base: base.into(),
client: Client::new()?,
client: Client::new(),
client_id: None,
client_secret: None,
redirect: None,
scopes: Scope::Read,
})
}
}
/// Register the application with the server from the `base` url.
@ -56,7 +56,7 @@ impl Registration {
/// website: None,
/// };
///
/// let mut registration = Registration::new("https://mastodon.social")?;
/// let mut registration = Registration::new("https://mastodon.social");
/// registration.register(app)?;
/// let url = registration.authorise()?;
/// // Here you now need to open the url in the browser

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -0,0 +1,29 @@
extern crate mammut;
extern crate dotenv;
use std::env;
use mammut::{Data, Mastodon};
use dotenv::dotenv;
#[test]
fn upload_photo() {
dotenv().ok();
run().unwrap();
}
fn run() -> mammut::Result<()> {
let data = Data {
base: String::from(env::var("BASE").unwrap()),
client_id: String::from(env::var("CLIENT_ID").unwrap()),
client_secret: String::from(env::var("CLIENT_SECRET").unwrap()),
redirect: String::from(env::var("REDIRECT").unwrap()),
token: String::from(env::var("TOKEN").unwrap()),
};
let mastodon = Mastodon::from_data(data);
mastodon.media("tests/test.png".into())?;
Ok(())
}
Loading…
Cancel
Save