rustfmt pass

master
Paul Woolcock 6 years ago
parent d617d74fa4
commit 8636e690c3
  1. 2
      README.md
  2. 1
      examples/print_your_profile.rs
  3. 19
      examples/register.rs
  4. 1
      rustfmt.toml
  5. 58
      src/apps.rs
  6. 29
      src/entities/account.rs
  7. 3
      src/entities/attachment.rs
  8. 9
      src/entities/itemsiter.rs
  9. 35
      src/entities/mod.rs
  10. 3
      src/entities/notification.rs
  11. 2
      src/entities/status.rs
  12. 20
      src/errors.rs
  13. 325
      src/lib.rs
  14. 2
      src/macros.rs
  15. 36
      src/page.rs
  16. 23
      src/registration.rs
  17. 7
      src/requests/statuses.rs
  18. 13
      src/status_builder.rs

@ -7,7 +7,7 @@
## [Documentation](https://docs.rs/elefren/)
A wrapper around the [API](https://github.com/tootsuite/mastodon/blob/master/docs/Using-the-API/API.md#tag) for [Mastodon](https://mastodon.social/)
A wrapper around the [API](https://github.com/tootsuite/documentation/blob/master/docs/Using-the-API/API.md#tag) for [Mastodon](https://mastodon.social/)
```rust
extern crate elefren;

@ -3,7 +3,6 @@ mod register;
use register::MastodonClient;
use std::error;
fn main() -> Result<(), Box<error::Error>> {
let mastodon = register::get_mastodon_data()?;
let you = mastodon.verify_credentials()?;

@ -3,19 +3,12 @@ extern crate toml;
pub use self::elefren::{Data, MastodonClient};
use std::{
error::Error,
fs,
io,
};
use std::{error::Error, fs, io};
use self::elefren::{
apps::{
App,
Scopes
},
apps::{App, Scopes},
Mastodon,
Registration
Registration,
};
#[allow(dead_code)]
@ -24,7 +17,6 @@ fn main() -> Result<(), Box<Error>> {
Ok(())
}
#[allow(dead_code)]
pub fn get_mastodon_data() -> Result<Mastodon, Box<Error>> {
if let Ok(config) = fs::read_to_string("mastodon-data.toml") {
@ -38,8 +30,8 @@ pub fn get_mastodon_data() -> Result<Mastodon, Box<Error>> {
pub fn register() -> Result<Mastodon, Box<Error>> {
let mut app = App::builder();
app.client_name("elefren-examples")
.scopes(Scopes::All)
.website("https://github.com/pwoolcoc/elefren");
.scopes(Scopes::All)
.website("https://github.com/pwoolcoc/elefren");
let website = read_line("Please enter your mastodon instance url:")?;
let registration = Registration::new(website.trim());
@ -67,4 +59,3 @@ pub fn read_line(message: &str) -> Result<String, Box<Error>> {
Ok(input)
}

@ -1,4 +1,3 @@
indent_style = "Visual"
format_strings = true
format_macro_matchers = true
imports_layout = "HorizontalVertical"

@ -1,5 +1,4 @@
use std::fmt;
use std::borrow::Cow;
use std::{borrow::Cow, fmt};
use try_from::TryInto;
@ -8,13 +7,8 @@ use errors::{Error, Result};
/// Provides the necessary types for registering an App and getting the
/// necessary auth information
pub mod prelude {
pub use {
apps::{
App,
Scopes
},
registration::Registration
};
pub use apps::{App, Scopes};
pub use registration::Registration;
}
/// Represents an application that can be registered with a mastodon instance
@ -23,7 +17,7 @@ pub struct App {
client_name: String,
redirect_uris: String,
scopes: Scopes,
#[serde(skip_serializing_if="Option::is_none")]
#[serde(skip_serializing_if = "Option::is_none")]
website: Option<String>,
}
@ -39,8 +33,8 @@ impl App {
/// Builder struct for defining your application.
/// ```
/// use std::error::Error;
/// use elefren::apps::prelude::*;
/// use std::error::Error;
///
/// # fn main() -> Result<(), Box<Error>> {
/// let mut builder = App::builder();
@ -98,14 +92,15 @@ impl<'a> AppBuilder<'a> {
/// Will fail if no `client_name` was provided
pub fn build(self) -> Result<App> {
Ok(App {
client_name: self.client_name
.ok_or_else(|| Error::MissingField("client_name"))?
.into(),
redirect_uris: self.redirect_uris
.unwrap_or_else(|| "urn:ietf:wg:oauth:2.0:oob".into())
.into(),
scopes: self.scopes
.unwrap_or_else(|| Scopes::Read),
client_name: self
.client_name
.ok_or_else(|| Error::MissingField("client_name"))?
.into(),
redirect_uris: self
.redirect_uris
.unwrap_or_else(|| "urn:ietf:wg:oauth:2.0:oob".into())
.into(),
scopes: self.scopes.unwrap_or_else(|| Scopes::Read),
website: self.website.map(|s| s.into()),
})
}
@ -128,7 +123,8 @@ impl<'a> TryInto<App> for AppBuilder<'a> {
}
/// Permission scope of the application.
/// [Details on what each permission provides](//github.com/tootsuite/documentation/blob/master/Using-the-API/OAuth-details.md)
/// [Details on what each permission provides][1]
/// [1]: https://github.com/tootsuite/documentation/blob/master/Using-the-API/OAuth-details.md)
#[derive(Debug, Clone, Copy, Serialize)]
pub enum Scopes {
/// All Permissions, equivalent to `read write follow`
@ -157,15 +153,19 @@ pub enum Scopes {
impl fmt::Display for Scopes {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Scopes::*;
write!(f, "{}", match *self {
All => "read%20write%20follow",
Follow => "follow",
Read => "read",
ReadFollow => "read%20follow",
ReadWrite => "read%20write",
Write => "write",
WriteFollow => "write%20follow"
})
write!(
f,
"{}",
match *self {
All => "read%20write%20follow",
Follow => "follow",
Read => "read",
ReadFollow => "read%20follow",
ReadWrite => "read%20write",
Write => "write",
WriteFollow => "write%20follow",
}
)
}
}

@ -2,9 +2,9 @@
use chrono::prelude::*;
use reqwest::multipart::Form;
use ::Result;
use std::path::Path;
use serde::de::{self, Deserialize, Deserializer, Unexpected};
use std::path::Path;
use Result;
/// A struct representing an Account.
#[derive(Debug, Clone, Deserialize)]
@ -57,9 +57,7 @@ pub struct Source {
note: String,
}
fn string_or_bool<'de, D: Deserializer<'de>>(val: D)
-> ::std::result::Result<bool, D::Error>
{
fn string_or_bool<'de, D: Deserializer<'de>>(val: D) -> ::std::result::Result<bool, D::Error> {
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum BoolOrString {
@ -68,16 +66,19 @@ fn string_or_bool<'de, D: Deserializer<'de>>(val: D)
}
Ok(match BoolOrString::deserialize(val)? {
BoolOrString::Bool(b) => b,
BoolOrString::Str(ref s) => {
if s == "true" {
true
} else if s == "false" {
false
} else {
return Err(de::Error::invalid_value(Unexpected::Str(s), &"true or false"));
}
BoolOrString::Bool(b) => b,
BoolOrString::Str(ref s) => {
if s == "true" {
true
} else if s == "false" {
false
} else {
return Err(de::Error::invalid_value(
Unexpected::Str(s),
&"true or false",
));
}
},
})
}

@ -6,7 +6,7 @@ pub struct Attachment {
/// ID of the attachment.
pub id: String,
/// The media type of an attachment.
#[serde(rename="type")]
#[serde(rename = "type")]
pub media_type: MediaType,
/// URL of the locally hosted version of the image.
pub url: String,
@ -43,7 +43,6 @@ pub struct ImageDetails {
size: String,
/// The aspect ratio of the attachment.
aspect: f64,
}
/// The type of media attachment.

@ -18,7 +18,7 @@ use serde::Deserialize;
/// let client = Mastodon::from(data);
/// let statuses = client.statuses("user-id", None)?;
/// for status in statuses.items_iter() {
/// // do something with `status`
/// // do something with `status`
/// }
/// # Ok(())
/// # }
@ -33,7 +33,7 @@ pub(crate) struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>> {
impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
pub(crate) fn new(page: Page<'a, T>) -> ItemsIter<'a, T> {
ItemsIter {
page: page,
page,
buffer: vec![],
cur_idx: 0,
use_initial: true,
@ -41,8 +41,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
}
fn need_next_page(&self) -> bool {
self.buffer.is_empty() ||
self.cur_idx == self.buffer.len()
self.buffer.is_empty() || self.cur_idx == self.buffer.len()
}
fn fill_next_page(&mut self) -> Option<()> {
@ -61,7 +60,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
}
}
impl<'a, T: Clone+ for<'de> Deserialize<'de>> Iterator for ItemsIter<'a, T> {
impl<'a, T: Clone + for<'de> Deserialize<'de>> Iterator for ItemsIter<'a, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {

@ -3,10 +3,10 @@ pub mod attachment;
pub mod card;
pub mod context;
pub mod instance;
pub(crate) mod itemsiter;
pub mod list;
pub mod mention;
pub mod notification;
pub(crate) mod itemsiter;
pub mod relationship;
pub mod report;
pub mod search_result;
@ -17,19 +17,22 @@ pub mod status;
pub struct Empty {}
pub mod prelude {
//! The purpose of this module is to alleviate imports of many common structs
//! by adding a glob import to the top of mastodon heavy modules:
pub use super::Empty;
pub use super::account::{Account, CredientialsBuilder, Source};
pub use super::attachment::{Attachment, MediaType};
pub use super::card::Card;
pub use super::context::Context;
pub use super::instance::*;
pub use super::list::List;
pub use super::mention::Mention;
pub use super::notification::Notification;
pub use super::relationship::Relationship;
pub use super::report::Report;
pub use super::search_result::SearchResult;
pub use super::status::{Application, Emoji, Status};
//! The purpose of this module is to alleviate imports of many common
//! structs by adding a glob import to the top of mastodon heavy
//! modules:
pub use super::{
account::{Account, CredientialsBuilder, Source},
attachment::{Attachment, MediaType},
card::Card,
context::Context,
instance::*,
list::List,
mention::Mention,
notification::Notification,
relationship::Relationship,
report::Report,
search_result::SearchResult,
status::{Application, Emoji, Status},
Empty,
};
}

@ -1,8 +1,7 @@
//! Module containing all info about notifications.
use super::{account::Account, status::Status};
use chrono::prelude::*;
use super::account::Account;
use super::status::Status;
/// A struct containing info about a notification.
#[derive(Debug, Clone, Deserialize)]

@ -1,7 +1,7 @@
//! Module containing all info relating to a status.
use chrono::prelude::*;
use super::prelude::*;
use chrono::prelude::*;
use status_builder::Visibility;
/// A status from the instance.

@ -1,12 +1,7 @@
use std::{
fmt,
error,
io::Error as IoError
};
use std::{error, fmt, io::Error as IoError};
use json::Error as SerdeError;
use reqwest::Error as HttpError;
use reqwest::StatusCode;
use reqwest::{Error as HttpError, StatusCode};
use url::ParseError as UrlError;
/// Convience type over `std::result::Result` with `Error` as the error type.
@ -52,11 +47,12 @@ impl fmt::Display for Error {
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Api(ref e) => {
e.error_description.as_ref().map(|i| &**i)
.or(e.error.as_ref().map(|i| &**i))
.unwrap_or("Unknown API Error")
},
Error::Api(ref e) => e
.error_description
.as_ref()
.map(|i| &**i)
.or(e.error.as_ref().map(|i| &**i))
.unwrap_or("Unknown API Error"),
Error::Serde(ref e) => e.description(),
Error::Http(ref e) => e.description(),
Error::Io(ref e) => e.description(),

@ -9,14 +9,12 @@
//! # try().unwrap();
//! # }
//! # fn try() -> elefren::Result<()> {
//! use elefren::prelude::*;
//! use elefren::apps::prelude::*;
//! use elefren::{apps::prelude::*, prelude::*};
//!
//! let mut app = App::builder();
//! app.client_name("elefren_test");
//!
//! let registration = Registration::new("https://mastodon.social")
//! .register(app)?;
//! let registration = Registration::new("https://mastodon.social").register(app)?;
//! let url = registration.authorize_url()?;
//! // Here you now need to open the url in the browser
//! // And handle a the redirect url coming back with the code.
@ -31,47 +29,57 @@
#![cfg_attr(test, deny(warnings))]
#![cfg_attr(test, deny(missing_docs))]
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate doc_comment;
#[macro_use] extern crate serde_json as json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate doc_comment;
#[macro_use]
extern crate serde_json as json;
extern crate chrono;
extern crate reqwest;
extern crate serde;
extern crate try_from;
extern crate url;
use std::borrow::Cow;
use std::ops;
use std::{borrow::Cow, ops};
use reqwest::{Client, Response};
use reqwest::header::{Authorization, Bearer, Headers};
use reqwest::{
header::{Authorization, Bearer, Headers},
Client,
Response,
};
use entities::prelude::*;
use page::Page;
pub use status_builder::StatusBuilder;
pub use requests::statuses::StatusesRequest;
pub use errors::{Result, Error, ApiError};
pub use errors::{ApiError, Error, Result};
pub use registration::Registration;
pub use requests::statuses::StatusesRequest;
pub use status_builder::StatusBuilder;
/// Registering your App
pub mod apps;
/// Constructing a status
pub mod status_builder;
/// Entities returned from the API
pub mod entities;
/// Registering your app.
pub mod registration;
/// Handling multiple pages of entities.
pub mod page;
/// Errors
pub mod errors;
/// Handling multiple pages of entities.
pub mod page;
/// Registering your app.
pub mod registration;
/// Requests
pub mod requests;
#[macro_use] mod macros;
/// Constructing a status
pub mod status_builder;
#[macro_use]
mod macros;
/// Automatically import the things you need
pub mod prelude {
pub use {Data, Mastodon, MastodonClient, StatusBuilder, StatusesRequest};
pub use Data;
pub use Mastodon;
pub use MastodonClient;
pub use StatusBuilder;
pub use StatusesRequest;
}
/// Your mastodon application client, handles all requests to and from Mastodon.
@ -80,7 +88,7 @@ pub struct Mastodon {
client: Client,
headers: Headers,
/// Raw data about your mastodon instance.
pub data: Data
pub data: Data,
}
/// Raw data about mastodon app. Save `Data` using `serde` to prevent needing
@ -103,53 +111,155 @@ pub struct Data {
/// implementations might be swapped out for testing
#[allow(unused)]
pub trait MastodonClient {
fn favourites(&self) -> Result<Page<Status>> { unimplemented!("This method was not implemented"); }
fn blocks(&self) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn domain_blocks(&self) -> Result<Page<String>> { unimplemented!("This method was not implemented"); }
fn follow_requests(&self) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn get_home_timeline(&self) -> Result<Page<Status>> { unimplemented!("This method was not implemented"); }
fn get_emojis(&self) -> Result<Page<Emoji>> { unimplemented!("This method was not implemented"); }
fn mutes(&self) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn notifications(&self) -> Result<Page<Notification>> { unimplemented!("This method was not implemented"); }
fn reports(&self) -> Result<Page<Report>> { unimplemented!("This method was not implemented"); }
fn followers(&self, id: &str) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn following(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn reblogged_by(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn favourited_by(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn unblock_domain(&self, domain: String) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn instance(&self) -> Result<Instance> { unimplemented!("This method was not implemented"); }
fn verify_credentials(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn report(&self, account_id: &str, status_ids: Vec<&str>, comment: String) -> Result<Report> { unimplemented!("This method was not implemented"); }
fn block_domain(&self, domain: String) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn authorize_follow_request(&self, id: &str) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn reject_follow_request(&self, id: &str) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn search(&self, q: String, resolve: bool) -> Result<SearchResult> { unimplemented!("This method was not implemented"); }
fn follows(&self, uri: Cow<'static, str>) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn media(&self, file: Cow<'static, str>) -> Result<Attachment> { unimplemented!("This method was not implemented"); }
fn clear_notifications(&self) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn get_account(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn follow(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn unfollow(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn block(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn unblock(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn mute(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn unmute(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn get_notification(&self, id: u64) -> Result<Notification> { unimplemented!("This method was not implemented"); }
fn get_status(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn get_context(&self, id: u64) -> Result<Context> { unimplemented!("This method was not implemented"); }
fn get_card(&self, id: u64) -> Result<Card> { unimplemented!("This method was not implemented"); }
fn reblog(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn unreblog(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn favourite(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn unfavourite(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn delete_status(&self, id: u64) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn update_credentials(&self, changes: CredientialsBuilder) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn new_status(&self, status: StatusBuilder) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn get_public_timeline(&self, local: bool) -> Result<Vec<Status>> { unimplemented!("This method was not implemented"); }
fn get_tagged_timeline(&self, hashtag: String, local: bool) -> Result<Vec<Status>> { unimplemented!("This method was not implemented"); }
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>> where S: Into<Option<StatusesRequest<'a>>> { unimplemented!("This method was not implemented"); }
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> { unimplemented!("This method was not implemented"); }
fn search_accounts(&self, query: &str, limit: Option<u64>, following: bool) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn favourites(&self) -> Result<Page<Status>> {
unimplemented!("This method was not implemented");
}
fn blocks(&self) -> Result<Page<Account>> {
unimplemented!("This method was not implemented");
}
fn domain_blocks(&self) -> Result<Page<String>> {
unimplemented!("This method was not implemented");
}
fn follow_requests(&self) -> Result<Page<Account>> {
unimplemented!("This method was not implemented");
}
fn get_home_timeline(&self) -> Result<Page<Status>> {
unimplemented!("This method was not implemented");
}
fn get_emojis(&self) -> Result<Page<Emoji>> {
unimplemented!("This method was not implemented");
}
fn mutes(&self) -> Result<Page<Account>> {
unimplemented!("This method was not implemented");
}
fn notifications(&self) -> Result<Page<Notification>> {
unimplemented!("This method was not implemented");
}
fn reports(&self) -> Result<Page<Report>> {
unimplemented!("This method was not implemented");
}
fn followers(&self, id: &str) -> Result<Page<Account>> {
unimplemented!("This method was not implemented");
}
fn following(&self) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn reblogged_by(&self) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn favourited_by(&self) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn unblock_domain(&self, domain: String) -> Result<Empty> {
unimplemented!("This method was not implemented");
}
fn instance(&self) -> Result<Instance> {
unimplemented!("This method was not implemented");
}
fn verify_credentials(&self) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn report(&self, account_id: &str, status_ids: Vec<&str>, comment: String) -> Result<Report> {
unimplemented!("This method was not implemented");
}
fn block_domain(&self, domain: String) -> Result<Empty> {
unimplemented!("This method was not implemented");
}
fn authorize_follow_request(&self, id: &str) -> Result<Empty> {
unimplemented!("This method was not implemented");
}
fn reject_follow_request(&self, id: &str) -> Result<Empty> {
unimplemented!("This method was not implemented");
}
fn search(&self, q: String, resolve: bool) -> Result<SearchResult> {
unimplemented!("This method was not implemented");
}
fn follows(&self, uri: Cow<'static, str>) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn media(&self, file: Cow<'static, str>) -> Result<Attachment> {
unimplemented!("This method was not implemented");
}
fn clear_notifications(&self) -> Result<Empty> {
unimplemented!("This method was not implemented");
}
fn get_account(&self, id: u64) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn follow(&self, id: u64) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn unfollow(&self, id: u64) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn block(&self, id: u64) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn unblock(&self, id: u64) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn mute(&self, id: u64) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn unmute(&self, id: u64) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn get_notification(&self, id: u64) -> Result<Notification> {
unimplemented!("This method was not implemented");
}
fn get_status(&self, id: u64) -> Result<Status> {
unimplemented!("This method was not implemented");
}
fn get_context(&self, id: u64) -> Result<Context> {
unimplemented!("This method was not implemented");
}
fn get_card(&self, id: u64) -> Result<Card> {
unimplemented!("This method was not implemented");
}
fn reblog(&self, id: u64) -> Result<Status> {
unimplemented!("This method was not implemented");
}
fn unreblog(&self, id: u64) -> Result<Status> {
unimplemented!("This method was not implemented");
}
fn favourite(&self, id: u64) -> Result<Status> {
unimplemented!("This method was not implemented");
}
fn unfavourite(&self, id: u64) -> Result<Status> {
unimplemented!("This method was not implemented");
}
fn delete_status(&self, id: u64) -> Result<Empty> {
unimplemented!("This method was not implemented");
}
fn update_credentials(&self, changes: CredientialsBuilder) -> Result<Account> {
unimplemented!("This method was not implemented");
}
fn new_status(&self, status: StatusBuilder) -> Result<Status> {
unimplemented!("This method was not implemented");
}
fn get_public_timeline(&self, local: bool) -> Result<Vec<Status>> {
unimplemented!("This method was not implemented");
}
fn get_tagged_timeline(&self, hashtag: String, local: bool) -> Result<Vec<Status>> {
unimplemented!("This method was not implemented");
}
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
where
S: Into<Option<StatusesRequest<'a>>>,
{
unimplemented!("This method was not implemented");
}
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> {
unimplemented!("This method was not implemented");
}
fn search_accounts(
&self,
query: &str,
limit: Option<u64>,
following: bool,
) -> Result<Page<Account>> {
unimplemented!("This method was not implemented");
}
}
impl Mastodon {
@ -167,12 +277,13 @@ impl From<Data> for Mastodon {
fn from(data: Data) -> Mastodon {
let mut builder = MastodonBuilder::new();
builder.data(data);
builder.build().expect("We know `data` is present, so this should be fine")
builder
.build()
.expect("We know `data` is present, so this should be fine")
}
}
impl MastodonClient for Mastodon {
paged_routes! {
(get) favourites: "favourites" => Status,
(get) blocks: "blocks" => Account,
@ -225,12 +336,11 @@ impl MastodonClient for Mastodon {
(delete) delete_status: "statuses/{}" => Empty,
}
fn update_credentials(&self, changes: CredientialsBuilder)
-> Result<Account>
{
fn update_credentials(&self, changes: CredientialsBuilder) -> Result<Account> {
let url = self.route("/api/v1/accounts/update_credentials");
let response = self.client.patch(&url)
let response = self
.client
.patch(&url)
.headers(self.headers.clone())
.multipart(changes.into_form()?)
.send()?;
@ -248,8 +358,9 @@ impl MastodonClient for Mastodon {
/// Post a new status to the account.
fn new_status(&self, status: StatusBuilder) -> Result<Status> {
let response = self.client.post(&self.route("/api/v1/statuses"))
let response = self
.client
.post(&self.route("/api/v1/statuses"))
.headers(self.headers.clone())
.json(&status)
.send()?;
@ -317,14 +428,14 @@ impl MastodonClient for Mastodon {
/// # token: "".into(),
/// # };
/// let client = Mastodon::from(data);
/// let request = StatusesRequest::default()
/// .only_media();
/// let request = StatusesRequest::default().only_media();
/// let statuses = client.statuses("user-id", request)?;
/// # Ok(())
/// # }
/// ```
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
where S: Into<Option<StatusesRequest<'a>>>
where
S: Into<Option<StatusesRequest<'a>>>,
{
let mut url = format!("{}/api/v1/accounts/{}/statuses", self.base, id);
@ -332,9 +443,7 @@ impl MastodonClient for Mastodon {
url = format!("{}{}", url, request.to_querystring());
}
let response = self.client.get(&url)
.headers(self.headers.clone())
.send()?;
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
Page::new(self, response)
}
@ -356,9 +465,7 @@ impl MastodonClient for Mastodon {
url.pop();
}
let response = self.client.get(&url)
.headers(self.headers.clone())
.send()?;
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
Page::new(self, response)
}
@ -366,21 +473,21 @@ impl MastodonClient for Mastodon {
/// Search for accounts by their name.
/// Will lookup an account remotely if the search term is in the
/// `username@domain` format and not yet in the database.
fn search_accounts(&self,
query: &str,
limit: Option<u64>,
following: bool)
-> Result<Page<Account>>
{
let url = format!("{}/api/v1/accounts/search?q={}&limit={}&following={}",
self.base,
query,
limit.unwrap_or(40),
following);
let response = self.client.get(&url)
.headers(self.headers.clone())
.send()?;
fn search_accounts(
&self,
query: &str,
limit: Option<u64>,
following: bool,
) -> Result<Page<Account>> {
let url = format!(
"{}/api/v1/accounts/search?q={}&limit={}&following={}",
self.base,
query,
limit.unwrap_or(40),
following
);
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
Page::new(self, response)
}
@ -421,12 +528,14 @@ impl MastodonBuilder {
pub fn build(self) -> Result<Mastodon> {
Ok(if let Some(data) = self.data {
let mut headers = Headers::new();
headers.set(Authorization(Bearer { token: (*data.token).to_owned() }));
headers.set(Authorization(Bearer {
token: (*data.token).to_owned(),
}));
Mastodon {
client: self.client.unwrap_or_else(|| Client::new()),
headers: headers,
data: data,
headers,
data,
}
} else {
return Err(Error::DataMissing);
@ -436,9 +545,7 @@ impl MastodonBuilder {
// Convert the HTTP response body from JSON. Pass up deserialization errors
// transparently.
fn deserialise<T: for<'de> serde::Deserialize<'de>>(mut response: Response)
-> Result<T>
{
fn deserialise<T: for<'de> serde::Deserialize<'de>>(mut response: Response) -> Result<T> {
use std::io::Read;
let mut vec = Vec::new();

@ -165,5 +165,3 @@ macro_rules! paged_routes_with_id {
route!{$($rest)*}
};
}

@ -1,9 +1,11 @@
use super::{Mastodon, Result, deserialise};
use reqwest::Response;
use reqwest::header::{Link, RelationType};
use super::{deserialise, Mastodon, Result};
use entities::itemsiter::ItemsIter;
use reqwest::{
header::{Link, RelationType},
Response,
};
use serde::Deserialize;
use url::Url;
use entities::itemsiter::ItemsIter;
pub struct Page<'a, T: for<'de> Deserialize<'de>> {
mastodon: &'a Mastodon,
@ -38,29 +40,32 @@ macro_rules! pages {
}
impl<'a, T: for<'de> Deserialize<'de>> Page<'a, T> {
pages! {
next: next_page,
prev: prev_page
}
pub fn new(mastodon: &'a Mastodon, response: Response) -> Result<Self> {
let (prev, next) = get_links(&response)?;
Ok(Page {
initial_items: deserialise(response)?,
next,
prev,
mastodon
mastodon,
})
}
pages! {
next: next_page,
prev: prev_page
}
}
impl<'a, T: Clone + for<'de> Deserialize<'de>> Page<'a, T> {
/// Returns an iterator that provides a stream of `T`s
///
/// This abstracts away the process of iterating over each item in a page, then making an http
/// call, then iterating over each item in the new page, etc. The iterator provides a stream of
/// `T`s, calling `self.next_page()` when necessary to get more of them, until there are no more
/// items.
/// This abstracts away the process of iterating over each item in a page,
/// then making an http call, then iterating over each item in the new
/// page, etc. The iterator provides a stream of `T`s, calling
/// `self.next_page()`
/// when necessary to get
/// more of them, until
/// there are no more items.
///
/// # Example
///
@ -86,7 +91,8 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> Page<'a, T> {
/// # }
/// ```
pub fn items_iter(self) -> impl Iterator<Item = T> + 'a
where T: 'a
where
T: 'a,
{
ItemsIter::new(self)
}

@ -1,8 +1,12 @@
use reqwest::Client;
use try_from::TryInto;
use {Data, Error, Mastodon, MastodonBuilder, Result};
use apps::{App, Scopes};
use Data;
use Error;
use Mastodon;
use MastodonBuilder;
use Result;
/// Handles registering your mastodon app to your instance. It is recommended
/// you cache your data struct to avoid registering on every run.
@ -47,8 +51,7 @@ impl Registration {
/// ```no_run
/// # extern crate elefren;
/// # fn main () -> elefren::Result<()> {
/// use elefren::prelude::*;
/// use elefren::apps::prelude::*;
/// use elefren::{apps::prelude::*, prelude::*};
///
/// let mut builder = App::builder();
/// builder.client_name("elefren_test");
@ -67,15 +70,12 @@ impl Registration {
/// # }
/// ```
pub fn register<I: TryInto<App>>(self, app: I) -> Result<Registered>
where Error: From<<I as TryInto<App>>::Err>
where
Error: From<<I as TryInto<App>>::Err>,
{
let app = app.try_into()?;
let url = format!("{}/api/v1/apps", self.base);
let oauth: OAuth = self.client
.post(&url)
.form(&app)
.send()?
.json()?;
let oauth: OAuth = self.client.post(&url).form(&app).send()?.json()?;
Ok(Registered {
base: self.base,
@ -94,10 +94,7 @@ impl Registered {
pub fn authorize_url(&self) -> Result<String> {
let url = format!(
"{}/oauth/authorize?client_id={}&redirect_uri={}&scope={}&response_type=code",
self.base,
self.client_id,
self.redirect,
self.scopes,
self.base, self.client_id, self.redirect, self.scopes,
);
Ok(url)

@ -5,10 +5,7 @@ use std::borrow::Cow;
/// ```
/// # extern crate elefren;
/// # use elefren::StatusesRequest;
/// let request = StatusesRequest::new()
/// .only_media()
/// .pinned()
/// .since_id("foo");
/// let request = StatusesRequest::new().only_media().pinned().since_id("foo");
/// # assert_eq!(&request.to_querystring()[..], "?only_media=1&pinned=1&since_id=foo");
/// ```
#[derive(Clone, Debug, Default)]
@ -90,5 +87,3 @@ impl<'a> StatusesRequest<'a> {
}
}
}

@ -4,19 +4,19 @@ pub struct StatusBuilder {
/// The text of the status.
pub status: String,
/// Ids of accounts being replied to.
#[serde(skip_serializing_if="Option::is_none")]
#[serde(skip_serializing_if = "Option::is_none")]
pub in_reply_to_id: Option<u64>,
/// Ids of media attachments being attached to the status.
#[serde(skip_serializing_if="Option::is_none")]
#[serde(skip_serializing_if = "Option::is_none")]
pub media_ids: Option<Vec<u64>>,
/// Whether current status is sensitive.
#[serde(skip_serializing_if="Option::is_none")]
#[serde(skip_serializing_if = "Option::is_none")]
pub sensitive: Option<bool>,
/// Text to precede the normal status text.
#[serde(skip_serializing_if="Option::is_none")]
#[serde(skip_serializing_if = "Option::is_none")]
pub spoiler_text: Option<String>,
/// Visibility of the status, defaults to `Public`.
#[serde(skip_serializing_if="Option::is_none")]
#[serde(skip_serializing_if = "Option::is_none")]
pub visibility: Option<Visibility>,
}
@ -38,7 +38,6 @@ pub enum Visibility {
}
impl StatusBuilder {
/// Create a new status with text.
/// ```
/// use elefren::prelude::*;
@ -47,7 +46,7 @@ impl StatusBuilder {
/// ```
pub fn new(status: String) -> Self {
StatusBuilder {
status: status,
status,
..Self::default()
}
}

Loading…
Cancel
Save