rustfmt pass
This commit is contained in:
+29
-29
@@ -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",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-14
@@ -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> {
|
||||
|
||||
+19
-16
@@ -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.
|
||||
|
||||
+8
-12
@@ -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(),
|
||||
|
||||
+215
-108
@@ -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);
|
||||
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()?;
|
||||
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)*}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
+21
-15
@@ -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)
|
||||
}
|
||||
|
||||
+10
-13
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user