Adds a `MastodonClient` trait

This is useful for user code, which can use the trait to add a layer of
indirection to their code, allowing them to swap out implementations for
testing
master
Paul Woolcock 6 years ago
parent 6c37ecb1e1
commit 22b4b04738
  1. 1
      examples/follow_profile.rs
  2. 2
      examples/print_your_profile.rs
  3. 2
      examples/register.rs
  4. 1
      examples/search.rs
  5. 1
      examples/upload_photo.rs
  6. 2
      src/entities/itemsiter.rs
  7. 102
      src/lib.rs
  8. 2
      src/registration.rs

@ -1,5 +1,6 @@
mod register;
use register::MastodonClient;
use std::error;
fn main() -> Result<(), Box<error::Error>> {

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

@ -1,6 +1,8 @@
extern crate mammut;
extern crate toml;
pub use self::mammut::MastodonClient;
use std::{
error::Error,
fs,

@ -1,5 +1,6 @@
mod register;
use register::MastodonClient;
use std::error;
fn main() -> Result<(), Box<error::Error>> {

@ -1,5 +1,6 @@
mod register;
use register::MastodonClient;
use std::error;
fn main() -> Result<(), Box<error::Error>> {

@ -5,7 +5,7 @@ use serde::Deserialize;
///
/// ```no_run
/// # extern crate mammut;
/// # use mammut::{Data, Mastodon};
/// # use mammut::{Data, Mastodon, MastodonClient};
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {

@ -9,7 +9,7 @@
//! # try().unwrap();
//! # }
//! # fn try() -> mammut::Result<()> {
//! use mammut::Registration;
//! use mammut::{MastodonClient, Registration};
//! use mammut::apps::{AppBuilder, Scopes};
//!
//! let app = AppBuilder {
@ -98,7 +98,7 @@ macro_rules! paged_routes {
"Equivalent to `/api/v1/",
$url,
"`\n# Errors\nIf `access_token` is not set."),
pub fn $name(&self) -> Result<Page<$ret>> {
fn $name(&self) -> Result<Page<$ret>> {
let url = self.route(concat!("/api/v1/", $url));
let response = self.client.$method(&url)
.headers(self.headers.clone())
@ -123,7 +123,7 @@ macro_rules! route {
"Equivalent to `/api/v1/",
$url,
"`\n# Errors\nIf `access_token` is not set."),
pub fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
use reqwest::multipart::Form;
let form_data = Form::new()
@ -158,7 +158,7 @@ macro_rules! route {
$url,
"`\n# Errors\nIf `access_token` is not set."),
pub fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
let form_data = json!({
$(
@ -192,7 +192,7 @@ macro_rules! route {
"Equivalent to `/api/v1/",
$url,
"`\n# Errors\nIf `access_token` is not set."),
pub fn $name(&self) -> Result<$ret> {
fn $name(&self) -> Result<$ret> {
self.$method(self.route(concat!("/api/v1/", $url)))
}
}
@ -212,7 +212,7 @@ macro_rules! route_id {
"Equivalent to `/api/v1/",
$url,
"`\n# Errors\nIf `access_token` is not set."),
pub fn $name(&self, id: u64) -> Result<$ret> {
fn $name(&self, id: u64) -> Result<$ret> {
self.$method(self.route(&format!(concat!("/api/v1/", $url), id)))
}
}
@ -228,7 +228,7 @@ macro_rules! paged_routes_with_id {
"Equivalent to `/api/v1/",
$url,
"`\n# Errors\nIf `access_token` is not set."),
pub fn $name(&self, id: &str) -> Result<Page<$ret>> {
fn $name(&self, id: &str) -> Result<Page<$ret>> {
let url = self.route(&format!(concat!("/api/v1/", $url), id));
let response = self.client.$method(&url)
.headers(self.headers.clone())
@ -433,6 +433,57 @@ impl<'a> StatusesRequest<'a> {
}
}
#[allow(unused)]
pub trait MastodonClient {
fn favourites(&self) -> Result<Page<Status>> { unimplemented!("This method was not implemented"); }
fn blocks(&self) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn domain_blocks(&self) -> Result<Page<String>> { unimplemented!("This method was not implemented"); }
fn follow_requests(&self) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn get_home_timeline(&self) -> Result<Page<Status>> { unimplemented!("This method was not implemented"); }
fn get_emojis(&self) -> Result<Page<Emoji>> { unimplemented!("This method was not implemented"); }
fn mutes(&self) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn notifications(&self) -> Result<Page<Notification>> { unimplemented!("This method was not implemented"); }
fn reports(&self) -> Result<Page<Report>> { unimplemented!("This method was not implemented"); }
fn followers(&self, id: &str) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
fn following(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn reblogged_by(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn favourited_by(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn unblock_domain(&self, domain: String) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn instance(&self) -> Result<Instance> { unimplemented!("This method was not implemented"); }
fn verify_credentials(&self) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn report(&self, account_id: &str, status_ids: Vec<&str>, comment: String) -> Result<Report> { unimplemented!("This method was not implemented"); }
fn block_domain(&self, domain: String) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn authorize_follow_request(&self, id: &str) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn reject_follow_request(&self, id: &str) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn search(&self, q: String, resolve: bool) -> Result<SearchResult> { unimplemented!("This method was not implemented"); }
fn follows(&self, uri: Cow<'static, str>) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn media(&self, file: Cow<'static, str>) -> Result<Attachment> { unimplemented!("This method was not implemented"); }
fn clear_notifications(&self) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn get_account(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn follow(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn unfollow(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn block(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn unblock(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn mute(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn unmute(&self, id: u64) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn get_notification(&self, id: u64) -> Result<Notification> { unimplemented!("This method was not implemented"); }
fn get_status(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn get_context(&self, id: u64) -> Result<Context> { unimplemented!("This method was not implemented"); }
fn get_card(&self, id: u64) -> Result<Card> { unimplemented!("This method was not implemented"); }
fn reblog(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn unreblog(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn favourite(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn unfavourite(&self, id: u64) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn delete_status(&self, id: u64) -> Result<Empty> { unimplemented!("This method was not implemented"); }
fn update_credentials(&self, changes: CredientialsBuilder) -> Result<Account> { unimplemented!("This method was not implemented"); }
fn new_status(&self, status: StatusBuilder) -> Result<Status> { unimplemented!("This method was not implemented"); }
fn get_public_timeline(&self, local: bool) -> Result<Vec<Status>> { unimplemented!("This method was not implemented"); }
fn get_tagged_timeline(&self, hashtag: String, local: bool) -> Result<Vec<Status>> { unimplemented!("This method was not implemented"); }
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>> where S: Into<Option<StatusesRequest<'a>>> { unimplemented!("This method was not implemented"); }
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> { unimplemented!("This method was not implemented"); }
fn search_accounts(&self, query: &str, limit: Option<u64>, following: bool) -> Result<Page<Account>> { unimplemented!("This method was not implemented"); }
}
impl Mastodon {
fn from_registration<I>(base: I,
client_id: I,
@ -474,6 +525,17 @@ impl Mastodon {
}
}
methods![get, post, delete,];
fn route(&self, url: &str) -> String {
let mut s = (*self.base).to_owned();
s += url;
s
}
}
impl MastodonClient for Mastodon {
paged_routes! {
(get) favourites: "favourites" => Status,
(get) blocks: "blocks" => Account,
@ -526,7 +588,7 @@ impl Mastodon {
(delete) delete_status: "statuses/{}" => Empty,
}
pub fn update_credentials(&self, changes: CredientialsBuilder)
fn update_credentials(&self, changes: CredientialsBuilder)
-> Result<Account>
{
@ -548,7 +610,7 @@ impl Mastodon {
}
/// Post a new status to the account.
pub fn new_status(&self, status: StatusBuilder) -> Result<Status> {
fn new_status(&self, status: StatusBuilder) -> Result<Status> {
let response = self.client.post(&self.route("/api/v1/statuses"))
.headers(self.headers.clone())
@ -559,7 +621,7 @@ impl Mastodon {
}
/// Get the federated timeline for the instance.
pub fn get_public_timeline(&self, local: bool) -> Result<Vec<Status>> {
fn get_public_timeline(&self, local: bool) -> Result<Vec<Status>> {
let mut url = self.route("/api/v1/timelines/public");
if local {
@ -571,7 +633,7 @@ impl Mastodon {
/// Get timeline filtered by a hashtag(eg. `#coffee`) either locally or
/// federated.
pub fn get_tagged_timeline(&self, hashtag: String, local: bool) -> Result<Vec<Status>> {
fn get_tagged_timeline(&self, hashtag: String, local: bool) -> Result<Vec<Status>> {
let mut url = self.route("/api/v1/timelines/tag/");
url += &hashtag;
@ -589,7 +651,7 @@ impl Mastodon {
///
/// ```no_run
/// # extern crate mammut;
/// # use mammut::{Data, Mastodon};
/// # use mammut::{Data, Mastodon, MastodonClient};
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
@ -607,7 +669,7 @@ impl Mastodon {
///
/// ```no_run
/// # extern crate mammut;
/// # use mammut::{Data, Mastodon, StatusesRequest};
/// # use mammut::{Data, Mastodon, MastodonClient, StatusesRequest};
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data {
@ -624,7 +686,7 @@ impl Mastodon {
/// # Ok(())
/// # }
/// ```
pub fn statuses<'a, S>(&self, id: &str, request: S) -> Result<Page<Status>>
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
where S: Into<Option<StatusesRequest<'a>>>
{
let mut url = format!("{}/api/v1/accounts/{}/statuses", self.base, id);
@ -642,7 +704,7 @@ impl Mastodon {
/// Returns the client account's relationship to a list of other accounts.
/// Such as whether they follow them or vice versa.
pub fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> {
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> {
let mut url = self.route("/api/v1/accounts/relationships?");
if ids.len() == 1 {
@ -667,7 +729,7 @@ impl Mastodon {
/// Search for accounts by their name.
/// Will lookup an account remotely if the search term is in the
/// `username@domain` format and not yet in the database.
pub fn search_accounts(&self,
fn search_accounts(&self,
query: &str,
limit: Option<u64>,
following: bool)
@ -685,14 +747,6 @@ impl Mastodon {
Page::new(self, response)
}
methods![get, post, delete,];
fn route(&self, url: &str) -> String {
let mut s = (*self.base).to_owned();
s += url;
s
}
}
impl ops::Deref for Mastodon {

@ -52,7 +52,7 @@ impl Registration {
/// # try().unwrap();
/// # }
/// # fn try() -> mammut::Result<()> {
/// use mammut::Registration;
/// use mammut::{MastodonClient, Registration};
/// use mammut::apps::{AppBuilder, Scopes};
///
/// let app = AppBuilder {

Loading…
Cancel
Save