Merge pull request #3 from pwoolcoc/mastodon-client-trait

Adds a `MastodonClient` trait
master
Paul Woolcock 6 years ago committed by GitHub
commit ecb8629a53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  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; mod register;
use register::MastodonClient;
use std::error; use std::error;
fn main() -> Result<(), Box<error::Error>> { fn main() -> Result<(), Box<error::Error>> {

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

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

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

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

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

@ -9,7 +9,7 @@
//! # try().unwrap(); //! # try().unwrap();
//! # } //! # }
//! # fn try() -> mammut::Result<()> { //! # fn try() -> mammut::Result<()> {
//! use mammut::Registration; //! use mammut::{MastodonClient, Registration};
//! use mammut::apps::{AppBuilder, Scopes}; //! use mammut::apps::{AppBuilder, Scopes};
//! //!
//! let app = AppBuilder { //! let app = AppBuilder {
@ -98,7 +98,7 @@ macro_rules! paged_routes {
"Equivalent to `/api/v1/", "Equivalent to `/api/v1/",
$url, $url,
"`\n# Errors\nIf `access_token` is not set."), "`\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 url = self.route(concat!("/api/v1/", $url));
let response = self.client.$method(&url) let response = self.client.$method(&url)
.headers(self.headers.clone()) .headers(self.headers.clone())
@ -123,7 +123,7 @@ macro_rules! route {
"Equivalent to `/api/v1/", "Equivalent to `/api/v1/",
$url, $url,
"`\n# Errors\nIf `access_token` is not set."), "`\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; use reqwest::multipart::Form;
let form_data = Form::new() let form_data = Form::new()
@ -158,7 +158,7 @@ macro_rules! route {
$url, $url,
"`\n# Errors\nIf `access_token` is not set."), "`\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!({ let form_data = json!({
$( $(
@ -192,7 +192,7 @@ macro_rules! route {
"Equivalent to `/api/v1/", "Equivalent to `/api/v1/",
$url, $url,
"`\n# Errors\nIf `access_token` is not set."), "`\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))) self.$method(self.route(concat!("/api/v1/", $url)))
} }
} }
@ -212,7 +212,7 @@ macro_rules! route_id {
"Equivalent to `/api/v1/", "Equivalent to `/api/v1/",
$url, $url,
"`\n# Errors\nIf `access_token` is not set."), "`\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))) self.$method(self.route(&format!(concat!("/api/v1/", $url), id)))
} }
} }
@ -228,7 +228,7 @@ macro_rules! paged_routes_with_id {
"Equivalent to `/api/v1/", "Equivalent to `/api/v1/",
$url, $url,
"`\n# Errors\nIf `access_token` is not set."), "`\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 url = self.route(&format!(concat!("/api/v1/", $url), id));
let response = self.client.$method(&url) let response = self.client.$method(&url)
.headers(self.headers.clone()) .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 { impl Mastodon {
fn from_registration<I>(base: I, fn from_registration<I>(base: I,
client_id: 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! { paged_routes! {
(get) favourites: "favourites" => Status, (get) favourites: "favourites" => Status,
(get) blocks: "blocks" => Account, (get) blocks: "blocks" => Account,
@ -526,7 +588,7 @@ impl Mastodon {
(delete) delete_status: "statuses/{}" => Empty, (delete) delete_status: "statuses/{}" => Empty,
} }
pub fn update_credentials(&self, changes: CredientialsBuilder) fn update_credentials(&self, changes: CredientialsBuilder)
-> Result<Account> -> Result<Account>
{ {
@ -548,7 +610,7 @@ impl Mastodon {
} }
/// Post a new status to the account. /// 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")) let response = self.client.post(&self.route("/api/v1/statuses"))
.headers(self.headers.clone()) .headers(self.headers.clone())
@ -559,7 +621,7 @@ impl Mastodon {
} }
/// Get the federated timeline for the instance. /// 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"); let mut url = self.route("/api/v1/timelines/public");
if local { if local {
@ -571,7 +633,7 @@ impl Mastodon {
/// Get timeline filtered by a hashtag(eg. `#coffee`) either locally or /// Get timeline filtered by a hashtag(eg. `#coffee`) either locally or
/// federated. /// 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/"); let mut url = self.route("/api/v1/timelines/tag/");
url += &hashtag; url += &hashtag;
@ -589,7 +651,7 @@ impl Mastodon {
/// ///
/// ```no_run /// ```no_run
/// # extern crate mammut; /// # extern crate mammut;
/// # use mammut::{Data, Mastodon}; /// # use mammut::{Data, Mastodon, MastodonClient};
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> { /// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data { /// # let data = Data {
@ -607,7 +669,7 @@ impl Mastodon {
/// ///
/// ```no_run /// ```no_run
/// # extern crate mammut; /// # extern crate mammut;
/// # use mammut::{Data, Mastodon, StatusesRequest}; /// # use mammut::{Data, Mastodon, MastodonClient, StatusesRequest};
/// # use std::error::Error; /// # use std::error::Error;
/// # fn main() -> Result<(), Box<Error>> { /// # fn main() -> Result<(), Box<Error>> {
/// # let data = Data { /// # let data = Data {
@ -624,7 +686,7 @@ impl Mastodon {
/// # Ok(()) /// # 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>>> where S: Into<Option<StatusesRequest<'a>>>
{ {
let mut url = format!("{}/api/v1/accounts/{}/statuses", self.base, id); let mut url = format!("{}/api/v1/accounts/{}/statuses", self.base, id);
@ -642,7 +704,7 @@ impl Mastodon {
/// Returns the client account's relationship to a list of other accounts. /// Returns the client account's relationship to a list of other accounts.
/// Such as whether they follow them or vice versa. /// 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?"); let mut url = self.route("/api/v1/accounts/relationships?");
if ids.len() == 1 { if ids.len() == 1 {
@ -667,7 +729,7 @@ impl Mastodon {
/// Search for accounts by their name. /// Search for accounts by their name.
/// Will lookup an account remotely if the search term is in the /// Will lookup an account remotely if the search term is in the
/// `username@domain` format and not yet in the database. /// `username@domain` format and not yet in the database.
pub fn search_accounts(&self, fn search_accounts(&self,
query: &str, query: &str,
limit: Option<u64>, limit: Option<u64>,
following: bool) following: bool)
@ -685,14 +747,6 @@ impl Mastodon {
Page::new(self, response) 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 { impl ops::Deref for Mastodon {

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

Loading…
Cancel
Save