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
This commit is contained in:
@@ -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 {
|
||||
|
||||
+78
-24
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user