Update Rust Edition; Update dependencies

Async needs added
This commit is contained in:
D. Scott Boggs 2022-11-29 18:50:29 -05:00
parent 96b16c62d9
commit f054c7d805
42 changed files with 372 additions and 665 deletions

View File

@ -2,4 +2,4 @@ export TOKEN='snakeoil'
export CLIENT_ID='' export CLIENT_ID=''
export CLIENT_SECRET='' export CLIENT_SECRET=''
export REDIRECT='' export REDIRECT=''
export BASE='https://mastodon.social' export BASE='https://botsin.space'

View File

@ -52,10 +52,10 @@ This release adds support for all new API endpoints introduced in Mastodon 2.4.*
* **scopes:** Implement granular OAuth scopes ([e284894d](e284894d), closes [#44](44)) * **scopes:** Implement granular OAuth scopes ([e284894d](e284894d), closes [#44](44))
* **helpers:** cli::authenticate ([034bd4e6](034bd4e6)) * **helpers:** cli::authenticate ([034bd4e6](034bd4e6))
* **client:** Implement client.update\_credentials ([a57c7e2f](a57c7e2f)) * **client:** Implement client.update\_credentials ([a57c7e2f](a57c7e2f))
* **status:** Add language code to status builer ([989d9a59](989d9a59), closes [#55](55)) * **status:** Add language code to status builder ([989d9a59](989d9a59), closes [#55](55))
* **client:** Implement profile metadata update ([0ad1e374](0ad1e374), closes [#54](54)) * **client:** Implement profile metadata update ([0ad1e374](0ad1e374), closes [#54](54))
* **search:** Implement `GET /api/v2/search` ([28192e11](28192e11)) * **search:** Implement `GET /api/v2/search` ([28192e11](28192e11))
* **client:** Implement push notifciations endpoints ([690b029d](690b029d), closes [#53](53)) * **client:** Implement push notifications endpoints ([690b029d](690b029d), closes [#53](53))
* **client:** Add `replies_count` property to `Status` entities ([7d752a9f](7d752a9f), closes [#73](73)) * **client:** Add `replies_count` property to `Status` entities ([7d752a9f](7d752a9f), closes [#73](73))
* **client:** Implement Keyword filtering API ([7d164cb8](7d164cb8), closes [#71](71)) * **client:** Implement Keyword filtering API ([7d164cb8](7d164cb8), closes [#71](71))
* **client:** Implement the Follow Suggestions API ([7de1bdc0](7de1bdc0), closes [#72](72)) * **client:** Implement the Follow Suggestions API ([7de1bdc0](7de1bdc0), closes [#72](72))
@ -111,7 +111,7 @@ This release adds support for all new API endpoints introduced in Mastodon 2.4.*
``` ```
You can still call use the `Registration` & `AppBuilder` APIs like You can still call use the `Registration` & `AppBuilder` APIs like
before, but any App passed to `.register` will supercede anything app before, but any App passed to `.register` will supersede anything app
config set on the `Registration` object itself. config set on the `Registration` object itself.
In future releases, this will become a hard error. In future releases, this will become a hard error.

View File

@ -12,14 +12,17 @@
[package] [package]
name = "elefren" name = "elefren"
version = "0.22.0" version = "0.23.0"
authors = ["Aaron Power <theaaronepower@gmail.com>", "Paul Woolcock <paul@woolcock.us>"] authors = ["Aaron Power <theaaronepower@gmail.com>", "Paul Woolcock <paul@woolcock.us>"]
description = "A wrapper around the Mastodon API." description = "A wrapper around the Mastodon API."
readme = "README.md" readme = "README.md"
keywords = ["api", "web", "social", "mastodon", "wrapper"] keywords = ["api", "web", "social", "mastodon", "wrapper"]
categories = ["web-programming", "web-programming::http-client", "api-bindings"] categories = ["web-programming", "web-programming::http-client", "api-bindings"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
repository = "https://github.com/pwoolcoc/elefren.git" edition = "2021"
# TODO setup repo
# repository = "https://github.com/pwoolcoc/elefren.git"
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["all"] features = ["all"]
[dependencies.chrono] [dependencies.chrono]
@ -30,15 +33,16 @@ features = ["serde"]
version = "0.3" version = "0.3"
[dependencies.envy] [dependencies.envy]
version = "0.4.0" version = "0.4"
optional = true optional = true
# Provides parsing for the link header in get_links() in page.rs
[dependencies.hyper-old-types] [dependencies.hyper-old-types]
version = "0.11.0" version = "0.11.0"
[dependencies.isolang] [dependencies.isolang]
version = "1.0" version = "2.2"
features = ["serde_serialize"] features = ["serde"]
[dependencies.log] [dependencies.log]
version = "0.4" version = "0.4"
@ -49,9 +53,7 @@ default-features = false
[dependencies.serde] [dependencies.serde]
version = "1" version = "1"
features = ["derive"]
[dependencies.serde_derive]
version = "1"
[dependencies.serde_json] [dependencies.serde_json]
version = "1" version = "1"
@ -66,30 +68,29 @@ version = "0.6.1"
version = "1" version = "1"
[dependencies.toml] [dependencies.toml]
version = "0.5.0" version = "0.5"
optional = true optional = true
[dependencies.try_from]
version = "0.3.2"
[dependencies.tungstenite] [dependencies.tungstenite]
version = "0.10.1" version = "0.10.1"
[dependencies.url] [dependencies.url]
version = "1" version = "1"
[dev-dependencies.indoc] [dev-dependencies.indoc]
version = "0.3.1" version = "1.0"
[dev-dependencies.pretty_env_logger] [dev-dependencies.pretty_env_logger]
version = "0.3.0" version = "0.3.0"
[dev-dependencies.skeptic] [dev-dependencies.skeptic]
version = "0.13.3" version = "0.13"
[dev-dependencies.tempfile] [dev-dependencies.tempfile]
version = "3.0.3" version = "3"
[build-dependencies.skeptic] [build-dependencies.skeptic]
version = "0.13.3" version = "0.13"
[features] [features]
all = ["toml", "json", "env"] all = ["toml", "json", "env"]

View File

@ -11,7 +11,7 @@
[Documentation](https://docs.rs/elefren/) [Documentation](https://docs.rs/elefren/)
A wrapper around the [API](https://github.com/tootsuite/documentation/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://botsin.space/)
## Installation ## Installation
@ -33,7 +33,6 @@ elefren = { version = "0.22", features = ["toml"] }
```rust,no_run ```rust,no_run
// src/main.rs // src/main.rs
extern crate elefren;
use std::error::Error; use std::error::Error;
@ -56,7 +55,7 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
fn register() -> Result<Mastodon, Box<dyn Error>> { fn register() -> Result<Mastodon, Box<dyn Error>> {
let registration = Registration::new("https://mastodon.social") let registration = Registration::new("https://botsin.space")
.client_name("elefren-examples") .client_name("elefren-examples")
.build()?; .build()?;
let mastodon = cli::authenticate(registration)?; let mastodon = cli::authenticate(registration)?;
@ -70,7 +69,7 @@ fn register() -> Result<Mastodon, Box<dyn Error>> {
It also supports the [Streaming API](https://docs.joinmastodon.org/api/streaming): It also supports the [Streaming API](https://docs.joinmastodon.org/api/streaming):
```no_run ```rust,no_run
use elefren::prelude::*; use elefren::prelude::*;
use elefren::entities::event::Event; use elefren::entities::event::Event;

View File

@ -2,7 +2,6 @@
#![cfg_attr(not(feature = "toml"), allow(unused_imports))] #![cfg_attr(not(feature = "toml"), allow(unused_imports))]
#[macro_use] #[macro_use]
extern crate pretty_env_logger; extern crate pretty_env_logger;
extern crate elefren;
mod register; mod register;
use register::MastodonClient; use register::MastodonClient;

View File

@ -2,7 +2,6 @@
#![cfg_attr(not(feature = "toml"), allow(unused_imports))] #![cfg_attr(not(feature = "toml"), allow(unused_imports))]
#[macro_use] #[macro_use]
extern crate pretty_env_logger; extern crate pretty_env_logger;
extern crate elefren;
mod register; mod register;
use register::MastodonClient; use register::MastodonClient;

View File

@ -2,7 +2,6 @@
#![cfg_attr(not(feature = "toml"), allow(unused_imports))] #![cfg_attr(not(feature = "toml"), allow(unused_imports))]
#[macro_use] #[macro_use]
extern crate pretty_env_logger; extern crate pretty_env_logger;
extern crate elefren;
mod register; mod register;
use register::MastodonClient; use register::MastodonClient;

View File

@ -1,9 +1,12 @@
use std::borrow::Cow; use std::borrow::Cow;
use try_from::TryInto; use serde::Serialize;
// use try_from::TryInto;
use errors::{Error, Result}; use crate::{
use scopes::Scopes; errors::{Error, Result},
scopes::Scopes,
};
/// Represents an application that can be registered with a mastodon instance /// Represents an application that can be registered with a mastodon instance
#[derive(Clone, Debug, Default, Serialize, PartialEq)] #[derive(Clone, Debug, Default, Serialize, PartialEq)]
@ -18,10 +21,9 @@ pub struct App {
impl App { impl App {
/// Get an AppBuilder object /// Get an AppBuilder object
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::apps::App; /// use elefren::apps::App;
/// ///
/// let mut builder = App::builder(); /// let mut builder = App::builder();
@ -32,21 +34,16 @@ impl App {
/// Retrieve the list of scopes that apply to this App /// Retrieve the list of scopes that apply to this App
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use elefren::Error;
/// use elefren::{apps::App, scopes::Scopes}; /// use elefren::{apps::App, scopes::Scopes};
/// ///
/// # fn main() -> Result<(), Error> {
/// let mut builder = App::builder(); /// let mut builder = App::builder();
/// builder.client_name("elefren-test"); /// builder.client_name("elefren-test");
/// let app = builder.build()?; /// let app = builder.build().unwrap();
/// let scopes = app.scopes(); /// let scopes = app.scopes();
/// assert_eq!(scopes, &Scopes::read_all()); /// assert_eq!(scopes, &Scopes::read_all());
/// # Ok(())
/// # }
/// ``` /// ```
pub fn scopes(&self) -> &Scopes { pub fn scopes(&self) -> &Scopes {
&self.scopes &self.scopes
@ -55,15 +52,11 @@ impl App {
/// Builder struct for defining your application. /// Builder struct for defining your application.
/// ``` /// ```
/// use elefren::apps::App; /// use elefren::{apps::App};
/// use std::error::Error;
/// ///
/// # fn main() -> Result<(), Box<Error>> {
/// let mut builder = App::builder(); /// let mut builder = App::builder();
/// builder.client_name("elefren_test"); /// builder.client_name("elefren_test");
/// let app = builder.build()?; /// let app = builder.build().unwrap();
/// # Ok(())
/// # }
/// ``` /// ```
#[derive(Clone, Debug, Default, PartialEq, Serialize)] #[derive(Clone, Debug, Default, PartialEq, Serialize)]
pub struct AppBuilder<'a> { pub struct AppBuilder<'a> {
@ -129,16 +122,8 @@ impl<'a> AppBuilder<'a> {
} }
} }
impl TryInto<App> for App {
type Err = Error;
fn try_into(self) -> Result<App> {
Ok(self)
}
}
impl<'a> TryInto<App> for AppBuilder<'a> { impl<'a> TryInto<App> for AppBuilder<'a> {
type Err = Error; type Error = Error;
fn try_into(self) -> Result<App> { fn try_into(self) -> Result<App> {
Ok(self.build()?) Ok(self.build()?)

View File

@ -1,10 +1,12 @@
use std::borrow::Cow; use std::borrow::Cow;
use serde::{Deserialize, Serialize};
/// Raw data about mastodon app. Save `Data` using `serde` to prevent needing /// Raw data about mastodon app. Save `Data` using `serde` to prevent needing
/// to authenticate on every run. /// to authenticate on every run.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
pub struct Data { pub struct Data {
/// Base url of instance eg. `https://mastodon.social`. /// Base url of instance eg. `https://botsin.space`.
pub base: Cow<'static, str>, pub base: Cow<'static, str>,
/// The client's id given by the instance. /// The client's id given by the instance.
pub client_id: Cow<'static, str>, pub client_id: Cow<'static, str>,

View File

@ -1,8 +1,12 @@
//! A module containing everything relating to a account returned from the api. //! A module containing everything relating to a account returned from the api.
use crate::status_builder;
use chrono::prelude::*; use chrono::prelude::*;
use serde::de::{self, Deserialize, Deserializer, Unexpected}; use serde::{
use status_builder; de::{self, Deserializer, Unexpected},
Deserialize,
Serialize,
};
use std::path::PathBuf; use std::path::PathBuf;
/// A struct representing an Account. /// A struct representing an Account.

View File

@ -1,5 +1,7 @@
//! Module containing everything related to media attachements. //! Module containing everything related to media attachements.
use serde::Deserialize;
/// A struct representing a media attachment. /// A struct representing a media attachment.
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Attachment { pub struct Attachment {

View File

@ -1,5 +1,7 @@
//! Module representing cards of statuses. //! Module representing cards of statuses.
use serde::Deserialize;
/// A card of a status. /// A card of a status.
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Card { pub struct Card {

View File

@ -1,5 +1,7 @@
//! A module about contexts of statuses. //! A module about contexts of statuses.
use serde::Deserialize;
use super::status::Status; use super::status::Status;
/// A context of a status returning a list of statuses it replied to and /// A context of a status returning a list of statuses it replied to and

View File

@ -1,4 +1,4 @@
use entities::{notification::Notification, status::Status}; use crate::entities::{notification::Notification, status::Status};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
/// Events that come from the /streaming/user API call /// Events that come from the /streaming/user API call

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
/// Represents a single Filter /// Represents a single Filter
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Filter { pub struct Filter {

View File

@ -1,4 +1,6 @@
//! Module containing everything related to an instance. //! Module containing everything related to an instance.
use serde::Deserialize;
use super::account::Account; use super::account::Account;
/// A struct containing info of an instance. /// A struct containing info of an instance.

View File

@ -1,28 +1,16 @@
use http_send::HttpSend; use crate::{http_send::HttpSend, page::Page};
use page::Page;
use serde::Deserialize; use serde::Deserialize;
/// Abstracts away the `next_page` logic into a single stream of items /// Abstracts away the `next_page` logic into a single stream of items
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::prelude::*;
/// # use elefren::prelude::*; /// let data = Data::default();
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// let statuses = client.statuses("user-id", None)?; /// let statuses = client.statuses("user-id", None).unwrap();
/// for status in statuses.items_iter() { /// for status in statuses.items_iter() {
/// // do something with `status` /// // do something with `status`
/// } /// }
/// # Ok(())
/// # }
/// ``` /// ```
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>, H: 'a + HttpSend> { pub(crate) struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>, H: 'a + HttpSend> {

View File

@ -1,3 +1,5 @@
use serde::Deserialize;
/// Used for ser/de of list resources /// Used for ser/de of list resources
#[derive(Clone, Debug, Deserialize, PartialEq)] #[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct List { pub struct List {

View File

@ -1,3 +1,5 @@
use serde::Deserialize;
/// Data structures for ser/de of account-related resources /// Data structures for ser/de of account-related resources
pub mod account; pub mod account;
/// Data structures for ser/de of attachment-related resources /// Data structures for ser/de of attachment-related resources

View File

@ -2,6 +2,7 @@
use super::{account::Account, status::Status}; use super::{account::Account, status::Status};
use chrono::prelude::*; use chrono::prelude::*;
use serde::Deserialize;
/// A struct containing info about a notification. /// A struct containing info about a notification.
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq)]

View File

@ -1,3 +1,5 @@
use serde::{Deserialize, Serialize};
/// Represents the `alerts` key of the `Subscription` object /// Represents the `alerts` key of the `Subscription` object
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Default)] #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Default)]
pub struct Alerts { pub struct Alerts {
@ -25,6 +27,8 @@ pub struct Subscription {
} }
pub(crate) mod add_subscription { pub(crate) mod add_subscription {
use serde::Serialize;
use super::Alerts; use super::Alerts;
#[derive(Debug, Clone, PartialEq, Serialize, Default)] #[derive(Debug, Clone, PartialEq, Serialize, Default)]
@ -52,6 +56,8 @@ pub(crate) mod add_subscription {
} }
pub(crate) mod update_data { pub(crate) mod update_data {
use serde::Serialize;
use super::Alerts; use super::Alerts;
#[derive(Debug, Clone, PartialEq, Serialize, Default)] #[derive(Debug, Clone, PartialEq, Serialize, Default)]

View File

@ -1,6 +1,8 @@
//! module containing everything relating to a relationship with //! module containing everything relating to a relationship with
//! another account. //! another account.
use serde::Deserialize;
/// A struct containing information about a relationship with another account. /// A struct containing information about a relationship with another account.
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Relationship { pub struct Relationship {

View File

@ -1,5 +1,7 @@
//! module containing information about a finished report of a user. //! module containing information about a finished report of a user.
use serde::Deserialize;
/// A struct containing info about a report. /// A struct containing info about a report.
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Report { pub struct Report {

View File

@ -1,5 +1,7 @@
//! A module containing info relating to a search result. //! A module containing info relating to a search result.
use serde::Deserialize;
use super::{ use super::{
prelude::{Account, Status}, prelude::{Account, Status},
status::Tag, status::Tag,

View File

@ -1,9 +1,9 @@
//! Module containing all info relating to a status. //! Module containing all info relating to a status.
use super::prelude::*; use super::prelude::*;
use crate::{entities::card::Card, status_builder::Visibility};
use chrono::prelude::*; use chrono::prelude::*;
use entities::card::Card; use serde::Deserialize;
use status_builder::Visibility;
/// A status from the instance. /// A status from the instance.
#[derive(Debug, Clone, Deserialize, PartialEq)] #[derive(Debug, Clone, Deserialize, PartialEq)]

View File

@ -4,6 +4,7 @@ use std::{error, fmt, io::Error as IoError};
use envy::Error as EnvyError; use envy::Error as EnvyError;
use hyper_old_types::Error as HeaderParseError; use hyper_old_types::Error as HeaderParseError;
use reqwest::{header::ToStrError as HeaderStrError, Error as HttpError, StatusCode}; use reqwest::{header::ToStrError as HeaderStrError, Error as HttpError, StatusCode};
use serde::Deserialize;
use serde_json::Error as SerdeError; use serde_json::Error as SerdeError;
use serde_qs::Error as SerdeQsError; use serde_qs::Error as SerdeQsError;
use serde_urlencoded::ser::Error as UrlEncodedError; use serde_urlencoded::ser::Error as UrlEncodedError;
@ -11,8 +12,8 @@ use serde_urlencoded::ser::Error as UrlEncodedError;
use tomlcrate::de::Error as TomlDeError; use tomlcrate::de::Error as TomlDeError;
#[cfg(feature = "toml")] #[cfg(feature = "toml")]
use tomlcrate::ser::Error as TomlSerError; use tomlcrate::ser::Error as TomlSerError;
use url::ParseError as UrlError;
use tungstenite::error::Error as WebSocketError; use tungstenite::error::Error as WebSocketError;
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.
pub type Result<T> = ::std::result::Result<T, Error>; pub type Result<T> = ::std::result::Result<T, Error>;
@ -93,9 +94,7 @@ impl error::Error for Error {
Error::SerdeQs(ref e) => e, Error::SerdeQs(ref e) => e,
Error::WebSocket(ref e) => e, Error::WebSocket(ref e) => e,
Error::Client(..) | Error::Server(..) => { Error::Client(..) | Error::Server(..) => return None,
return None
},
Error::ClientIdRequired => return None, Error::ClientIdRequired => return None,
Error::ClientSecretRequired => return None, Error::ClientSecretRequired => return None,
Error::AccessTokenRequired => return None, Error::AccessTokenRequired => return None,
@ -167,9 +166,6 @@ macro_rules! format_err {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use reqwest;
use serde_json;
use serde_urlencoded;
use std::io; use std::io;
macro_rules! assert_is { macro_rules! assert_is {

View File

@ -1,9 +1,6 @@
use std::io::{self, BufRead, Write}; use std::io::{self, BufRead, Write};
use errors::Result; use crate::{errors::Result, http_send::HttpSend, registration::Registered, Mastodon};
use http_send::HttpSend;
use registration::Registered;
use Mastodon;
/// Finishes the authentication process for the given `Registered` object, /// Finishes the authentication process for the given `Registered` object,
/// using the command-line /// using the command-line

View File

@ -1,7 +1,7 @@
use envy; use envy;
use crate::Result;
use data::Data; use data::Data;
use Result;
/// Attempts to deserialize a Data struct from the environment /// Attempts to deserialize a Data struct from the environment
pub fn from_env() -> Result<Data> { pub fn from_env() -> Result<Data> {

View File

@ -6,8 +6,8 @@ use std::{
use serde_json; use serde_json;
use crate::Result;
use data::Data; use data::Data;
use Result;
/// Attempts to deserialize a Data struct from a string /// Attempts to deserialize a Data struct from a string
pub fn from_str(s: &str) -> Result<Data> { pub fn from_str(s: &str) -> Result<Data> {

View File

@ -6,8 +6,8 @@ use std::{
use tomlcrate; use tomlcrate;
use crate::Result;
use data::Data; use data::Data;
use Result;
/// Attempts to deserialize a Data struct from a string /// Attempts to deserialize a Data struct from a string
pub fn from_str(s: &str) -> Result<Data> { pub fn from_str(s: &str) -> Result<Data> {

View File

@ -1,6 +1,6 @@
use crate::Result;
use reqwest::{Client, Request, RequestBuilder, Response}; use reqwest::{Client, Request, RequestBuilder, Response};
use std::fmt::Debug; use std::fmt::Debug;
use Result;
/// Abstracts away the process of turning an HTTP request into an HTTP response /// Abstracts away the process of turning an HTTP request into an HTTP response
pub trait HttpSend: Clone + Debug { pub trait HttpSend: Clone + Debug {

View File

@ -1,51 +1,36 @@
//! # Elefren: API Wrapper around the Mastodon API. //! // Elefren: API Wrapper around the Mastodon API.
//! //!
//! Most of the api is documented on [Mastodon's website](https://docs.joinmastodon.org/client/intro/) //! Most of the api is documented on [Mastodon's website](https://docs.joinmastodon.org/client/intro/)
//! //!
//! ```no_run //! ```no_run
//! # extern crate elefren;
//! # fn main() {
//! # try().unwrap();
//! # }
//! # fn try() -> elefren::Result<()> {
//! use elefren::{helpers::cli, prelude::*}; //! use elefren::{helpers::cli, prelude::*};
//! //!
//! let registration = Registration::new("https://mastodon.social") //! let registration = Registration::new("https://botsin.space")
//! .client_name("elefren_test") //! .client_name("elefren_test")
//! .build()?; //! .build()
//! let mastodon = cli::authenticate(registration)?; //! .unwrap();
//! let mastodon = cli::authenticate(registration).unwrap();
//! //!
//! println!( //! println!(
//! "{:?}", //! "{:?}",
//! mastodon //! mastodon
//! .get_home_timeline()? //! .get_home_timeline()
//! .unwrap()
//! .items_iter() //! .items_iter()
//! .take(100) //! .take(100)
//! .collect::<Vec<_>>() //! .collect::<Vec<_>>()
//! ); //! );
//! # Ok(())
//! # }
//! ``` //! ```
//! //!
//! Elefren also supports Mastodon's Streaming API: //! Elefren also supports Mastodon's Streaming API:
//! //!
//! # Example //! // Example
//! //!
//! ```no_run //! ```no_run
//! # extern crate elefren; //! use elefren::{prelude::*, entities::event::Event};
//! # use elefren::prelude::*; //! let data = Data::default();
//! # use std::error::Error;
//! use elefren::entities::event::Event;
//! # fn main() -> Result<(), Box<Error>> {
//! # let data = Data {
//! # base: "".into(),
//! # client_id: "".into(),
//! # client_secret: "".into(),
//! # redirect: "".into(),
//! # token: "".into(),
//! # };
//! let client = Mastodon::from(data); //! let client = Mastodon::from(data);
//! for event in client.streaming_user()? { //! for event in client.streaming_user().unwrap() {
//! match event { //! match event {
//! Event::Update(ref status) => { /* .. */ }, //! Event::Update(ref status) => { /* .. */ },
//! Event::Notification(ref notification) => { /* .. */ }, //! Event::Notification(ref notification) => { /* .. */ },
@ -53,8 +38,6 @@
//! Event::FiltersChanged => { /* .. */ }, //! Event::FiltersChanged => { /* .. */ },
//! } //! }
//! } //! }
//! # Ok(())
//! # }
//! ``` //! ```
#![deny( #![deny(
@ -73,8 +56,6 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
#[macro_use] #[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate doc_comment; extern crate doc_comment;
extern crate hyper_old_types; extern crate hyper_old_types;
extern crate isolang; extern crate isolang;
@ -82,11 +63,11 @@ extern crate isolang;
extern crate serde_json; extern crate serde_json;
extern crate chrono; extern crate chrono;
extern crate reqwest; extern crate reqwest;
#[macro_use]
extern crate serde; extern crate serde;
extern crate serde_qs; extern crate serde_qs;
extern crate serde_urlencoded; extern crate serde_urlencoded;
extern crate tap_reader; extern crate tap_reader;
extern crate try_from;
extern crate tungstenite; extern crate tungstenite;
extern crate url; extern crate url;
@ -154,14 +135,16 @@ pub mod status_builder;
mod macros; mod macros;
/// Automatically import the things you need /// Automatically import the things you need
pub mod prelude { pub mod prelude {
pub use scopes::Scopes; pub use crate::{
pub use Data; scopes::Scopes,
pub use Mastodon; Data,
pub use MastodonClient; Mastodon,
pub use NewStatus; MastodonClient,
pub use Registration; NewStatus,
pub use StatusBuilder; Registration,
pub use StatusesRequest; StatusBuilder,
StatusesRequest,
};
} }
/// Your mastodon application client, handles all requests to and from Mastodon. /// Your mastodon application client, handles all requests to and from Mastodon.
@ -344,44 +327,22 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
/// Get statuses of a single account by id. Optionally only with pictures /// Get statuses of a single account by id. Optionally only with pictures
/// and or excluding replies. /// and or excluding replies.
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::prelude::*;
/// # use elefren::prelude::*; /// let data = Data::default();
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// let statuses = client.statuses("user-id", None)?; /// let statuses = client.statuses("user-id", None).unwrap();
/// # Ok(())
/// # }
/// ``` /// ```
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::prelude::*;
/// # use elefren::prelude::*; /// let data = Data::default();
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// let mut request = StatusesRequest::new(); /// let mut request = StatusesRequest::new();
/// request.only_media(); /// request.only_media();
/// let statuses = client.statuses("user-id", request)?; /// let statuses = client.statuses("user-id", request).unwrap();
/// # Ok(())
/// # }
/// ``` /// ```
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status, H>> fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status, H>>
where where
@ -460,23 +421,14 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
/// returns events that are relevant to the authorized user, i.e. home /// returns events that are relevant to the authorized user, i.e. home
/// timeline & notifications /// timeline & notifications
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::prelude::*;
/// # use elefren::prelude::*;
/// # use std::error::Error;
/// use elefren::entities::event::Event; /// use elefren::entities::event::Event;
/// # fn main() -> Result<(), Box<Error>> { /// let data = Data::default();
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// for event in client.streaming_user()? { /// for event in client.streaming_user().unwrap() {
/// match event { /// match event {
/// Event::Update(ref status) => { /* .. */ }, /// Event::Update(ref status) => { /* .. */ },
/// Event::Notification(ref notification) => { /* .. */ }, /// Event::Notification(ref notification) => { /* .. */ },
@ -484,8 +436,6 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
/// Event::FiltersChanged => { /* .. */ }, /// Event::FiltersChanged => { /* .. */ },
/// } /// }
/// } /// }
/// # Ok(())
/// # }
/// ``` /// ```
fn streaming_user(&self) -> Result<Self::Stream> { fn streaming_user(&self) -> Result<Self::Stream> {
let mut url: url::Url = self.route("/api/v1/streaming").parse()?; let mut url: url::Url = self.route("/api/v1/streaming").parse()?;

View File

@ -24,20 +24,10 @@ macro_rules! paged_routes {
"`\n# Errors\nIf `access_token` is not set.", "`\n# Errors\nIf `access_token` is not set.",
"\n", "\n",
"```no_run", "```no_run",
"# extern crate elefren;\n", "use elefren::prelude::*;\n",
"# use elefren::prelude::*;\n", "let data = Data::default();\n",
"# fn main() -> Result<(), Box<::std::error::Error>> {\n",
"# let data = Data {\n",
"# base: \"https://example.com\".into(),\n",
"# client_id: \"taosuah\".into(),\n",
"# client_secret: \"htnjdiuae\".into(),\n",
"# redirect: \"https://example.com\".into(),\n",
"# token: \"tsaohueaheis\".into(),\n",
"# };\n",
"let client = Mastodon::from(data);\n", "let client = Mastodon::from(data);\n",
"client.", stringify!($name), "();\n", "client.", stringify!($name), "();\n",
"# Ok(())\n",
"# }\n",
"```" "```"
), ),
fn $name(&self) -> Result<Page<$ret, H>> { fn $name(&self) -> Result<Page<$ret, H>> {
@ -259,20 +249,10 @@ macro_rules! route {
"`\n# Errors\nIf `access_token` is not set.", "`\n# Errors\nIf `access_token` is not set.",
"\n", "\n",
"```no_run", "```no_run",
"# extern crate elefren;\n", "use elefren::prelude::*;\n",
"# use elefren::prelude::*;\n", "let data = Data::default();\n",
"# fn main() -> Result<(), Box<::std::error::Error>> {\n",
"# let data = Data {\n",
"# base: \"https://example.com\".into(),\n",
"# client_id: \"taosuah\".into(),\n",
"# client_secret: \"htnjdiuae\".into(),\n",
"# redirect: \"https://example.com\".into(),\n",
"# token: \"tsaohueaheis\".into(),\n",
"# };\n",
"let client = Mastodon::from(data);\n", "let client = Mastodon::from(data);\n",
"client.", stringify!($name), "();\n", "client.", stringify!($name), "();\n",
"# Ok(())\n",
"# }\n",
"```" "```"
), ),
fn $name(&self) -> Result<$ret> { fn $name(&self) -> Result<$ret> {
@ -297,16 +277,8 @@ macro_rules! route_id {
"`\n# Errors\nIf `access_token` is not set.", "`\n# Errors\nIf `access_token` is not set.",
"\n", "\n",
"```no_run", "```no_run",
"# extern crate elefren;\n", "use elefren::prelude::*;\n",
"# use elefren::prelude::*;\n", "let data = Data::default();\n",
"# fn main() -> Result<(), Box<::std::error::Error>> {\n",
"# let data = Data {\n",
"# base: \"https://example.com\".into(),\n",
"# client_id: \"taosuah\".into(),\n",
"# client_secret: \"htnjdiuae\".into(),\n",
"# redirect: \"https://example.com\".into(),\n",
"# token: \"tsaohueaheis\".into(),\n",
"# };\n",
"let client = Mastodon::from(data);\n", "let client = Mastodon::from(data);\n",
"client.", stringify!($name), "(\"42\");\n", "client.", stringify!($name), "(\"42\");\n",
"# Ok(())\n", "# Ok(())\n",
@ -331,20 +303,10 @@ macro_rules! paged_routes_with_id {
"`\n# Errors\nIf `access_token` is not set.", "`\n# Errors\nIf `access_token` is not set.",
"\n", "\n",
"```no_run", "```no_run",
"# extern crate elefren;\n", "use elefren::prelude::*;\n",
"# use elefren::prelude::*;\n", "let data = Data::default();",
"# fn main() -> Result<(), Box<::std::error::Error>> {\n",
"# let data = Data {\n",
"# base: \"https://example.com\".into(),\n",
"# client_id: \"taosuah\".into(),\n",
"# client_secret: \"htnjdiuae\".into(),\n",
"# redirect: \"https://example.com\".into(),\n",
"# token: \"tsaohueaheis\".into(),\n",
"# };\n",
"let client = Mastodon::from(data);\n", "let client = Mastodon::from(data);\n",
"client.", stringify!($name), "(\"some-id\");\n", "client.", stringify!($name), "(\"some-id\");\n",
"# Ok(())\n",
"# }\n",
"```" "```"
), ),
fn $name(&self, id: &str) -> Result<Page<$ret, H>> { fn $name(&self, id: &str) -> Result<Page<$ret, H>> {

View File

@ -1,17 +1,19 @@
use std::borrow::Cow; use std::borrow::Cow;
use entities::prelude::*; use crate::{
use errors::Result; entities::prelude::*,
use http_send::{HttpSend, HttpSender}; errors::Result,
use page::Page; http_send::{HttpSend, HttpSender},
use requests::{ page::Page,
AddFilterRequest, requests::{
AddPushRequest, AddFilterRequest,
StatusesRequest, AddPushRequest,
UpdateCredsRequest, StatusesRequest,
UpdatePushRequest, UpdateCredsRequest,
UpdatePushRequest,
},
status_builder::NewStatus,
}; };
use status_builder::NewStatus;
/// Represents the set of methods that a Mastodon Client can do, so that /// Represents the set of methods that a Mastodon Client can do, so that
/// implementations might be swapped out for testing /// implementations might be swapped out for testing
@ -283,21 +285,11 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
/// Shortcut for: `let me = client.verify_credentials(); client.followers()` /// Shortcut for: `let me = client.verify_credentials(); client.followers()`
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::prelude::*;
/// # use std::error::Error; /// let data = Data::default();
/// # use elefren::prelude::*; /// let client = Mastodon::from(data);
/// # fn main() -> Result<(), Box<Error>> { /// let follows_me = client.follows_me().unwrap();
/// # let data = Data { /// ```
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// # let client = Mastodon::from(data);
/// let follows_me = client.follows_me()?;
/// # Ok(())
/// # }
fn follows_me(&self) -> Result<Page<Account, H>> { fn follows_me(&self) -> Result<Page<Account, H>> {
unimplemented!("This method was not implemented"); unimplemented!("This method was not implemented");
} }
@ -305,21 +297,11 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
/// `let me = client.verify_credentials(); client.following(&me.id)` /// `let me = client.verify_credentials(); client.following(&me.id)`
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::prelude::*;
/// # use std::error::Error; /// let data = Data::default();
/// # use elefren::prelude::*; /// let client = Mastodon::from(data);
/// # fn main() -> Result<(), Box<Error>> { /// let follows_me = client.followed_by_me().unwrap();
/// # let data = Data { /// ```
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// # let client = Mastodon::from(data);
/// let follows_me = client.followed_by_me()?;
/// # Ok(())
/// # }
fn followed_by_me(&self) -> Result<Page<Account, H>> { fn followed_by_me(&self) -> Result<Page<Account, H>> {
unimplemented!("This method was not implemented"); unimplemented!("This method was not implemented");
} }

View File

@ -1,11 +1,11 @@
use super::{deserialise, Mastodon, Result}; use super::{deserialise, Mastodon, Result};
use entities::itemsiter::ItemsIter; use crate::entities::itemsiter::ItemsIter;
use hyper_old_types::header::{parsing, Link, RelationType}; use hyper_old_types::header::{parsing, Link, RelationType};
use reqwest::{header::LINK, Response}; use reqwest::{header::LINK, Response};
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
use http_send::HttpSend; use crate::http_send::HttpSend;
macro_rules! pages { macro_rules! pages {
($($direction:ident: $fun:ident),*) => { ($($direction:ident: $fun:ident),*) => {
@ -36,36 +36,28 @@ macro_rules! pages {
/// Owned version of the `Page` struct in this module. Allows this to be more /// Owned version of the `Page` struct in this module. Allows this to be more
/// easily stored for later use /// easily stored for later use
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::{
/// # use elefren::Mastodon; /// prelude::*,
/// # use elefren::page::OwnedPage; /// page::OwnedPage,
/// # use elefren::http_send::HttpSender; /// http_send::HttpSender,
/// # use elefren::entities::status::Status; /// entities::status::Status
/// # use std::cell::RefCell; /// };
/// # use elefren::prelude::*; /// use std::cell::RefCell;
/// # fn main() -> Result<(), elefren::Error> { ///
/// # let data = Data { /// let data = Data::default();
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// struct HomeTimeline { /// struct HomeTimeline {
/// client: Mastodon, /// client: Mastodon,
/// page: RefCell<Option<OwnedPage<Status, HttpSender>>>, /// page: RefCell<Option<OwnedPage<Status, HttpSender>>>,
/// } /// }
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// let home = client.get_home_timeline()?.to_owned(); /// let home = client.get_home_timeline().unwrap().to_owned();
/// let tl = HomeTimeline { /// let tl = HomeTimeline {
/// client, /// client,
/// page: RefCell::new(Some(home)), /// page: RefCell::new(Some(home)),
/// }; /// };
/// # Ok(())
/// # }
/// ``` /// ```
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct OwnedPage<T: for<'de> Deserialize<'de>, H: HttpSend> { pub struct OwnedPage<T: for<'de> Deserialize<'de>, H: HttpSend> {
@ -125,36 +117,22 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
/// Returns an owned version of this struct that doesn't borrow the client /// Returns an owned version of this struct that doesn't borrow the client
/// that created it /// that created it
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::{Mastodon, page::OwnedPage, http_send::HttpSender, entities::status::Status, prelude::*};
/// # use elefren::Mastodon; /// use std::cell::RefCell;
/// # use elefren::page::OwnedPage; /// let data = Data::default();
/// # use elefren::http_send::HttpSender;
/// # use elefren::entities::status::Status;
/// # use std::cell::RefCell;
/// # use elefren::prelude::*;
/// # fn main() -> Result<(), elefren::Error> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// struct HomeTimeline { /// struct HomeTimeline {
/// client: Mastodon, /// client: Mastodon,
/// page: RefCell<Option<OwnedPage<Status, HttpSender>>>, /// page: RefCell<Option<OwnedPage<Status, HttpSender>>>,
/// } /// }
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// let home = client.get_home_timeline()?.to_owned(); /// let home = client.get_home_timeline().unwrap().to_owned();
/// let tl = HomeTimeline { /// let tl = HomeTimeline {
/// client, /// client,
/// page: RefCell::new(Some(home)), /// page: RefCell::new(Some(home)),
/// }; /// };
/// # Ok(())
/// # }
/// ``` /// ```
pub fn to_owned(self) -> OwnedPage<T, H> { pub fn to_owned(self) -> OwnedPage<T, H> {
OwnedPage::from(self) OwnedPage::from(self)
@ -170,28 +148,17 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
/// more of them, until /// more of them, until
/// there are no more items. /// there are no more items.
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::prelude::*; /// use elefren::prelude::*;
/// # fn main() -> Result<(), Box<Error>> { /// let data = Data::default();
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// let mastodon = Mastodon::from(data); /// let mastodon = Mastodon::from(data);
/// let req = StatusesRequest::new(); /// let req = StatusesRequest::new();
/// let resp = mastodon.statuses("some-id", req)?; /// let resp = mastodon.statuses("some-id", req).unwrap();
/// for status in resp.items_iter() { /// for status in resp.items_iter() {
/// // do something with status /// // do something with status
/// } /// }
/// # Ok(())
/// # }
/// ``` /// ```
pub fn items_iter(self) -> impl Iterator<Item = T> + 'a pub fn items_iter(self) -> impl Iterator<Item = T> + 'a
where where

View File

@ -1,17 +1,18 @@
use std::borrow::Cow; use std::borrow::Cow;
use reqwest::{Client, RequestBuilder, Response}; use reqwest::{Client, RequestBuilder, Response};
use try_from::TryInto;
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET}; use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
use apps::{App, AppBuilder}; use crate::{
use http_send::{HttpSend, HttpSender}; apps::{App, AppBuilder},
use scopes::Scopes; http_send::{HttpSend, HttpSender},
use Data; scopes::Scopes,
use Error; Data,
use Mastodon; Error,
use MastodonBuilder; Mastodon,
use Result; MastodonBuilder,
Result,
};
const DEFAULT_REDIRECT_URI: &'static str = "urn:ietf:wg:oauth:2.0:oob"; const DEFAULT_REDIRECT_URI: &'static str = "urn:ietf:wg:oauth:2.0:oob";
@ -48,7 +49,7 @@ impl<'a> Registration<'a, HttpSender> {
/// ``` /// ```
/// use elefren::prelude::*; /// use elefren::prelude::*;
/// ///
/// let registration = Registration::new("https://mastodon.social"); /// let registration = Registration::new("https://botsin.space");
/// ``` /// ```
pub fn new<I: Into<String>>(base: I) -> Self { pub fn new<I: Into<String>>(base: I) -> Self {
Registration { Registration {
@ -116,27 +117,23 @@ impl<'a, H: HttpSend> Registration<'a, H> {
/// Register the given application /// Register the given application
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren;
/// # fn main () -> elefren::Result<()> {
/// use elefren::{apps::App, prelude::*}; /// use elefren::{apps::App, 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").register(app)?; /// let registration = Registration::new("https://botsin.space").register(app).unwrap();
/// let url = registration.authorize_url()?; /// let url = registration.authorize_url().unwrap();
/// // 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.
/// let code = String::from("RETURNED_FROM_BROWSER"); /// let code = String::from("RETURNED_FROM_BROWSER");
/// let mastodon = registration.complete(&code)?; /// let mastodon = registration.complete(&code).unwrap();
/// ///
/// println!("{:?}", mastodon.get_home_timeline()?.initial_items); /// println!("{:?}", mastodon.get_home_timeline().unwrap().initial_items);
/// # Ok(())
/// # }
/// ``` /// ```
pub fn register<I: TryInto<App>>(&mut self, app: I) -> Result<Registered<H>> pub fn register<I: TryInto<App>>(&mut self, app: I) -> Result<Registered<H>>
where where
Error: From<<I as TryInto<App>>::Err>, Error: From<<I as TryInto<App>>::Error>,
{ {
let app = app.try_into()?; let app = app.try_into()?;
let oauth = self.send_app(&app)?; let oauth = self.send_app(&app)?;
@ -156,22 +153,18 @@ impl<'a, H: HttpSend> Registration<'a, H> {
/// Register the application with the server from the `base` url. /// Register the application with the server from the `base` url.
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren;
/// # fn main () -> elefren::Result<()> {
/// use elefren::prelude::*; /// use elefren::prelude::*;
/// ///
/// let registration = Registration::new("https://mastodon.social") /// let registration = Registration::new("https://botsin.space")
/// .client_name("elefren_test") /// .client_name("elefren_test")
/// .build()?; /// .build().unwrap();
/// let url = registration.authorize_url()?; /// let url = registration.authorize_url().unwrap();
/// // 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.
/// let code = String::from("RETURNED_FROM_BROWSER"); /// let code = String::from("RETURNED_FROM_BROWSER");
/// let mastodon = registration.complete(&code)?; /// let mastodon = registration.complete(&code).unwrap();
/// ///
/// println!("{:?}", mastodon.get_home_timeline()?.initial_items); /// println!("{:?}", mastodon.get_home_timeline().unwrap().initial_items);
/// # Ok(())
/// # }
/// ``` /// ```
pub fn build(&mut self) -> Result<Registered<H>> { pub fn build(&mut self) -> Result<Registered<H>> {
let app: App = self.app_builder.clone().build()?; let app: App = self.app_builder.clone().build()?;
@ -199,11 +192,9 @@ impl Registered<HttpSender> {
/// Skip having to retrieve the client id and secret from the server by /// Skip having to retrieve the client id and secret from the server by
/// creating a `Registered` struct directly /// creating a `Registered` struct directly
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren;
/// # fn main() -> elefren::Result<()> {
/// use elefren::{prelude::*, registration::Registered}; /// use elefren::{prelude::*, registration::Registered};
/// ///
/// let registration = Registered::from_parts( /// let registration = Registered::from_parts(
@ -214,15 +205,13 @@ impl Registered<HttpSender> {
/// Scopes::read_all(), /// Scopes::read_all(),
/// false, /// false,
/// ); /// );
/// let url = registration.authorize_url()?; /// let url = registration.authorize_url().unwrap();
/// // 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.
/// let code = String::from("RETURNED_FROM_BROWSER"); /// let code = String::from("RETURNED_FROM_BROWSER");
/// let mastodon = registration.complete(&code)?; /// let mastodon = registration.complete(&code).unwrap();
/// ///
/// println!("{:?}", mastodon.get_home_timeline()?.initial_items); /// println!("{:?}", mastodon.get_home_timeline().unwrap().initial_items);
/// # Ok(())
/// # }
/// ``` /// ```
pub fn from_parts( pub fn from_parts(
base: &str, base: &str,
@ -253,39 +242,35 @@ impl<H: HttpSend> Registered<H> {
/// Returns the parts of the `Registered` struct that can be used to /// Returns the parts of the `Registered` struct that can be used to
/// recreate another `Registered` struct /// recreate another `Registered` struct
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::{prelude::*, registration::Registered}; /// use elefren::{prelude::*, registration::Registered};
/// # fn main() -> Result<(), Box<std::error::Error>> {
/// ///
/// let origbase = "https://example.social"; /// let orig_base = "https://example.social";
/// let origclient_id = "some-client_id"; /// let orig_client_id = "some-client_id";
/// let origclient_secret = "some-client-secret"; /// let orig_client_secret = "some-client-secret";
/// let origredirect = "https://example.social/redirect"; /// let orig_redirect = "https://example.social/redirect";
/// let origscopes = Scopes::all(); /// let orig_scopes = Scopes::all();
/// let origforce_login = false; /// let orig_force_login = false;
/// ///
/// let registered = Registered::from_parts( /// let registered = Registered::from_parts(
/// origbase, /// orig_base,
/// origclient_id, /// orig_client_id,
/// origclient_secret, /// orig_client_secret,
/// origredirect, /// orig_redirect,
/// origscopes.clone(), /// orig_scopes.clone(),
/// origforce_login, /// orig_force_login,
/// ); /// );
/// ///
/// let (base, client_id, client_secret, redirect, scopes, force_login) = registered.into_parts(); /// let (base, client_id, client_secret, redirect, scopes, force_login) = registered.into_parts();
/// ///
/// assert_eq!(origbase, &base); /// assert_eq!(orig_base, &base);
/// assert_eq!(origclient_id, &client_id); /// assert_eq!(orig_client_id, &client_id);
/// assert_eq!(origclient_secret, &client_secret); /// assert_eq!(orig_client_secret, &client_secret);
/// assert_eq!(origredirect, &redirect); /// assert_eq!(orig_redirect, &redirect);
/// assert_eq!(origscopes, scopes); /// assert_eq!(orig_scopes, scopes);
/// assert_eq!(origforce_login, force_login); /// assert_eq!(orig_force_login, force_login);
/// # Ok(())
/// # }
/// ``` /// ```
pub fn into_parts(self) -> (String, String, String, String, Scopes, bool) { pub fn into_parts(self) -> (String, String, String, String, Scopes, bool) {
( (
@ -298,7 +283,7 @@ impl<H: HttpSend> Registered<H> {
) )
} }
/// Returns the full url needed for authorisation. This needs to be opened /// Returns the full url needed for authorization. This needs to be opened
/// in a browser. /// in a browser.
pub fn authorize_url(&self) -> Result<String> { pub fn authorize_url(&self) -> Result<String> {
let scopes = format!("{}", self.scopes); let scopes = format!("{}", self.scopes);
@ -320,7 +305,7 @@ impl<H: HttpSend> Registered<H> {
} }
/// Create an access token from the client id, client secret, and code /// Create an access token from the client id, client secret, and code
/// provided by the authorisation url. /// provided by the authorization url.
pub fn complete(&self, code: &str) -> Result<Mastodon<H>> { pub fn complete(&self, code: &str) -> Result<Mastodon<H>> {
let url = format!( let url = format!(
"{}/oauth/token?client_id={}&client_secret={}&code={}&grant_type=authorization_code&\ "{}/oauth/token?client_id={}&client_secret={}&code={}&grant_type=authorization_code&\

View File

@ -1,18 +1,13 @@
use entities::filter::FilterContext; use crate::entities::filter::FilterContext;
use std::time::Duration; use std::time::Duration;
/// Form used to create a filter /// Form used to create a filter
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::{entities::filter::FilterContext, requests::AddFilterRequest}; /// use elefren::{entities::filter::FilterContext, requests::AddFilterRequest};
/// # fn main() -> Result<(), Box<Error>> {
/// let request = AddFilterRequest::new("foo", FilterContext::Home); /// let request = AddFilterRequest::new("foo", FilterContext::Home);
/// # Ok(())
/// # }
/// ``` /// ```
#[derive(Debug, Clone, PartialEq, Serialize)] #[derive(Debug, Clone, PartialEq, Serialize)]
pub struct AddFilterRequest { pub struct AddFilterRequest {

View File

@ -1,12 +1,13 @@
use entities::push::{add_subscription, update_data}; use crate::{
use errors::Result; entities::push::{add_subscription, update_data},
errors::Result,
};
/// Container for the key & auth strings for an AddPushRequest /// Container for the key & auth strings for an AddPushRequest
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::Keys; /// use elefren::requests::Keys;
/// ///
/// let keys = Keys::new("anetohias===", "oeatssah="); /// let keys = Keys::new("anetohias===", "oeatssah=");
@ -20,10 +21,9 @@ pub struct Keys {
impl Keys { impl Keys {
/// Create the `Keys` container /// Create the `Keys` container
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::Keys; /// use elefren::requests::Keys;
/// ///
/// let keys = Keys::new("anetohias===", "oeatssah="); /// let keys = Keys::new("anetohias===", "oeatssah=");
@ -38,30 +38,20 @@ impl Keys {
/// Builder to pass to the Mastodon::add_push_subscription method /// Builder to pass to the Mastodon::add_push_subscription method
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::{MastodonClient, Mastodon, Data};
/// # use elefren::{MastodonClient, Mastodon, Data};
/// # fn main() -> Result<(), elefren::Error> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// use elefren::requests::{AddPushRequest, Keys}; /// use elefren::requests::{AddPushRequest, Keys};
/// ///
/// let data = Data::default();
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// ///
/// let keys = Keys::new("stahesuahoei293ise===", "tasecoa,nmeozka=="); /// let keys = Keys::new("stahesuahoei293ise===", "tasecoa,nmeozka==");
/// let mut request = AddPushRequest::new("http://example.com/push/endpoint", &keys); /// let mut request = AddPushRequest::new("http://example.com/push/endpoint", &keys);
/// request.follow().reblog(); /// request.follow().reblog();
/// ///
/// client.add_push_subscription(&request)?; /// client.add_push_subscription(&request).unwrap();
/// # Ok(())
/// # }
/// ``` /// ```
#[derive(Debug, Default, Clone, PartialEq)] #[derive(Debug, Default, Clone, PartialEq)]
pub struct AddPushRequest { pub struct AddPushRequest {
@ -79,10 +69,9 @@ pub struct AddPushRequest {
impl AddPushRequest { impl AddPushRequest {
/// Construct a new AddPushRequest /// Construct a new AddPushRequest
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::{AddPushRequest, Keys}; /// use elefren::requests::{AddPushRequest, Keys};
/// let keys = Keys::new("abcdef===", "foobar=="); /// let keys = Keys::new("abcdef===", "foobar==");
/// let push_endpoint = "https://example.com/push/endpoint"; /// let push_endpoint = "https://example.com/push/endpoint";
@ -99,9 +88,8 @@ impl AddPushRequest {
/// A flag that indicates if you want follow notifications pushed /// A flag that indicates if you want follow notifications pushed
/// ///
/// # Example /// // Example
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::{AddPushRequest, Keys}; /// use elefren::requests::{AddPushRequest, Keys};
/// let keys = Keys::new("abcdef===", "foobar=="); /// let keys = Keys::new("abcdef===", "foobar==");
/// let push_endpoint = "https://example.com/push/endpoint"; /// let push_endpoint = "https://example.com/push/endpoint";
@ -115,9 +103,8 @@ impl AddPushRequest {
/// A flag that indicates if you want favourite notifications pushed /// A flag that indicates if you want favourite notifications pushed
/// ///
/// # Example /// // Example
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::{AddPushRequest, Keys}; /// use elefren::requests::{AddPushRequest, Keys};
/// let keys = Keys::new("abcdef===", "foobar=="); /// let keys = Keys::new("abcdef===", "foobar==");
/// let push_endpoint = "https://example.com/push/endpoint"; /// let push_endpoint = "https://example.com/push/endpoint";
@ -131,9 +118,8 @@ impl AddPushRequest {
/// A flag that indicates if you want reblog notifications pushed /// A flag that indicates if you want reblog notifications pushed
/// ///
/// # Example /// // Example
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::{AddPushRequest, Keys}; /// use elefren::requests::{AddPushRequest, Keys};
/// let keys = Keys::new("abcdef===", "foobar=="); /// let keys = Keys::new("abcdef===", "foobar==");
/// let push_endpoint = "https://example.com/push/endpoint"; /// let push_endpoint = "https://example.com/push/endpoint";
@ -147,9 +133,8 @@ impl AddPushRequest {
/// A flag that indicates if you want mention notifications pushed /// A flag that indicates if you want mention notifications pushed
/// ///
/// # Example /// // Example
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::{AddPushRequest, Keys}; /// use elefren::requests::{AddPushRequest, Keys};
/// let keys = Keys::new("abcdef===", "foobar=="); /// let keys = Keys::new("abcdef===", "foobar==");
/// let push_endpoint = "https://example.com/push/endpoint"; /// let push_endpoint = "https://example.com/push/endpoint";
@ -169,7 +154,7 @@ impl AddPushRequest {
} }
pub(crate) fn build(&self) -> Result<add_subscription::Form> { pub(crate) fn build(&self) -> Result<add_subscription::Form> {
use entities::push::{ use crate::entities::push::{
add_subscription::{Data, Form, Keys, Subscription}, add_subscription::{Data, Form, Keys, Subscription},
Alerts, Alerts,
}; };
@ -212,29 +197,19 @@ impl AddPushRequest {
/// Builder to pass to the Mastodon::update_push_data method /// Builder to pass to the Mastodon::update_push_data method
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren; /// use elefren::{MastodonClient, Mastodon, Data, requests::UpdatePushRequest};
/// # use elefren::{MastodonClient, Mastodon, Data}; /// let data = Data::default();
/// # fn main() -> Result<(), elefren::Error> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// use elefren::requests::UpdatePushRequest;
/// ///
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// ///
/// let mut request = UpdatePushRequest::new("foobar"); /// let mut request = UpdatePushRequest::new("foobar");
/// request.follow(true).reblog(true); /// request.follow(true)
/// .reblog(true);
/// ///
/// client.update_push_data(&request)?; /// client.update_push_data(&request).unwrap();
/// # Ok(())
/// # }
/// ``` /// ```
#[derive(Debug, Default, Clone, PartialEq, Serialize)] #[derive(Debug, Default, Clone, PartialEq, Serialize)]
pub struct UpdatePushRequest { pub struct UpdatePushRequest {
@ -248,12 +223,10 @@ pub struct UpdatePushRequest {
impl UpdatePushRequest { impl UpdatePushRequest {
/// Construct a new UpdatePushRequest /// Construct a new UpdatePushRequest
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let request = elefren::requests::UpdatePushRequest::new("some-id");
/// use elefren::requests::UpdatePushRequest;
/// let request = UpdatePushRequest::new("some-id");
/// ``` /// ```
pub fn new(id: &str) -> UpdatePushRequest { pub fn new(id: &str) -> UpdatePushRequest {
UpdatePushRequest { UpdatePushRequest {
@ -264,11 +237,9 @@ impl UpdatePushRequest {
/// A flag that indicates if you want follow notifications pushed /// A flag that indicates if you want follow notifications pushed
/// ///
/// # Example /// // Example
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::UpdatePushRequest::new("foobar");
/// use elefren::requests::UpdatePushRequest;
/// let mut request = UpdatePushRequest::new("foobar");
/// request.follow(true); /// request.follow(true);
/// ``` /// ```
pub fn follow(&mut self, follow: bool) -> &mut Self { pub fn follow(&mut self, follow: bool) -> &mut Self {
@ -278,11 +249,9 @@ impl UpdatePushRequest {
/// A flag that indicates if you want favourite notifications pushed /// A flag that indicates if you want favourite notifications pushed
/// ///
/// # Example /// // Example
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::UpdatePushRequest::new("foobar");
/// use elefren::requests::UpdatePushRequest;
/// let mut request = UpdatePushRequest::new("foobar");
/// request.favourite(true); /// request.favourite(true);
/// ``` /// ```
pub fn favourite(&mut self, favourite: bool) -> &mut Self { pub fn favourite(&mut self, favourite: bool) -> &mut Self {
@ -292,9 +261,8 @@ impl UpdatePushRequest {
/// A flag that indicates if you want reblog notifications pushed /// A flag that indicates if you want reblog notifications pushed
/// ///
/// # Example /// // Example
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::UpdatePushRequest; /// use elefren::requests::UpdatePushRequest;
/// let mut request = UpdatePushRequest::new("foobar"); /// let mut request = UpdatePushRequest::new("foobar");
/// request.reblog(true); /// request.reblog(true);
@ -306,9 +274,8 @@ impl UpdatePushRequest {
/// A flag that indicates if you want mention notifications pushed /// A flag that indicates if you want mention notifications pushed
/// ///
/// # Example /// // Example
/// ``` /// ```
/// # extern crate elefren;
/// use elefren::requests::UpdatePushRequest; /// use elefren::requests::UpdatePushRequest;
/// let mut request = UpdatePushRequest::new("foobar"); /// let mut request = UpdatePushRequest::new("foobar");
/// request.mention(true); /// request.mention(true);
@ -326,7 +293,7 @@ impl UpdatePushRequest {
} }
pub(crate) fn build(&self) -> update_data::Form { pub(crate) fn build(&self) -> update_data::Form {
use entities::push::{ use crate::entities::push::{
update_data::{Data, Form}, update_data::{Data, Form},
Alerts, Alerts,
}; };
@ -361,7 +328,7 @@ impl UpdatePushRequest {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use entities::push::{add_subscription, update_data, Alerts}; use crate::entities::push::{add_subscription, update_data, Alerts};
#[test] #[test]
fn test_keys_new() { fn test_keys_new() {

View File

@ -1,4 +1,5 @@
use errors::Error; use crate::errors::Error;
use serde::Serialize;
use serde_qs; use serde_qs;
use std::{borrow::Cow, convert::Into}; use std::{borrow::Cow, convert::Into};
@ -20,14 +21,13 @@ mod bool_qs_serialize {
/// Builder for making a client.statuses() call /// Builder for making a client.statuses() call
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// use elefren::requests::StatusesRequest;
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new(); /// let mut request = StatusesRequest::new();
/// request.only_media().pinned().since_id("foo"); /// request.only_media().pinned().since_id("foo");
/// # assert_eq!(&request.to_querystring().expect("Couldn't serialize qs")[..], "?only_media=1&pinned=1&since_id=foo"); /// assert_eq!(&request.to_querystring().expect("Couldn't serialize qs")[..], "?only_media=1&pinned=1&since_id=foo");
/// ``` /// ```
#[derive(Clone, Debug, Default, PartialEq, Serialize)] #[derive(Clone, Debug, Default, PartialEq, Serialize)]
pub struct StatusesRequest<'a> { pub struct StatusesRequest<'a> {
@ -66,27 +66,18 @@ impl<'a> Into<Option<StatusesRequest<'a>>> for &'a mut StatusesRequest<'a> {
impl<'a> StatusesRequest<'a> { impl<'a> StatusesRequest<'a> {
/// Construct a new `StatusesRequest` object /// Construct a new `StatusesRequest` object
///
/// # Example
///
/// ```
/// # extern crate elefren;
/// # use elefren::StatusesRequest;
/// let request = StatusesRequest::new();
/// ```
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
/// Set the `?only_media=1` flag for the .statuses() request /// Set the `?only_media=1` flag for the .statuses() request
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::StatusesRequest::new();
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new();
/// assert_eq!(&request.only_media().to_querystring().expect("Couldn't serialize qs"), "?only_media=1"); /// assert_eq!(&request.only_media().to_querystring().expect("Couldn't serialize qs"), "?only_media=1");
/// ```
pub fn only_media(&mut self) -> &mut Self { pub fn only_media(&mut self) -> &mut Self {
self.only_media = true; self.only_media = true;
self self
@ -94,12 +85,10 @@ impl<'a> StatusesRequest<'a> {
/// Set the `?exclude_replies=1` flag for the .statuses() request /// Set the `?exclude_replies=1` flag for the .statuses() request
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::StatusesRequest::new();
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new();
/// assert_eq!( /// assert_eq!(
/// &request /// &request
/// .exclude_replies() /// .exclude_replies()
@ -115,12 +104,10 @@ impl<'a> StatusesRequest<'a> {
/// Set the `?pinned=1` flag for the .statuses() request /// Set the `?pinned=1` flag for the .statuses() request
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::StatusesRequest::new();
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new();
/// assert_eq!( /// assert_eq!(
/// &request /// &request
/// .pinned() /// .pinned()
@ -136,12 +123,10 @@ impl<'a> StatusesRequest<'a> {
/// Set the `?max_id=:max_id` flag for the .statuses() request /// Set the `?max_id=:max_id` flag for the .statuses() request
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::StatusesRequest::new();
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new();
/// assert_eq!( /// assert_eq!(
/// &request /// &request
/// .max_id("foo") /// .max_id("foo")
@ -157,12 +142,10 @@ impl<'a> StatusesRequest<'a> {
/// Set the `?since_id=:since_id` flag for the .statuses() request /// Set the `?since_id=:since_id` flag for the .statuses() request
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::StatusesRequest::new();
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new();
/// assert_eq!( /// assert_eq!(
/// &request /// &request
/// .since_id("foo") /// .since_id("foo")
@ -178,12 +161,10 @@ impl<'a> StatusesRequest<'a> {
/// Set the `?limit=:limit` flag for the .statuses() request /// Set the `?limit=:limit` flag for the .statuses() request
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::StatusesRequest::new();
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new();
/// assert_eq!( /// assert_eq!(
/// &request /// &request
/// .limit(10) /// .limit(10)
@ -199,12 +180,10 @@ impl<'a> StatusesRequest<'a> {
/// Set the `?min_id=:min_id` flag for the .statuses() request /// Set the `?min_id=:min_id` flag for the .statuses() request
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::StatusesRequest::new();
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new();
/// assert_eq!( /// assert_eq!(
/// &request /// &request
/// .min_id("foobar") /// .min_id("foobar")
@ -220,12 +199,10 @@ impl<'a> StatusesRequest<'a> {
/// Turns this builder into a querystring /// Turns this builder into a querystring
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// let mut request = elefren::requests::StatusesRequest::new();
/// # use elefren::StatusesRequest;
/// let mut request = StatusesRequest::new();
/// assert_eq!( /// assert_eq!(
/// &request /// &request
/// .limit(10) /// .limit(10)

View File

@ -3,35 +3,26 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use entities::account::{Credentials, MetadataField, UpdateSource}; use crate::{
use errors::Result; entities::account::{Credentials, MetadataField, UpdateSource},
use status_builder; errors::Result,
status_builder,
};
/// Builder to pass to the Mastodon::update_credentials method /// Builder to pass to the Mastodon::update_credentials method
/// ///
/// # Example /// // Example
/// ///
/// ```no_run /// ```no_run
/// # extern crate elefren;
/// # use elefren::Data;
/// # fn main() -> Result<(), elefren::Error> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// use elefren::{prelude::*, status_builder::Visibility, UpdateCredsRequest}; /// use elefren::{prelude::*, status_builder::Visibility, UpdateCredsRequest};
/// ///
/// let data = Data::default();
/// let client = Mastodon::from(data); /// let client = Mastodon::from(data);
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
/// ///
/// builder.privacy(Visibility::Unlisted); /// builder.privacy(Visibility::Unlisted);
/// ///
/// let result = client.update_credentials(&mut builder)?; /// let result = client.update_credentials(&mut builder).unwrap();
/// # Ok(())
/// # }
/// ``` /// ```
#[derive(Debug, Default, Clone, PartialEq)] #[derive(Debug, Default, Clone, PartialEq)]
pub struct UpdateCredsRequest { pub struct UpdateCredsRequest {
@ -49,10 +40,10 @@ pub struct UpdateCredsRequest {
impl UpdateCredsRequest { impl UpdateCredsRequest {
/// Create a new UpdateCredsRequest /// Create a new UpdateCredsRequest
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// // extern crate elefren;
/// use elefren::UpdateCredsRequest; /// use elefren::UpdateCredsRequest;
/// ///
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
@ -63,10 +54,10 @@ impl UpdateCredsRequest {
/// Set the new display_name value /// Set the new display_name value
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// // extern crate elefren;
/// use elefren::UpdateCredsRequest; /// use elefren::UpdateCredsRequest;
/// ///
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
@ -80,10 +71,10 @@ impl UpdateCredsRequest {
/// Set the new note value /// Set the new note value
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// // extern crate elefren;
/// use elefren::UpdateCredsRequest; /// use elefren::UpdateCredsRequest;
/// ///
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
@ -97,10 +88,10 @@ impl UpdateCredsRequest {
/// Set the new avatar value /// Set the new avatar value
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// // extern crate elefren;
/// use elefren::UpdateCredsRequest; /// use elefren::UpdateCredsRequest;
/// ///
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
@ -116,10 +107,10 @@ impl UpdateCredsRequest {
/// Set the new header value /// Set the new header value
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// // extern crate elefren;
/// use elefren::UpdateCredsRequest; /// use elefren::UpdateCredsRequest;
/// ///
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
@ -135,10 +126,10 @@ impl UpdateCredsRequest {
/// Set the new privacy value /// Set the new privacy value
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// // extern crate elefren;
/// use elefren::{status_builder::Visibility, UpdateCredsRequest}; /// use elefren::{status_builder::Visibility, UpdateCredsRequest};
/// ///
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
@ -152,10 +143,10 @@ impl UpdateCredsRequest {
/// Set the new sensitive value /// Set the new sensitive value
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// // extern crate elefren;
/// use elefren::UpdateCredsRequest; /// use elefren::UpdateCredsRequest;
/// ///
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
@ -169,10 +160,10 @@ impl UpdateCredsRequest {
/// Add a metadata field /// Add a metadata field
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// // extern crate elefren;
/// use elefren::UpdateCredsRequest; /// use elefren::UpdateCredsRequest;
/// ///
/// let mut builder = UpdateCredsRequest::new(); /// let mut builder = UpdateCredsRequest::new();
@ -202,7 +193,7 @@ impl UpdateCredsRequest {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use entities::account::{Credentials, MetadataField, UpdateSource}; use crate::entities::account::{Credentials, MetadataField, UpdateSource};
use status_builder::Visibility; use status_builder::Visibility;
#[test] #[test]

View File

@ -8,13 +8,16 @@ use std::{
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use errors::Error; use crate::errors::Error;
use serde::{Deserialize, Deserializer}; use serde::{
use serde::de::{self, Visitor}; de::{self, Visitor},
Deserialize,
Deserializer,
};
/// Represents a set of OAuth scopes /// Represents a set of OAuth scopes
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// use elefren::prelude::*; /// use elefren::prelude::*;
@ -64,15 +67,18 @@ impl<'de> Visitor<'de> for DeserializeScopesVisitor {
} }
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: de::Error where
E: de::Error,
{ {
Scopes::from_str(v).map_err(de::Error::custom) Scopes::from_str(v).map_err(de::Error::custom)
} }
} }
impl<'de> Deserialize<'de> for Scopes { impl<'de> Deserialize<'de> for Scopes {
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error> where fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
D: Deserializer<'de> { where
D: Deserializer<'de>,
{
deserializer.deserialize_str(DeserializeScopesVisitor) deserializer.deserialize_str(DeserializeScopesVisitor)
} }
} }
@ -81,15 +87,10 @@ impl Scopes {
/// Represents all available oauth scopes: "read write follow push" /// Represents all available oauth scopes: "read write follow push"
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::scopes::Scopes; /// use elefren::scopes::Scopes;
/// ///
/// # fn main() -> Result<(), Box<Error>> {
/// let scope = Scopes::all(); /// let scope = Scopes::all();
/// assert_eq!(&format!("{}", scope), "read write follow push"); /// assert_eq!(&format!("{}", scope), "read write follow push");
/// # Ok(())
/// # }
/// ``` /// ```
pub fn all() -> Scopes { pub fn all() -> Scopes {
Scopes::read_all() | Scopes::write_all() | Scopes::follow() | Scopes::push() Scopes::read_all() | Scopes::write_all() | Scopes::follow() | Scopes::push()
@ -98,15 +99,10 @@ impl Scopes {
/// Represents the full "read" scope /// Represents the full "read" scope
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::scopes::Scopes; /// use elefren::scopes::Scopes;
/// ///
/// # fn main() -> Result<(), Box<Error>> {
/// let scope = Scopes::read_all(); /// let scope = Scopes::read_all();
/// assert_eq!(&format!("{}", scope), "read"); /// assert_eq!(&format!("{}", scope), "read");
/// # Ok(())
/// # }
/// ``` /// ```
pub fn read_all() -> Scopes { pub fn read_all() -> Scopes {
Scopes::_read(None) Scopes::_read(None)
@ -115,15 +111,10 @@ impl Scopes {
/// Represents a specific "read:___" scope /// Represents a specific "read:___" scope
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::scopes::{Read, Scopes}; /// use elefren::scopes::{Read, Scopes};
/// ///
/// # fn main() -> Result<(), Box<Error>> {
/// let scope = Scopes::read(Read::Accounts); /// let scope = Scopes::read(Read::Accounts);
/// assert_eq!(&format!("{}", scope), "read:accounts"); /// assert_eq!(&format!("{}", scope), "read:accounts");
/// # Ok(())
/// # }
/// ``` /// ```
pub fn read(subscope: Read) -> Scopes { pub fn read(subscope: Read) -> Scopes {
Scopes::_read(Some(subscope)) Scopes::_read(Some(subscope))
@ -132,15 +123,10 @@ impl Scopes {
/// Represents the full "write" scope /// Represents the full "write" scope
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::scopes::Scopes; /// use elefren::scopes::Scopes;
/// ///
/// # fn main() -> Result<(), Box<Error>> {
/// let scope = Scopes::write_all(); /// let scope = Scopes::write_all();
/// assert_eq!(&format!("{}", scope), "write"); /// assert_eq!(&format!("{}", scope), "write");
/// # Ok(())
/// # }
/// ``` /// ```
pub fn write_all() -> Scopes { pub fn write_all() -> Scopes {
Scopes::_write(None) Scopes::_write(None)
@ -149,15 +135,10 @@ impl Scopes {
/// Represents a specific "write:___" scope /// Represents a specific "write:___" scope
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::scopes::{Scopes, Write}; /// use elefren::scopes::{Scopes, Write};
/// ///
/// # fn main() -> Result<(), Box<Error>> {
/// let scope = Scopes::write(Write::Accounts); /// let scope = Scopes::write(Write::Accounts);
/// assert_eq!(&format!("{}", scope), "write:accounts"); /// assert_eq!(&format!("{}", scope), "write:accounts");
/// # Ok(())
/// # }
/// ``` /// ```
pub fn write(subscope: Write) -> Scopes { pub fn write(subscope: Write) -> Scopes {
Scopes::_write(Some(subscope)) Scopes::_write(Some(subscope))
@ -166,15 +147,10 @@ impl Scopes {
/// Represents the "follow" scope /// Represents the "follow" scope
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::scopes::Scopes; /// use elefren::scopes::Scopes;
/// ///
/// # fn main() -> Result<(), Box<Error>> {
/// let scope = Scopes::follow(); /// let scope = Scopes::follow();
/// assert_eq!(&format!("{}", scope), "follow"); /// assert_eq!(&format!("{}", scope), "follow");
/// # Ok(())
/// # }
/// ``` /// ```
pub fn follow() -> Scopes { pub fn follow() -> Scopes {
Scopes::new(Scope::Follow) Scopes::new(Scope::Follow)
@ -183,15 +159,10 @@ impl Scopes {
/// Represents the full "push" scope /// Represents the full "push" scope
/// ///
/// ``` /// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::scopes::Scopes; /// use elefren::scopes::Scopes;
/// ///
/// # fn main() -> Result<(), Box<Error>> {
/// let scope = Scopes::push(); /// let scope = Scopes::push();
/// assert_eq!(&format!("{}", scope), "push"); /// assert_eq!(&format!("{}", scope), "push");
/// # Ok(())
/// # }
/// ``` /// ```
pub fn push() -> Scopes { pub fn push() -> Scopes {
Scopes::new(Scope::Push) Scopes::new(Scope::Push)
@ -199,7 +170,7 @@ impl Scopes {
/// Combines 2 scopes together /// Combines 2 scopes together
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// use elefren::prelude::*; /// use elefren::prelude::*;
@ -764,7 +735,7 @@ mod tests {
let expected = format!("\"{}\"", b); let expected = format!("\"{}\"", b);
assert_eq!(&ser, &expected); assert_eq!(&ser, &expected);
let des : Scopes = serde_json::from_str(&ser).expect("Couldn't deserialize Scopes"); let des: Scopes = serde_json::from_str(&ser).expect("Couldn't deserialize Scopes");
assert_eq!(&des, a); assert_eq!(&des, a);
} }
} }

View File

@ -1,22 +1,19 @@
use isolang::Language; use isolang::Language;
use serde::{Deserialize, Serialize};
/// A builder pattern struct for constructing a status. /// A builder pattern struct for constructing a status.
/// ///
/// # Example /// // Example
/// ///
/// ``` /// ```
/// # extern crate elefren; /// use elefren::{Language, StatusBuilder};
/// # use elefren::{Language, StatusBuilder};
/// ///
/// # fn main() -> Result<(), elefren::Error> {
/// let status = StatusBuilder::new() /// let status = StatusBuilder::new()
/// .status("a status") /// .status("a status")
/// .sensitive(true) /// .sensitive(true)
/// .spoiler_text("a CW") /// .spoiler_text("a CW")
/// .language(Language::Eng) /// .language(Language::Eng)
/// .build()?; /// .build().unwrap();
/// # Ok(())
/// # }
/// ``` /// ```
#[derive(Debug, Default, Clone, PartialEq)] #[derive(Debug, Default, Clone, PartialEq)]
pub struct StatusBuilder { pub struct StatusBuilder {
@ -33,27 +30,19 @@ pub struct StatusBuilder {
impl StatusBuilder { impl StatusBuilder {
/// Create a StatusBuilder object /// Create a StatusBuilder object
/// ///
/// # Example /// // Example
/// ///
/// ```rust,no_run /// ```rust,no_run
/// # use elefren::prelude::*; /// use elefren::{status_builder::Visibility, prelude::*};
/// # use elefren::status_builder::Visibility; ///
/// # fn main() -> Result<(), elefren::Error> { /// let data = Data::default();
/// # let data = Data { /// let client = Mastodon::from(data);
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// # let client = Mastodon::from(data);
/// let status = StatusBuilder::new() /// let status = StatusBuilder::new()
/// .status("a status") /// .status("a status")
/// .visibility(Visibility::Public) /// .visibility(Visibility::Public)
/// .build()?; /// .build()
/// client.new_status(status)?; /// .unwrap();
/// # Ok(()) /// client.new_status(status).unwrap();
/// # }
/// ``` /// ```
pub fn new() -> StatusBuilder { pub fn new() -> StatusBuilder {
StatusBuilder::default() StatusBuilder::default()
@ -61,14 +50,11 @@ impl StatusBuilder {
/// Set the text for the post /// Set the text for the post
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// # use elefren::prelude::*; /// use elefren::prelude::*;
/// # fn main() -> Result<(), elefren::Error> { /// let status = StatusBuilder::new().status("awoooooo").build().unwrap();
/// let status = StatusBuilder::new().status("awoooooo").build()?;
/// # Ok(())
/// # }
/// ``` /// ```
pub fn status<I: Into<String>>(&mut self, status: I) -> &mut Self { pub fn status<I: Into<String>>(&mut self, status: I) -> &mut Self {
self.status = Some(status.into()); self.status = Some(status.into());
@ -77,17 +63,15 @@ impl StatusBuilder {
/// Set the in_reply_to_id for the post /// Set the in_reply_to_id for the post
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// # use elefren::prelude::*; /// use elefren::prelude::*;
/// # fn main() -> Result<(), elefren::Error> {
/// let status = StatusBuilder::new() /// let status = StatusBuilder::new()
/// .status("awooooo") /// .status("awooooo")
/// .in_reply_to("12345") /// .in_reply_to("12345")
/// .build()?; /// .build()
/// # Ok(()) /// .unwrap();
/// # }
/// ``` /// ```
pub fn in_reply_to<I: Into<String>>(&mut self, id: I) -> &mut Self { pub fn in_reply_to<I: Into<String>>(&mut self, id: I) -> &mut Self {
self.in_reply_to_id = Some(id.into()); self.in_reply_to_id = Some(id.into());
@ -96,14 +80,11 @@ impl StatusBuilder {
/// Set the media_ids for the post /// Set the media_ids for the post
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// # use elefren::prelude::*; /// use elefren::prelude::*;
/// # fn main() -> Result<(), elefren::Error> { /// let status = StatusBuilder::new().media_ids(&["foo", "bar"]).build().unwrap();
/// let status = StatusBuilder::new().media_ids(&["foo", "bar"]).build()?;
/// # Ok(())
/// # }
/// ``` /// ```
pub fn media_ids<S: std::fmt::Display, I: IntoIterator<Item = S>>( pub fn media_ids<S: std::fmt::Display, I: IntoIterator<Item = S>>(
&mut self, &mut self,
@ -115,36 +96,15 @@ impl StatusBuilder {
/// Set the sensitive attribute for the post /// Set the sensitive attribute for the post
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// # use elefren::prelude::*; /// use elefren::prelude::*;
/// # fn main() -> Result<(), elefren::Error> {
/// let status = StatusBuilder::new() /// let status = StatusBuilder::new()
/// .media_ids(&["foo", "bar"]) /// .media_ids(&["foo", "bar"])
/// .sensitive(true) /// .sensitive(true)
/// .build()?; /// .build()
/// # Ok(()) /// .unwrap();
/// # }
/// ```
pub fn sensitive(&mut self, sensitive: bool) -> &mut Self {
self.sensitive = Some(sensitive);
self
}
/// Set the spoiler text/CW for the post
///
/// # Example
///
/// ```rust
/// # use elefren::prelude::*;
/// # fn main() -> Result<(), elefren::Error> {
/// let status = StatusBuilder::new()
/// .status("awoooo!!")
/// .spoiler_text("awoo inside")
/// .build()?;
/// # Ok(())
/// # }
/// ``` /// ```
pub fn spoiler_text<I: Into<String>>(&mut self, spoiler_text: I) -> &mut Self { pub fn spoiler_text<I: Into<String>>(&mut self, spoiler_text: I) -> &mut Self {
self.spoiler_text = Some(spoiler_text.into()); self.spoiler_text = Some(spoiler_text.into());
@ -155,7 +115,7 @@ impl StatusBuilder {
/// ///
/// This is a Pleroma and Glitch-soc extension of the API. /// This is a Pleroma and Glitch-soc extension of the API.
/// ///
/// # Possible values /// // Possible values
/// - `text/plain` /// - `text/plain`
/// - `text/html` /// - `text/html`
/// - `text/markdown` /// - `text/markdown`
@ -163,17 +123,15 @@ impl StatusBuilder {
/// ///
/// The set of supported content types may vary by server. /// The set of supported content types may vary by server.
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// # use elefren::prelude::*; /// use elefren::prelude::*;
/// # fn main() -> Result<(), elefren::Error> {
/// let status = StatusBuilder::new() /// let status = StatusBuilder::new()
/// .status("<b>thicc</b>") /// .status("<b>thicc</b>")
/// .content_type("text/html") /// .content_type("text/html")
/// .build()?; /// .build()
/// # Ok(()) /// .unwrap();
/// # }
/// ``` /// ```
pub fn content_type<I: Into<String>>(&mut self, content_type: I) -> &mut Self { pub fn content_type<I: Into<String>>(&mut self, content_type: I) -> &mut Self {
self.content_type = Some(content_type.into()); self.content_type = Some(content_type.into());
@ -182,18 +140,15 @@ impl StatusBuilder {
/// Set the visibility for the post /// Set the visibility for the post
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// # use elefren::prelude::*; /// use elefren::{prelude::*, status_builder::Visibility};
/// # use elefren::status_builder::Visibility;
/// # fn main() -> Result<(), elefren::Error> {
/// let status = StatusBuilder::new() /// let status = StatusBuilder::new()
/// .status("awooooooo") /// .status("awooooooo")
/// .visibility(Visibility::Public) /// .visibility(Visibility::Public)
/// .build()?; /// .build()
/// # Ok(()) /// .unwrap();
/// # }
/// ``` /// ```
pub fn visibility(&mut self, visibility: Visibility) -> &mut Self { pub fn visibility(&mut self, visibility: Visibility) -> &mut Self {
self.visibility = Some(visibility); self.visibility = Some(visibility);
@ -202,34 +157,43 @@ impl StatusBuilder {
/// Set the language for the post /// Set the language for the post
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// # use elefren::prelude::*; /// use elefren::{Language, prelude::*};
/// # use elefren::Language;
/// # fn main() -> Result<(), elefren::Error> {
/// let status = StatusBuilder::new() /// let status = StatusBuilder::new()
/// .status("awoo!!!!") /// .status("awoo!!!!")
/// .language(Language::Eng) /// .language(Language::Eng)
/// .build()?; /// .build()
/// # Ok(()) /// .unwrap();
/// # }
/// ``` /// ```
pub fn language(&mut self, language: Language) -> &mut Self { pub fn language(&mut self, language: Language) -> &mut Self {
self.language = Some(language); self.language = Some(language);
self self
} }
/// Set the status as "sensitive".
/// ```
/// use elefren::StatusBuilder;
///
/// let status = StatusBuilder::new()
/// .status("a sensitive matter")
/// .sensitive(true)
/// .build()
/// .unwrap();
/// ```
pub fn sensitive(&mut self, flag: bool) -> &mut Self {
self.sensitive = Some(flag);
self
}
/// Constructs a NewStatus /// Constructs a NewStatus
/// ///
/// # Example /// // Example
/// ///
/// ```rust /// ```rust
/// # use elefren::prelude::*; /// use elefren::prelude::*;
/// # fn main() -> Result<(), elefren::Error> { /// let status = StatusBuilder::new().status("awoo!").build().unwrap();
/// let status = StatusBuilder::new().status("awoo!").build()?;
/// # Ok(())
/// # }
/// ``` /// ```
pub fn build(&self) -> Result<NewStatus, crate::Error> { pub fn build(&self) -> Result<NewStatus, crate::Error> {
if self.status.is_none() && self.media_ids.is_none() { if self.status.is_none() && self.media_ids.is_none() {