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_SECRET=''
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))
* **helpers:** cli::authenticate ([034bd4e6](034bd4e6))
* **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))
* **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:** Implement Keyword filtering API ([7d164cb8](7d164cb8), closes [#71](71))
* **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
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.
In future releases, this will become a hard error.

View File

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

View File

@ -11,7 +11,7 @@
[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
@ -33,7 +33,6 @@ elefren = { version = "0.22", features = ["toml"] }
```rust,no_run
// src/main.rs
extern crate elefren;
use std::error::Error;
@ -56,7 +55,7 @@ fn main() -> Result<(), 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")
.build()?;
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):
```no_run
```rust,no_run
use elefren::prelude::*;
use elefren::entities::event::Event;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
//! A module about contexts of statuses.
use serde::Deserialize;
use super::status::Status;
/// 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)]
/// Events that come from the /streaming/user API call

View File

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

View File

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

View File

@ -1,28 +1,16 @@
use http_send::HttpSend;
use page::Page;
use crate::{http_send::HttpSend, page::Page};
use serde::Deserialize;
/// Abstracts away the `next_page` logic into a single stream of items
///
/// ```no_run
/// # extern crate elefren;
/// # use elefren::prelude::*;
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// use elefren::prelude::*;
/// let data = Data::default();
/// 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() {
/// // do something with `status`
/// }
/// # Ok(())
/// # }
/// ```
#[derive(Debug, Clone)]
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
#[derive(Clone, Debug, Deserialize, PartialEq)]
pub struct List {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
//! Module containing all info relating to a status.
use super::prelude::*;
use crate::{entities::card::Card, status_builder::Visibility};
use chrono::prelude::*;
use entities::card::Card;
use status_builder::Visibility;
use serde::Deserialize;
/// A status from the instance.
#[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 hyper_old_types::Error as HeaderParseError;
use reqwest::{header::ToStrError as HeaderStrError, Error as HttpError, StatusCode};
use serde::Deserialize;
use serde_json::Error as SerdeError;
use serde_qs::Error as SerdeQsError;
use serde_urlencoded::ser::Error as UrlEncodedError;
@ -11,8 +12,8 @@ use serde_urlencoded::ser::Error as UrlEncodedError;
use tomlcrate::de::Error as TomlDeError;
#[cfg(feature = "toml")]
use tomlcrate::ser::Error as TomlSerError;
use url::ParseError as UrlError;
use tungstenite::error::Error as WebSocketError;
use url::ParseError as UrlError;
/// Convience type over `std::result::Result` with `Error` as the error type.
pub type Result<T> = ::std::result::Result<T, Error>;
@ -93,9 +94,7 @@ impl error::Error for Error {
Error::SerdeQs(ref e) => e,
Error::WebSocket(ref e) => e,
Error::Client(..) | Error::Server(..) => {
return None
},
Error::Client(..) | Error::Server(..) => return None,
Error::ClientIdRequired => return None,
Error::ClientSecretRequired => return None,
Error::AccessTokenRequired => return None,
@ -167,9 +166,6 @@ macro_rules! format_err {
#[cfg(test)]
mod tests {
use super::*;
use reqwest;
use serde_json;
use serde_urlencoded;
use std::io;
macro_rules! assert_is {

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
use crate::Result;
use reqwest::{Client, Request, RequestBuilder, Response};
use std::fmt::Debug;
use Result;
/// Abstracts away the process of turning an HTTP request into an HTTP response
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/)
//!
//! ```no_run
//! # extern crate elefren;
//! # fn main() {
//! # try().unwrap();
//! # }
//! # fn try() -> elefren::Result<()> {
//! use elefren::{helpers::cli, prelude::*};
//!
//! let registration = Registration::new("https://mastodon.social")
//! let registration = Registration::new("https://botsin.space")
//! .client_name("elefren_test")
//! .build()?;
//! let mastodon = cli::authenticate(registration)?;
//! .build()
//! .unwrap();
//! let mastodon = cli::authenticate(registration).unwrap();
//!
//! println!(
//! "{:?}",
//! mastodon
//! .get_home_timeline()?
//! .get_home_timeline()
//! .unwrap()
//! .items_iter()
//! .take(100)
//! .collect::<Vec<_>>()
//! );
//! # Ok(())
//! # }
//! ```
//!
//! Elefren also supports Mastodon's Streaming API:
//!
//! # Example
//! // Example
//!
//! ```no_run
//! # extern crate elefren;
//! # use elefren::prelude::*;
//! # 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(),
//! # };
//! use elefren::{prelude::*, entities::event::Event};
//! let data = Data::default();
//! let client = Mastodon::from(data);
//! for event in client.streaming_user()? {
//! for event in client.streaming_user().unwrap() {
//! match event {
//! Event::Update(ref status) => { /* .. */ },
//! Event::Notification(ref notification) => { /* .. */ },
@ -53,8 +38,6 @@
//! Event::FiltersChanged => { /* .. */ },
//! }
//! }
//! # Ok(())
//! # }
//! ```
#![deny(
@ -73,8 +56,6 @@
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate doc_comment;
extern crate hyper_old_types;
extern crate isolang;
@ -82,11 +63,11 @@ extern crate isolang;
extern crate serde_json;
extern crate chrono;
extern crate reqwest;
#[macro_use]
extern crate serde;
extern crate serde_qs;
extern crate serde_urlencoded;
extern crate tap_reader;
extern crate try_from;
extern crate tungstenite;
extern crate url;
@ -154,14 +135,16 @@ pub mod status_builder;
mod macros;
/// Automatically import the things you need
pub mod prelude {
pub use scopes::Scopes;
pub use Data;
pub use Mastodon;
pub use MastodonClient;
pub use NewStatus;
pub use Registration;
pub use StatusBuilder;
pub use StatusesRequest;
pub use crate::{
scopes::Scopes,
Data,
Mastodon,
MastodonClient,
NewStatus,
Registration,
StatusBuilder,
StatusesRequest,
};
}
/// 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
/// and or excluding replies.
///
/// # Example
/// // Example
///
/// ```no_run
/// # extern crate elefren;
/// # use elefren::prelude::*;
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// use elefren::prelude::*;
/// let data = Data::default();
/// let client = Mastodon::from(data);
/// let statuses = client.statuses("user-id", None)?;
/// # Ok(())
/// # }
/// let statuses = client.statuses("user-id", None).unwrap();
/// ```
///
/// ```no_run
/// # extern crate elefren;
/// # use elefren::prelude::*;
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// use elefren::prelude::*;
/// let data = Data::default();
/// let client = Mastodon::from(data);
/// let mut request = StatusesRequest::new();
/// request.only_media();
/// let statuses = client.statuses("user-id", request)?;
/// # Ok(())
/// # }
/// let statuses = client.statuses("user-id", request).unwrap();
/// ```
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status, H>>
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
/// timeline & notifications
///
/// # Example
/// // Example
///
/// ```no_run
/// # extern crate elefren;
/// # use elefren::prelude::*;
/// # use std::error::Error;
/// use elefren::prelude::*;
/// 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 data = Data::default();
/// let client = Mastodon::from(data);
/// for event in client.streaming_user()? {
/// for event in client.streaming_user().unwrap() {
/// match event {
/// Event::Update(ref status) => { /* .. */ },
/// Event::Notification(ref notification) => { /* .. */ },
@ -484,8 +436,6 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
/// Event::FiltersChanged => { /* .. */ },
/// }
/// }
/// # Ok(())
/// # }
/// ```
fn streaming_user(&self) -> Result<Self::Stream> {
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",
"```no_run",
"# extern crate elefren;\n",
"# use elefren::prelude::*;\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",
"use elefren::prelude::*;\n",
"let data = Data::default();\n",
"let client = Mastodon::from(data);\n",
"client.", stringify!($name), "();\n",
"# Ok(())\n",
"# }\n",
"```"
),
fn $name(&self) -> Result<Page<$ret, H>> {
@ -259,20 +249,10 @@ macro_rules! route {
"`\n# Errors\nIf `access_token` is not set.",
"\n",
"```no_run",
"# extern crate elefren;\n",
"# use elefren::prelude::*;\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",
"use elefren::prelude::*;\n",
"let data = Data::default();\n",
"let client = Mastodon::from(data);\n",
"client.", stringify!($name), "();\n",
"# Ok(())\n",
"# }\n",
"```"
),
fn $name(&self) -> Result<$ret> {
@ -297,16 +277,8 @@ macro_rules! route_id {
"`\n# Errors\nIf `access_token` is not set.",
"\n",
"```no_run",
"# extern crate elefren;\n",
"# use elefren::prelude::*;\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",
"use elefren::prelude::*;\n",
"let data = Data::default();\n",
"let client = Mastodon::from(data);\n",
"client.", stringify!($name), "(\"42\");\n",
"# Ok(())\n",
@ -331,20 +303,10 @@ macro_rules! paged_routes_with_id {
"`\n# Errors\nIf `access_token` is not set.",
"\n",
"```no_run",
"# extern crate elefren;\n",
"# use elefren::prelude::*;\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",
"use elefren::prelude::*;\n",
"let data = Data::default();",
"let client = Mastodon::from(data);\n",
"client.", stringify!($name), "(\"some-id\");\n",
"# Ok(())\n",
"# }\n",
"```"
),
fn $name(&self, id: &str) -> Result<Page<$ret, H>> {

View File

@ -1,17 +1,19 @@
use std::borrow::Cow;
use entities::prelude::*;
use errors::Result;
use http_send::{HttpSend, HttpSender};
use page::Page;
use requests::{
AddFilterRequest,
AddPushRequest,
StatusesRequest,
UpdateCredsRequest,
UpdatePushRequest,
use crate::{
entities::prelude::*,
errors::Result,
http_send::{HttpSend, HttpSender},
page::Page,
requests::{
AddFilterRequest,
AddPushRequest,
StatusesRequest,
UpdateCredsRequest,
UpdatePushRequest,
},
status_builder::NewStatus,
};
use status_builder::NewStatus;
/// Represents the set of methods that a Mastodon Client can do, so that
/// 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()`
///
/// ```no_run
/// # extern crate elefren;
/// # use std::error::Error;
/// # use elefren::prelude::*;
/// # 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 follows_me = client.follows_me()?;
/// # Ok(())
/// # }
/// use elefren::prelude::*;
/// let data = Data::default();
/// let client = Mastodon::from(data);
/// let follows_me = client.follows_me().unwrap();
/// ```
fn follows_me(&self) -> Result<Page<Account, H>> {
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)`
///
/// ```no_run
/// # extern crate elefren;
/// # use std::error::Error;
/// # use elefren::prelude::*;
/// # 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 follows_me = client.followed_by_me()?;
/// # Ok(())
/// # }
/// use elefren::prelude::*;
/// let data = Data::default();
/// let client = Mastodon::from(data);
/// let follows_me = client.followed_by_me().unwrap();
/// ```
fn followed_by_me(&self) -> Result<Page<Account, H>> {
unimplemented!("This method was not implemented");
}

View File

@ -1,11 +1,11 @@
use super::{deserialise, Mastodon, Result};
use entities::itemsiter::ItemsIter;
use crate::entities::itemsiter::ItemsIter;
use hyper_old_types::header::{parsing, Link, RelationType};
use reqwest::{header::LINK, Response};
use serde::Deserialize;
use url::Url;
use http_send::HttpSend;
use crate::http_send::HttpSend;
macro_rules! pages {
($($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
/// easily stored for later use
///
/// # Example
/// // Example
///
/// ```no_run
/// # extern crate elefren;
/// # use elefren::Mastodon;
/// # use elefren::page::OwnedPage;
/// # 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(),
/// # };
/// use elefren::{
/// prelude::*,
/// page::OwnedPage,
/// http_send::HttpSender,
/// entities::status::Status
/// };
/// use std::cell::RefCell;
///
/// let data = Data::default();
/// struct HomeTimeline {
/// client: Mastodon,
/// page: RefCell<Option<OwnedPage<Status, HttpSender>>>,
/// }
/// 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 {
/// client,
/// page: RefCell::new(Some(home)),
/// };
/// # Ok(())
/// # }
/// ```
#[derive(Debug, Clone)]
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
/// that created it
///
/// # Example
/// // Example
///
/// ```no_run
/// # extern crate elefren;
/// # use elefren::Mastodon;
/// # use elefren::page::OwnedPage;
/// # 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(),
/// # };
/// use elefren::{Mastodon, page::OwnedPage, http_send::HttpSender, entities::status::Status, prelude::*};
/// use std::cell::RefCell;
/// let data = Data::default();
/// struct HomeTimeline {
/// client: Mastodon,
/// page: RefCell<Option<OwnedPage<Status, HttpSender>>>,
/// }
/// 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 {
/// client,
/// page: RefCell::new(Some(home)),
/// };
/// # Ok(())
/// # }
/// ```
pub fn to_owned(self) -> OwnedPage<T, H> {
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
/// there are no more items.
///
/// # Example
/// // Example
///
/// ```no_run
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::prelude::*;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
/// # base: "".into(),
/// # client_id: "".into(),
/// # client_secret: "".into(),
/// # redirect: "".into(),
/// # token: "".into(),
/// # };
/// let data = Data::default();
/// let mastodon = Mastodon::from(data);
/// 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() {
/// // do something with status
/// }
/// # Ok(())
/// # }
/// ```
pub fn items_iter(self) -> impl Iterator<Item = T> + 'a
where

View File

@ -1,17 +1,18 @@
use std::borrow::Cow;
use reqwest::{Client, RequestBuilder, Response};
use try_from::TryInto;
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
use apps::{App, AppBuilder};
use http_send::{HttpSend, HttpSender};
use scopes::Scopes;
use Data;
use Error;
use Mastodon;
use MastodonBuilder;
use Result;
use crate::{
apps::{App, AppBuilder},
http_send::{HttpSend, HttpSender},
scopes::Scopes,
Data,
Error,
Mastodon,
MastodonBuilder,
Result,
};
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::*;
///
/// let registration = Registration::new("https://mastodon.social");
/// let registration = Registration::new("https://botsin.space");
/// ```
pub fn new<I: Into<String>>(base: I) -> Self {
Registration {
@ -116,27 +117,23 @@ impl<'a, H: HttpSend> Registration<'a, H> {
/// Register the given application
///
/// ```no_run
/// # extern crate elefren;
/// # fn main () -> elefren::Result<()> {
/// use elefren::{apps::App, prelude::*};
///
/// let mut app = App::builder();
/// app.client_name("elefren_test");
///
/// let registration = Registration::new("https://mastodon.social").register(app)?;
/// let url = registration.authorize_url()?;
/// let registration = Registration::new("https://botsin.space").register(app).unwrap();
/// let url = registration.authorize_url().unwrap();
/// // Here you now need to open the url in the browser
/// // And handle a the redirect url coming back with the code.
/// 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);
/// # Ok(())
/// # }
/// println!("{:?}", mastodon.get_home_timeline().unwrap().initial_items);
/// ```
pub fn register<I: TryInto<App>>(&mut self, app: I) -> Result<Registered<H>>
where
Error: From<<I as TryInto<App>>::Err>,
Error: From<<I as TryInto<App>>::Error>,
{
let app = app.try_into()?;
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.
///
/// ```no_run
/// # extern crate elefren;
/// # fn main () -> elefren::Result<()> {
/// use elefren::prelude::*;
///
/// let registration = Registration::new("https://mastodon.social")
/// let registration = Registration::new("https://botsin.space")
/// .client_name("elefren_test")
/// .build()?;
/// let url = registration.authorize_url()?;
/// .build().unwrap();
/// let url = registration.authorize_url().unwrap();
/// // Here you now need to open the url in the browser
/// // And handle a the redirect url coming back with the code.
/// 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);
/// # Ok(())
/// # }
/// println!("{:?}", mastodon.get_home_timeline().unwrap().initial_items);
/// ```
pub fn build(&mut self) -> Result<Registered<H>> {
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
/// creating a `Registered` struct directly
///
/// # Example
/// // Example
///
/// ```no_run
/// # extern crate elefren;
/// # fn main() -> elefren::Result<()> {
/// use elefren::{prelude::*, registration::Registered};
///
/// let registration = Registered::from_parts(
@ -214,15 +205,13 @@ impl Registered<HttpSender> {
/// Scopes::read_all(),
/// false,
/// );
/// let url = registration.authorize_url()?;
/// let url = registration.authorize_url().unwrap();
/// // Here you now need to open the url in the browser
/// // And handle a the redirect url coming back with the code.
/// 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);
/// # Ok(())
/// # }
/// println!("{:?}", mastodon.get_home_timeline().unwrap().initial_items);
/// ```
pub fn from_parts(
base: &str,
@ -253,39 +242,35 @@ impl<H: HttpSend> Registered<H> {
/// Returns the parts of the `Registered` struct that can be used to
/// recreate another `Registered` struct
///
/// # Example
/// // Example
///
/// ```
/// # extern crate elefren;
/// use elefren::{prelude::*, registration::Registered};
/// # fn main() -> Result<(), Box<std::error::Error>> {
///
/// let origbase = "https://example.social";
/// let origclient_id = "some-client_id";
/// let origclient_secret = "some-client-secret";
/// let origredirect = "https://example.social/redirect";
/// let origscopes = Scopes::all();
/// let origforce_login = false;
/// let orig_base = "https://example.social";
/// let orig_client_id = "some-client_id";
/// let orig_client_secret = "some-client-secret";
/// let orig_redirect = "https://example.social/redirect";
/// let orig_scopes = Scopes::all();
/// let orig_force_login = false;
///
/// let registered = Registered::from_parts(
/// origbase,
/// origclient_id,
/// origclient_secret,
/// origredirect,
/// origscopes.clone(),
/// origforce_login,
/// orig_base,
/// orig_client_id,
/// orig_client_secret,
/// orig_redirect,
/// orig_scopes.clone(),
/// orig_force_login,
/// );
///
/// let (base, client_id, client_secret, redirect, scopes, force_login) = registered.into_parts();
///
/// assert_eq!(origbase, &base);
/// assert_eq!(origclient_id, &client_id);
/// assert_eq!(origclient_secret, &client_secret);
/// assert_eq!(origredirect, &redirect);
/// assert_eq!(origscopes, scopes);
/// assert_eq!(origforce_login, force_login);
/// # Ok(())
/// # }
/// assert_eq!(orig_base, &base);
/// assert_eq!(orig_client_id, &client_id);
/// assert_eq!(orig_client_secret, &client_secret);
/// assert_eq!(orig_redirect, &redirect);
/// assert_eq!(orig_scopes, scopes);
/// assert_eq!(orig_force_login, force_login);
/// ```
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.
pub fn authorize_url(&self) -> Result<String> {
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
/// provided by the authorisation url.
/// provided by the authorization url.
pub fn complete(&self, code: &str) -> Result<Mastodon<H>> {
let url = format!(
"{}/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;
/// Form used to create a filter
///
/// # Example
/// // Example
///
/// ```
/// # extern crate elefren;
/// # use std::error::Error;
/// use elefren::{entities::filter::FilterContext, requests::AddFilterRequest};
/// # fn main() -> Result<(), Box<Error>> {
/// let request = AddFilterRequest::new("foo", FilterContext::Home);
/// # Ok(())
/// # }
/// ```
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct AddFilterRequest {

View File

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

View File

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

View File

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

View File

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

View File

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