rustfmt pass
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
## [Documentation](https://docs.rs/elefren/)
|
## [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
|
```rust
|
||||||
extern crate elefren;
|
extern crate elefren;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ mod register;
|
|||||||
use register::MastodonClient;
|
use register::MastodonClient;
|
||||||
use std::error;
|
use std::error;
|
||||||
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<error::Error>> {
|
fn main() -> Result<(), Box<error::Error>> {
|
||||||
let mastodon = register::get_mastodon_data()?;
|
let mastodon = register::get_mastodon_data()?;
|
||||||
let you = mastodon.verify_credentials()?;
|
let you = mastodon.verify_credentials()?;
|
||||||
|
|||||||
+5
-14
@@ -3,19 +3,12 @@ extern crate toml;
|
|||||||
|
|
||||||
pub use self::elefren::{Data, MastodonClient};
|
pub use self::elefren::{Data, MastodonClient};
|
||||||
|
|
||||||
use std::{
|
use std::{error::Error, fs, io};
|
||||||
error::Error,
|
|
||||||
fs,
|
|
||||||
io,
|
|
||||||
};
|
|
||||||
|
|
||||||
use self::elefren::{
|
use self::elefren::{
|
||||||
apps::{
|
apps::{App, Scopes},
|
||||||
App,
|
|
||||||
Scopes
|
|
||||||
},
|
|
||||||
Mastodon,
|
Mastodon,
|
||||||
Registration
|
Registration,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -24,7 +17,6 @@ fn main() -> Result<(), Box<Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn get_mastodon_data() -> Result<Mastodon, Box<Error>> {
|
pub fn get_mastodon_data() -> Result<Mastodon, Box<Error>> {
|
||||||
if let Ok(config) = fs::read_to_string("mastodon-data.toml") {
|
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>> {
|
pub fn register() -> Result<Mastodon, Box<Error>> {
|
||||||
let mut app = App::builder();
|
let mut app = App::builder();
|
||||||
app.client_name("elefren-examples")
|
app.client_name("elefren-examples")
|
||||||
.scopes(Scopes::All)
|
.scopes(Scopes::All)
|
||||||
.website("https://github.com/pwoolcoc/elefren");
|
.website("https://github.com/pwoolcoc/elefren");
|
||||||
|
|
||||||
let website = read_line("Please enter your mastodon instance url:")?;
|
let website = read_line("Please enter your mastodon instance url:")?;
|
||||||
let registration = Registration::new(website.trim());
|
let registration = Registration::new(website.trim());
|
||||||
@@ -67,4 +59,3 @@ pub fn read_line(message: &str) -> Result<String, Box<Error>> {
|
|||||||
|
|
||||||
Ok(input)
|
Ok(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
indent_style = "Visual"
|
|
||||||
format_strings = true
|
format_strings = true
|
||||||
format_macro_matchers = true
|
format_macro_matchers = true
|
||||||
imports_layout = "HorizontalVertical"
|
imports_layout = "HorizontalVertical"
|
||||||
|
|||||||
+29
-29
@@ -1,5 +1,4 @@
|
|||||||
use std::fmt;
|
use std::{borrow::Cow, fmt};
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use try_from::TryInto;
|
use try_from::TryInto;
|
||||||
|
|
||||||
@@ -8,13 +7,8 @@ use errors::{Error, Result};
|
|||||||
/// Provides the necessary types for registering an App and getting the
|
/// Provides the necessary types for registering an App and getting the
|
||||||
/// necessary auth information
|
/// necessary auth information
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use {
|
pub use apps::{App, Scopes};
|
||||||
apps::{
|
pub use registration::Registration;
|
||||||
App,
|
|
||||||
Scopes
|
|
||||||
},
|
|
||||||
registration::Registration
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents an application that can be registered with a mastodon instance
|
/// Represents an application that can be registered with a mastodon instance
|
||||||
@@ -23,7 +17,7 @@ pub struct App {
|
|||||||
client_name: String,
|
client_name: String,
|
||||||
redirect_uris: String,
|
redirect_uris: String,
|
||||||
scopes: Scopes,
|
scopes: Scopes,
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
website: Option<String>,
|
website: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,8 +33,8 @@ impl App {
|
|||||||
|
|
||||||
/// Builder struct for defining your application.
|
/// Builder struct for defining your application.
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::error::Error;
|
|
||||||
/// use elefren::apps::prelude::*;
|
/// use elefren::apps::prelude::*;
|
||||||
|
/// use std::error::Error;
|
||||||
///
|
///
|
||||||
/// # fn main() -> Result<(), Box<Error>> {
|
/// # fn main() -> Result<(), Box<Error>> {
|
||||||
/// let mut builder = App::builder();
|
/// let mut builder = App::builder();
|
||||||
@@ -98,14 +92,15 @@ impl<'a> AppBuilder<'a> {
|
|||||||
/// Will fail if no `client_name` was provided
|
/// Will fail if no `client_name` was provided
|
||||||
pub fn build(self) -> Result<App> {
|
pub fn build(self) -> Result<App> {
|
||||||
Ok(App {
|
Ok(App {
|
||||||
client_name: self.client_name
|
client_name: self
|
||||||
.ok_or_else(|| Error::MissingField("client_name"))?
|
.client_name
|
||||||
.into(),
|
.ok_or_else(|| Error::MissingField("client_name"))?
|
||||||
redirect_uris: self.redirect_uris
|
.into(),
|
||||||
.unwrap_or_else(|| "urn:ietf:wg:oauth:2.0:oob".into())
|
redirect_uris: self
|
||||||
.into(),
|
.redirect_uris
|
||||||
scopes: self.scopes
|
.unwrap_or_else(|| "urn:ietf:wg:oauth:2.0:oob".into())
|
||||||
.unwrap_or_else(|| Scopes::Read),
|
.into(),
|
||||||
|
scopes: self.scopes.unwrap_or_else(|| Scopes::Read),
|
||||||
website: self.website.map(|s| s.into()),
|
website: self.website.map(|s| s.into()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -128,7 +123,8 @@ impl<'a> TryInto<App> for AppBuilder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Permission scope of the application.
|
/// 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)]
|
#[derive(Debug, Clone, Copy, Serialize)]
|
||||||
pub enum Scopes {
|
pub enum Scopes {
|
||||||
/// All Permissions, equivalent to `read write follow`
|
/// All Permissions, equivalent to `read write follow`
|
||||||
@@ -157,15 +153,19 @@ pub enum Scopes {
|
|||||||
impl fmt::Display for Scopes {
|
impl fmt::Display for Scopes {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use self::Scopes::*;
|
use self::Scopes::*;
|
||||||
write!(f, "{}", match *self {
|
write!(
|
||||||
All => "read%20write%20follow",
|
f,
|
||||||
Follow => "follow",
|
"{}",
|
||||||
Read => "read",
|
match *self {
|
||||||
ReadFollow => "read%20follow",
|
All => "read%20write%20follow",
|
||||||
ReadWrite => "read%20write",
|
Follow => "follow",
|
||||||
Write => "write",
|
Read => "read",
|
||||||
WriteFollow => "write%20follow"
|
ReadFollow => "read%20follow",
|
||||||
})
|
ReadWrite => "read%20write",
|
||||||
|
Write => "write",
|
||||||
|
WriteFollow => "write%20follow",
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-14
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use reqwest::multipart::Form;
|
use reqwest::multipart::Form;
|
||||||
use ::Result;
|
|
||||||
use std::path::Path;
|
|
||||||
use serde::de::{self, Deserialize, Deserializer, Unexpected};
|
use serde::de::{self, Deserialize, Deserializer, Unexpected};
|
||||||
|
use std::path::Path;
|
||||||
|
use Result;
|
||||||
|
|
||||||
/// A struct representing an Account.
|
/// A struct representing an Account.
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
@@ -57,9 +57,7 @@ pub struct Source {
|
|||||||
note: String,
|
note: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string_or_bool<'de, D: Deserializer<'de>>(val: D)
|
fn string_or_bool<'de, D: Deserializer<'de>>(val: D) -> ::std::result::Result<bool, D::Error> {
|
||||||
-> ::std::result::Result<bool, D::Error>
|
|
||||||
{
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum BoolOrString {
|
pub enum BoolOrString {
|
||||||
@@ -68,16 +66,19 @@ fn string_or_bool<'de, D: Deserializer<'de>>(val: D)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(match BoolOrString::deserialize(val)? {
|
Ok(match BoolOrString::deserialize(val)? {
|
||||||
BoolOrString::Bool(b) => b,
|
BoolOrString::Bool(b) => b,
|
||||||
BoolOrString::Str(ref s) => {
|
BoolOrString::Str(ref s) => {
|
||||||
if s == "true" {
|
if s == "true" {
|
||||||
true
|
true
|
||||||
} else if s == "false" {
|
} else if s == "false" {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
return Err(de::Error::invalid_value(Unexpected::Str(s), &"true or false"));
|
return Err(de::Error::invalid_value(
|
||||||
}
|
Unexpected::Str(s),
|
||||||
|
&"true or false",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ pub struct Attachment {
|
|||||||
/// ID of the attachment.
|
/// ID of the attachment.
|
||||||
pub id: String,
|
pub id: String,
|
||||||
/// The media type of an attachment.
|
/// The media type of an attachment.
|
||||||
#[serde(rename="type")]
|
#[serde(rename = "type")]
|
||||||
pub media_type: MediaType,
|
pub media_type: MediaType,
|
||||||
/// URL of the locally hosted version of the image.
|
/// URL of the locally hosted version of the image.
|
||||||
pub url: String,
|
pub url: String,
|
||||||
@@ -43,7 +43,6 @@ pub struct ImageDetails {
|
|||||||
size: String,
|
size: String,
|
||||||
/// The aspect ratio of the attachment.
|
/// The aspect ratio of the attachment.
|
||||||
aspect: f64,
|
aspect: f64,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type of media attachment.
|
/// The type of media attachment.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use serde::Deserialize;
|
|||||||
/// let client = Mastodon::from(data);
|
/// let client = Mastodon::from(data);
|
||||||
/// let statuses = client.statuses("user-id", None)?;
|
/// let statuses = client.statuses("user-id", None)?;
|
||||||
/// for status in statuses.items_iter() {
|
/// for status in statuses.items_iter() {
|
||||||
/// // do something with `status`
|
/// // do something with `status`
|
||||||
/// }
|
/// }
|
||||||
/// # Ok(())
|
/// # 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> {
|
impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
|
||||||
pub(crate) fn new(page: Page<'a, T>) -> ItemsIter<'a, T> {
|
pub(crate) fn new(page: Page<'a, T>) -> ItemsIter<'a, T> {
|
||||||
ItemsIter {
|
ItemsIter {
|
||||||
page: page,
|
page,
|
||||||
buffer: vec![],
|
buffer: vec![],
|
||||||
cur_idx: 0,
|
cur_idx: 0,
|
||||||
use_initial: true,
|
use_initial: true,
|
||||||
@@ -41,8 +41,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn need_next_page(&self) -> bool {
|
fn need_next_page(&self) -> bool {
|
||||||
self.buffer.is_empty() ||
|
self.buffer.is_empty() || self.cur_idx == self.buffer.len()
|
||||||
self.cur_idx == self.buffer.len()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_next_page(&mut self) -> Option<()> {
|
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;
|
type Item = T;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
|||||||
+19
-16
@@ -3,10 +3,10 @@ pub mod attachment;
|
|||||||
pub mod card;
|
pub mod card;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod instance;
|
pub mod instance;
|
||||||
|
pub(crate) mod itemsiter;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
pub mod mention;
|
pub mod mention;
|
||||||
pub mod notification;
|
pub mod notification;
|
||||||
pub(crate) mod itemsiter;
|
|
||||||
pub mod relationship;
|
pub mod relationship;
|
||||||
pub mod report;
|
pub mod report;
|
||||||
pub mod search_result;
|
pub mod search_result;
|
||||||
@@ -17,19 +17,22 @@ pub mod status;
|
|||||||
pub struct Empty {}
|
pub struct Empty {}
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
//! The purpose of this module is to alleviate imports of many common structs
|
//! The purpose of this module is to alleviate imports of many common
|
||||||
//! by adding a glob import to the top of mastodon heavy modules:
|
//! structs by adding a glob import to the top of mastodon heavy
|
||||||
pub use super::Empty;
|
//! modules:
|
||||||
pub use super::account::{Account, CredientialsBuilder, Source};
|
pub use super::{
|
||||||
pub use super::attachment::{Attachment, MediaType};
|
account::{Account, CredientialsBuilder, Source},
|
||||||
pub use super::card::Card;
|
attachment::{Attachment, MediaType},
|
||||||
pub use super::context::Context;
|
card::Card,
|
||||||
pub use super::instance::*;
|
context::Context,
|
||||||
pub use super::list::List;
|
instance::*,
|
||||||
pub use super::mention::Mention;
|
list::List,
|
||||||
pub use super::notification::Notification;
|
mention::Mention,
|
||||||
pub use super::relationship::Relationship;
|
notification::Notification,
|
||||||
pub use super::report::Report;
|
relationship::Relationship,
|
||||||
pub use super::search_result::SearchResult;
|
report::Report,
|
||||||
pub use super::status::{Application, Emoji, Status};
|
search_result::SearchResult,
|
||||||
|
status::{Application, Emoji, Status},
|
||||||
|
Empty,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
//! Module containing all info about notifications.
|
//! Module containing all info about notifications.
|
||||||
|
|
||||||
|
use super::{account::Account, status::Status};
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use super::account::Account;
|
|
||||||
use super::status::Status;
|
|
||||||
|
|
||||||
/// A struct containing info about a notification.
|
/// A struct containing info about a notification.
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//! Module containing all info relating to a status.
|
//! Module containing all info relating to a status.
|
||||||
|
|
||||||
use chrono::prelude::*;
|
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
|
use chrono::prelude::*;
|
||||||
use status_builder::Visibility;
|
use status_builder::Visibility;
|
||||||
|
|
||||||
/// A status from the instance.
|
/// A status from the instance.
|
||||||
|
|||||||
+8
-12
@@ -1,12 +1,7 @@
|
|||||||
use std::{
|
use std::{error, fmt, io::Error as IoError};
|
||||||
fmt,
|
|
||||||
error,
|
|
||||||
io::Error as IoError
|
|
||||||
};
|
|
||||||
|
|
||||||
use json::Error as SerdeError;
|
use json::Error as SerdeError;
|
||||||
use reqwest::Error as HttpError;
|
use reqwest::{Error as HttpError, StatusCode};
|
||||||
use reqwest::StatusCode;
|
|
||||||
use url::ParseError as UrlError;
|
use url::ParseError as UrlError;
|
||||||
|
|
||||||
/// Convience type over `std::result::Result` with `Error` as the error type.
|
/// 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 {
|
impl error::Error for Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
Error::Api(ref e) => {
|
Error::Api(ref e) => e
|
||||||
e.error_description.as_ref().map(|i| &**i)
|
.error_description
|
||||||
.or(e.error.as_ref().map(|i| &**i))
|
.as_ref()
|
||||||
.unwrap_or("Unknown API Error")
|
.map(|i| &**i)
|
||||||
},
|
.or(e.error.as_ref().map(|i| &**i))
|
||||||
|
.unwrap_or("Unknown API Error"),
|
||||||
Error::Serde(ref e) => e.description(),
|
Error::Serde(ref e) => e.description(),
|
||||||
Error::Http(ref e) => e.description(),
|
Error::Http(ref e) => e.description(),
|
||||||
Error::Io(ref e) => e.description(),
|
Error::Io(ref e) => e.description(),
|
||||||
|
|||||||
+215
-108
@@ -9,14 +9,12 @@
|
|||||||
//! # try().unwrap();
|
//! # try().unwrap();
|
||||||
//! # }
|
//! # }
|
||||||
//! # fn try() -> elefren::Result<()> {
|
//! # fn try() -> elefren::Result<()> {
|
||||||
//! use elefren::prelude::*;
|
//! use elefren::{apps::prelude::*, prelude::*};
|
||||||
//! use elefren::apps::prelude::*;
|
|
||||||
//!
|
//!
|
||||||
//! let mut app = App::builder();
|
//! let mut app = App::builder();
|
||||||
//! app.client_name("elefren_test");
|
//! app.client_name("elefren_test");
|
||||||
//!
|
//!
|
||||||
//! let registration = Registration::new("https://mastodon.social")
|
//! let registration = Registration::new("https://mastodon.social").register(app)?;
|
||||||
//! .register(app)?;
|
|
||||||
//! let url = registration.authorize_url()?;
|
//! let url = registration.authorize_url()?;
|
||||||
//! // Here you now need to open the url in the browser
|
//! // Here you now need to open the url in the browser
|
||||||
//! // And handle a the redirect url coming back with the code.
|
//! // And handle a the redirect url coming back with the code.
|
||||||
@@ -31,47 +29,57 @@
|
|||||||
#![cfg_attr(test, deny(warnings))]
|
#![cfg_attr(test, deny(warnings))]
|
||||||
#![cfg_attr(test, deny(missing_docs))]
|
#![cfg_attr(test, deny(missing_docs))]
|
||||||
|
|
||||||
#[macro_use] extern crate serde_derive;
|
#[macro_use]
|
||||||
#[macro_use] extern crate doc_comment;
|
extern crate serde_derive;
|
||||||
#[macro_use] extern crate serde_json as json;
|
#[macro_use]
|
||||||
|
extern crate doc_comment;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_json as json;
|
||||||
extern crate chrono;
|
extern crate chrono;
|
||||||
extern crate reqwest;
|
extern crate reqwest;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate try_from;
|
extern crate try_from;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::{borrow::Cow, ops};
|
||||||
use std::ops;
|
|
||||||
|
|
||||||
use reqwest::{Client, Response};
|
use reqwest::{
|
||||||
use reqwest::header::{Authorization, Bearer, Headers};
|
header::{Authorization, Bearer, Headers},
|
||||||
|
Client,
|
||||||
|
Response,
|
||||||
|
};
|
||||||
|
|
||||||
use entities::prelude::*;
|
use entities::prelude::*;
|
||||||
use page::Page;
|
use page::Page;
|
||||||
|
|
||||||
pub use status_builder::StatusBuilder;
|
pub use errors::{ApiError, Error, Result};
|
||||||
pub use requests::statuses::StatusesRequest;
|
|
||||||
pub use errors::{Result, Error, ApiError};
|
|
||||||
pub use registration::Registration;
|
pub use registration::Registration;
|
||||||
|
pub use requests::statuses::StatusesRequest;
|
||||||
|
pub use status_builder::StatusBuilder;
|
||||||
|
|
||||||
/// Registering your App
|
/// Registering your App
|
||||||
pub mod apps;
|
pub mod apps;
|
||||||
/// Constructing a status
|
|
||||||
pub mod status_builder;
|
|
||||||
/// Entities returned from the API
|
/// Entities returned from the API
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
/// Registering your app.
|
|
||||||
pub mod registration;
|
|
||||||
/// Handling multiple pages of entities.
|
|
||||||
pub mod page;
|
|
||||||
/// Errors
|
/// Errors
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
/// Handling multiple pages of entities.
|
||||||
|
pub mod page;
|
||||||
|
/// Registering your app.
|
||||||
|
pub mod registration;
|
||||||
/// Requests
|
/// Requests
|
||||||
pub mod 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
|
/// Automatically import the things you need
|
||||||
pub mod prelude {
|
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.
|
/// Your mastodon application client, handles all requests to and from Mastodon.
|
||||||
@@ -80,7 +88,7 @@ pub struct Mastodon {
|
|||||||
client: Client,
|
client: Client,
|
||||||
headers: Headers,
|
headers: Headers,
|
||||||
/// Raw data about your mastodon instance.
|
/// Raw data about your mastodon instance.
|
||||||
pub data: Data
|
pub data: Data,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raw data about mastodon app. Save `Data` using `serde` to prevent needing
|
/// 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
|
/// implementations might be swapped out for testing
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub trait MastodonClient {
|
pub trait MastodonClient {
|
||||||
fn favourites(&self) -> Result<Page<Status>> { unimplemented!("This method was not implemented"); }
|
fn favourites(&self) -> Result<Page<Status>> {
|
||||||
fn blocks(&self) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
|
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 blocks(&self) -> Result<Page<Account>> {
|
||||||
fn get_home_timeline(&self) -> Result<Page<Status>> { unimplemented!("This method was not implemented"); }
|
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 domain_blocks(&self) -> Result<Page<String>> {
|
||||||
fn notifications(&self) -> Result<Page<Notification>> { unimplemented!("This method was not implemented"); }
|
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 follow_requests(&self) -> Result<Page<Account>> {
|
||||||
fn following(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
|
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 get_home_timeline(&self) -> Result<Page<Status>> {
|
||||||
fn unblock_domain(&self, domain: String) -> Result<Empty> { unimplemented!("This method was not implemented"); }
|
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 get_emojis(&self) -> Result<Page<Emoji>> {
|
||||||
fn report(&self, account_id: &str, status_ids: Vec<&str>, comment: String) -> Result<Report> { unimplemented!("This method was not implemented"); }
|
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 mutes(&self) -> Result<Page<Account>> {
|
||||||
fn reject_follow_request(&self, id: &str) -> Result<Empty> { unimplemented!("This method was not implemented"); }
|
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 notifications(&self) -> Result<Page<Notification>> {
|
||||||
fn media(&self, file: Cow<'static, str>) -> Result<Attachment> { unimplemented!("This method was not implemented"); }
|
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 reports(&self) -> Result<Page<Report>> {
|
||||||
fn follow(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
|
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 followers(&self, id: &str) -> Result<Page<Account>> {
|
||||||
fn unblock(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
|
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 following(&self) -> Result<Account> {
|
||||||
fn get_notification(&self, id: u64) -> Result<Notification> { unimplemented!("This method was not implemented"); }
|
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 reblogged_by(&self) -> Result<Account> {
|
||||||
fn get_card(&self, id: u64) -> Result<Card> { unimplemented!("This method was not implemented"); }
|
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 favourited_by(&self) -> Result<Account> {
|
||||||
fn favourite(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
|
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 unblock_domain(&self, domain: String) -> Result<Empty> {
|
||||||
fn update_credentials(&self, changes: CredientialsBuilder) -> Result<Account> { unimplemented!("This method was not implemented"); }
|
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 instance(&self) -> Result<Instance> {
|
||||||
fn get_tagged_timeline(&self, hashtag: String, local: bool) -> Result<Vec<Status>> { unimplemented!("This method was not implemented"); }
|
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 verify_credentials(&self) -> Result<Account> {
|
||||||
fn search_accounts(&self, query: &str, limit: Option<u64>, following: bool) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
|
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 {
|
impl Mastodon {
|
||||||
@@ -167,12 +277,13 @@ impl From<Data> for Mastodon {
|
|||||||
fn from(data: Data) -> Mastodon {
|
fn from(data: Data) -> Mastodon {
|
||||||
let mut builder = MastodonBuilder::new();
|
let mut builder = MastodonBuilder::new();
|
||||||
builder.data(data);
|
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 {
|
impl MastodonClient for Mastodon {
|
||||||
|
|
||||||
paged_routes! {
|
paged_routes! {
|
||||||
(get) favourites: "favourites" => Status,
|
(get) favourites: "favourites" => Status,
|
||||||
(get) blocks: "blocks" => Account,
|
(get) blocks: "blocks" => Account,
|
||||||
@@ -225,12 +336,11 @@ impl MastodonClient for Mastodon {
|
|||||||
(delete) delete_status: "statuses/{}" => Empty,
|
(delete) delete_status: "statuses/{}" => Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_credentials(&self, changes: CredientialsBuilder)
|
fn update_credentials(&self, changes: CredientialsBuilder) -> Result<Account> {
|
||||||
-> Result<Account>
|
|
||||||
{
|
|
||||||
|
|
||||||
let url = self.route("/api/v1/accounts/update_credentials");
|
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())
|
.headers(self.headers.clone())
|
||||||
.multipart(changes.into_form()?)
|
.multipart(changes.into_form()?)
|
||||||
.send()?;
|
.send()?;
|
||||||
@@ -248,8 +358,9 @@ impl MastodonClient for Mastodon {
|
|||||||
|
|
||||||
/// Post a new status to the account.
|
/// Post a new status to the account.
|
||||||
fn new_status(&self, status: StatusBuilder) -> Result<Status> {
|
fn new_status(&self, status: StatusBuilder) -> Result<Status> {
|
||||||
|
let response = self
|
||||||
let response = self.client.post(&self.route("/api/v1/statuses"))
|
.client
|
||||||
|
.post(&self.route("/api/v1/statuses"))
|
||||||
.headers(self.headers.clone())
|
.headers(self.headers.clone())
|
||||||
.json(&status)
|
.json(&status)
|
||||||
.send()?;
|
.send()?;
|
||||||
@@ -317,14 +428,14 @@ impl MastodonClient for Mastodon {
|
|||||||
/// # token: "".into(),
|
/// # token: "".into(),
|
||||||
/// # };
|
/// # };
|
||||||
/// let client = Mastodon::from(data);
|
/// let client = Mastodon::from(data);
|
||||||
/// let request = StatusesRequest::default()
|
/// let request = StatusesRequest::default().only_media();
|
||||||
/// .only_media();
|
|
||||||
/// let statuses = client.statuses("user-id", request)?;
|
/// let statuses = client.statuses("user-id", request)?;
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
|
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);
|
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());
|
url = format!("{}{}", url, request.to_querystring());
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = self.client.get(&url)
|
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
|
||||||
.headers(self.headers.clone())
|
|
||||||
.send()?;
|
|
||||||
|
|
||||||
Page::new(self, response)
|
Page::new(self, response)
|
||||||
}
|
}
|
||||||
@@ -356,9 +465,7 @@ impl MastodonClient for Mastodon {
|
|||||||
url.pop();
|
url.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = self.client.get(&url)
|
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
|
||||||
.headers(self.headers.clone())
|
|
||||||
.send()?;
|
|
||||||
|
|
||||||
Page::new(self, response)
|
Page::new(self, response)
|
||||||
}
|
}
|
||||||
@@ -366,21 +473,21 @@ impl MastodonClient for Mastodon {
|
|||||||
/// Search for accounts by their name.
|
/// Search for accounts by their name.
|
||||||
/// Will lookup an account remotely if the search term is in the
|
/// Will lookup an account remotely if the search term is in the
|
||||||
/// `username@domain` format and not yet in the database.
|
/// `username@domain` format and not yet in the database.
|
||||||
fn search_accounts(&self,
|
fn search_accounts(
|
||||||
query: &str,
|
&self,
|
||||||
limit: Option<u64>,
|
query: &str,
|
||||||
following: bool)
|
limit: Option<u64>,
|
||||||
-> Result<Page<Account>>
|
following: bool,
|
||||||
{
|
) -> Result<Page<Account>> {
|
||||||
let url = format!("{}/api/v1/accounts/search?q={}&limit={}&following={}",
|
let url = format!(
|
||||||
self.base,
|
"{}/api/v1/accounts/search?q={}&limit={}&following={}",
|
||||||
query,
|
self.base,
|
||||||
limit.unwrap_or(40),
|
query,
|
||||||
following);
|
limit.unwrap_or(40),
|
||||||
|
following
|
||||||
|
);
|
||||||
|
|
||||||
let response = self.client.get(&url)
|
let response = self.client.get(&url).headers(self.headers.clone()).send()?;
|
||||||
.headers(self.headers.clone())
|
|
||||||
.send()?;
|
|
||||||
|
|
||||||
Page::new(self, response)
|
Page::new(self, response)
|
||||||
}
|
}
|
||||||
@@ -421,12 +528,14 @@ impl MastodonBuilder {
|
|||||||
pub fn build(self) -> Result<Mastodon> {
|
pub fn build(self) -> Result<Mastodon> {
|
||||||
Ok(if let Some(data) = self.data {
|
Ok(if let Some(data) = self.data {
|
||||||
let mut headers = Headers::new();
|
let mut headers = Headers::new();
|
||||||
headers.set(Authorization(Bearer { token: (*data.token).to_owned() }));
|
headers.set(Authorization(Bearer {
|
||||||
|
token: (*data.token).to_owned(),
|
||||||
|
}));
|
||||||
|
|
||||||
Mastodon {
|
Mastodon {
|
||||||
client: self.client.unwrap_or_else(|| Client::new()),
|
client: self.client.unwrap_or_else(|| Client::new()),
|
||||||
headers: headers,
|
headers,
|
||||||
data: data,
|
data,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::DataMissing);
|
return Err(Error::DataMissing);
|
||||||
@@ -436,9 +545,7 @@ impl MastodonBuilder {
|
|||||||
|
|
||||||
// Convert the HTTP response body from JSON. Pass up deserialization errors
|
// Convert the HTTP response body from JSON. Pass up deserialization errors
|
||||||
// transparently.
|
// transparently.
|
||||||
fn deserialise<T: for<'de> serde::Deserialize<'de>>(mut response: Response)
|
fn deserialise<T: for<'de> serde::Deserialize<'de>>(mut response: Response) -> Result<T> {
|
||||||
-> Result<T>
|
|
||||||
{
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
let mut vec = Vec::new();
|
let mut vec = Vec::new();
|
||||||
|
|||||||
@@ -165,5 +165,3 @@ macro_rules! paged_routes_with_id {
|
|||||||
route!{$($rest)*}
|
route!{$($rest)*}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+21
-15
@@ -1,9 +1,11 @@
|
|||||||
use super::{Mastodon, Result, deserialise};
|
use super::{deserialise, Mastodon, Result};
|
||||||
use reqwest::Response;
|
use entities::itemsiter::ItemsIter;
|
||||||
use reqwest::header::{Link, RelationType};
|
use reqwest::{
|
||||||
|
header::{Link, RelationType},
|
||||||
|
Response,
|
||||||
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use entities::itemsiter::ItemsIter;
|
|
||||||
|
|
||||||
pub struct Page<'a, T: for<'de> Deserialize<'de>> {
|
pub struct Page<'a, T: for<'de> Deserialize<'de>> {
|
||||||
mastodon: &'a Mastodon,
|
mastodon: &'a Mastodon,
|
||||||
@@ -38,29 +40,32 @@ macro_rules! pages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: for<'de> Deserialize<'de>> Page<'a, T> {
|
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> {
|
pub fn new(mastodon: &'a Mastodon, response: Response) -> Result<Self> {
|
||||||
let (prev, next) = get_links(&response)?;
|
let (prev, next) = get_links(&response)?;
|
||||||
Ok(Page {
|
Ok(Page {
|
||||||
initial_items: deserialise(response)?,
|
initial_items: deserialise(response)?,
|
||||||
next,
|
next,
|
||||||
prev,
|
prev,
|
||||||
mastodon
|
mastodon,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pages! {
|
|
||||||
next: next_page,
|
|
||||||
prev: prev_page
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Clone + for<'de> Deserialize<'de>> Page<'a, T> {
|
impl<'a, T: Clone + for<'de> Deserialize<'de>> Page<'a, T> {
|
||||||
/// Returns an iterator that provides a stream of `T`s
|
/// 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
|
/// This abstracts away the process of iterating over each item in a page,
|
||||||
/// call, then iterating over each item in the new page, etc. The iterator provides a stream of
|
/// then making an http call, then iterating over each item in the new
|
||||||
/// `T`s, calling `self.next_page()` when necessary to get more of them, until there are no more
|
/// page, etc. The iterator provides a stream of `T`s, calling
|
||||||
/// items.
|
/// `self.next_page()`
|
||||||
|
/// when necessary to get
|
||||||
|
/// more of them, until
|
||||||
|
/// there are no more items.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # 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
|
pub fn items_iter(self) -> impl Iterator<Item = T> + 'a
|
||||||
where T: 'a
|
where
|
||||||
|
T: 'a,
|
||||||
{
|
{
|
||||||
ItemsIter::new(self)
|
ItemsIter::new(self)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-13
@@ -1,8 +1,12 @@
|
|||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use try_from::TryInto;
|
use try_from::TryInto;
|
||||||
|
|
||||||
use {Data, Error, Mastodon, MastodonBuilder, Result};
|
|
||||||
use apps::{App, Scopes};
|
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
|
/// 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.
|
||||||
@@ -47,8 +51,7 @@ impl Registration {
|
|||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # extern crate elefren;
|
/// # extern crate elefren;
|
||||||
/// # fn main () -> elefren::Result<()> {
|
/// # fn main () -> elefren::Result<()> {
|
||||||
/// use elefren::prelude::*;
|
/// use elefren::{apps::prelude::*, prelude::*};
|
||||||
/// use elefren::apps::prelude::*;
|
|
||||||
///
|
///
|
||||||
/// let mut builder = App::builder();
|
/// let mut builder = App::builder();
|
||||||
/// builder.client_name("elefren_test");
|
/// builder.client_name("elefren_test");
|
||||||
@@ -67,15 +70,12 @@ impl Registration {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn register<I: TryInto<App>>(self, app: I) -> Result<Registered>
|
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 app = app.try_into()?;
|
||||||
let url = format!("{}/api/v1/apps", self.base);
|
let url = format!("{}/api/v1/apps", self.base);
|
||||||
let oauth: OAuth = self.client
|
let oauth: OAuth = self.client.post(&url).form(&app).send()?.json()?;
|
||||||
.post(&url)
|
|
||||||
.form(&app)
|
|
||||||
.send()?
|
|
||||||
.json()?;
|
|
||||||
|
|
||||||
Ok(Registered {
|
Ok(Registered {
|
||||||
base: self.base,
|
base: self.base,
|
||||||
@@ -94,10 +94,7 @@ impl Registered {
|
|||||||
pub fn authorize_url(&self) -> Result<String> {
|
pub fn authorize_url(&self) -> Result<String> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/oauth/authorize?client_id={}&redirect_uri={}&scope={}&response_type=code",
|
"{}/oauth/authorize?client_id={}&redirect_uri={}&scope={}&response_type=code",
|
||||||
self.base,
|
self.base, self.client_id, self.redirect, self.scopes,
|
||||||
self.client_id,
|
|
||||||
self.redirect,
|
|
||||||
self.scopes,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(url)
|
Ok(url)
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ use std::borrow::Cow;
|
|||||||
/// ```
|
/// ```
|
||||||
/// # extern crate elefren;
|
/// # extern crate elefren;
|
||||||
/// # use elefren::StatusesRequest;
|
/// # use elefren::StatusesRequest;
|
||||||
/// let request = StatusesRequest::new()
|
/// let request = StatusesRequest::new().only_media().pinned().since_id("foo");
|
||||||
/// .only_media()
|
|
||||||
/// .pinned()
|
|
||||||
/// .since_id("foo");
|
|
||||||
/// # assert_eq!(&request.to_querystring()[..], "?only_media=1&pinned=1&since_id=foo");
|
/// # assert_eq!(&request.to_querystring()[..], "?only_media=1&pinned=1&since_id=foo");
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
@@ -90,5 +87,3 @@ impl<'a> StatusesRequest<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,19 +4,19 @@ pub struct StatusBuilder {
|
|||||||
/// The text of the status.
|
/// The text of the status.
|
||||||
pub status: String,
|
pub status: String,
|
||||||
/// Ids of accounts being replied to.
|
/// 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>,
|
pub in_reply_to_id: Option<u64>,
|
||||||
/// Ids of media attachments being attached to the status.
|
/// 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>>,
|
pub media_ids: Option<Vec<u64>>,
|
||||||
/// Whether current status is sensitive.
|
/// Whether current status is sensitive.
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub sensitive: Option<bool>,
|
pub sensitive: Option<bool>,
|
||||||
/// Text to precede the normal status text.
|
/// 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>,
|
pub spoiler_text: Option<String>,
|
||||||
/// Visibility of the status, defaults to `Public`.
|
/// 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>,
|
pub visibility: Option<Visibility>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,6 @@ pub enum Visibility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StatusBuilder {
|
impl StatusBuilder {
|
||||||
|
|
||||||
/// Create a new status with text.
|
/// Create a new status with text.
|
||||||
/// ```
|
/// ```
|
||||||
/// use elefren::prelude::*;
|
/// use elefren::prelude::*;
|
||||||
@@ -47,7 +46,7 @@ impl StatusBuilder {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn new(status: String) -> Self {
|
pub fn new(status: String) -> Self {
|
||||||
StatusBuilder {
|
StatusBuilder {
|
||||||
status: status,
|
status,
|
||||||
..Self::default()
|
..Self::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user