forked from MightyPork/elefren-fork
Remove HttpSend and HttpSender
this was maybe a good idea, but it isn't really needed
This commit is contained in:
@@ -76,7 +76,7 @@ use elefren::entities::event::Event;
|
||||
|
||||
use std::error::Error;
|
||||
|
||||
fn main() -> Result<(), Box<Error>> {
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let data = Data {
|
||||
base: "".into(),
|
||||
client_id: "".into(),
|
||||
|
||||
+2
-2
@@ -61,7 +61,7 @@ impl App {
|
||||
/// use elefren::apps::App;
|
||||
/// use std::error::Error;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let mut builder = App::builder();
|
||||
/// builder.client_name("elefren_test");
|
||||
/// let app = builder.build()?;
|
||||
@@ -120,7 +120,7 @@ impl<'a> AppBuilder<'a> {
|
||||
Ok(App {
|
||||
client_name: self
|
||||
.client_name
|
||||
.ok_or_else(|| Error::MissingField("client_name"))?
|
||||
.ok_or(Error::MissingField("client_name"))?
|
||||
.into(),
|
||||
redirect_uris: self
|
||||
.redirect_uris
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{http_send::HttpSend, page::Page};
|
||||
use crate::page::Page;
|
||||
use serde::Deserialize;
|
||||
|
||||
/// Abstracts away the `next_page` logic into a single stream of items
|
||||
@@ -7,7 +7,7 @@ use serde::Deserialize;
|
||||
/// # extern crate elefren;
|
||||
/// # use elefren::prelude::*;
|
||||
/// # use std::error::Error;
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// # let data = Data {
|
||||
/// # base: "".into(),
|
||||
/// # client_id: "".into(),
|
||||
@@ -24,15 +24,15 @@ use serde::Deserialize;
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>, H: 'a + HttpSend> {
|
||||
page: Page<'a, T, H>,
|
||||
pub(crate) struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>> {
|
||||
page: Page<'a, T>,
|
||||
buffer: Vec<T>,
|
||||
cur_idx: usize,
|
||||
use_initial: bool,
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> ItemsIter<'a, T, H> {
|
||||
pub(crate) fn new(page: Page<'a, T, H>) -> ItemsIter<'a, T, H> {
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
|
||||
pub(crate) fn new(page: Page<'a, T>) -> ItemsIter<'a, T> {
|
||||
ItemsIter {
|
||||
page,
|
||||
buffer: vec![],
|
||||
@@ -64,7 +64,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> ItemsIter<'a, T, H>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Iterator for ItemsIter<'a, T, H> {
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>> Iterator for ItemsIter<'a, T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
use std::io::{self, BufRead, Write};
|
||||
|
||||
use crate::{errors::Result, http_send::HttpSend, registration::Registered, Mastodon};
|
||||
use crate::{errors::Result, registration::Registered, Mastodon};
|
||||
|
||||
/// Finishes the authentication process for the given `Registered` object,
|
||||
/// using the command-line
|
||||
pub fn authenticate<H: HttpSend>(registration: Registered<H>) -> Result<Mastodon<H>> {
|
||||
pub fn authenticate(registration: Registered) -> Result<Mastodon> {
|
||||
let url = registration.authorize_url()?;
|
||||
|
||||
let stdout = io::stdout();
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
use crate::Result;
|
||||
use reqwest::{Client, Request, RequestBuilder, Response};
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Abstracts away the process of turning an HTTP request into an HTTP response
|
||||
pub trait HttpSend: Clone + Debug {
|
||||
/// Converts an HTTP request into an HTTP response
|
||||
fn execute(&self, client: &Client, request: Request) -> Result<Response>;
|
||||
|
||||
/// Convenience method so that .build() doesn't have to be called at every
|
||||
/// call site
|
||||
fn send(&self, client: &Client, builder: RequestBuilder) -> Result<Response> {
|
||||
let request = builder.build()?;
|
||||
self.execute(client, request)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct HttpSender;
|
||||
|
||||
impl HttpSend for HttpSender {
|
||||
fn execute(&self, client: &Client, request: Request) -> Result<Response> {
|
||||
Ok(client.execute(request)?)
|
||||
}
|
||||
}
|
||||
+30
-42
@@ -36,7 +36,7 @@
|
||||
//! # use elefren::prelude::*;
|
||||
//! # use std::error::Error;
|
||||
//! use elefren::entities::event::Event;
|
||||
//! # fn main() -> Result<(), Box<Error>> {
|
||||
//! # fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! # let data = Data {
|
||||
//! # base: "".into(),
|
||||
//! # client_id: "".into(),
|
||||
@@ -77,11 +77,7 @@ use reqwest::{Client, RequestBuilder, Response};
|
||||
use tap_reader::Tap;
|
||||
use tungstenite::client::AutoStream;
|
||||
|
||||
use crate::{
|
||||
entities::prelude::*,
|
||||
http_send::{HttpSend, HttpSender},
|
||||
page::Page,
|
||||
};
|
||||
use crate::{entities::prelude::*, page::Page};
|
||||
|
||||
pub use crate::{
|
||||
data::Data,
|
||||
@@ -110,8 +106,6 @@ pub mod entities;
|
||||
pub mod errors;
|
||||
/// Collection of helpers for serializing/deserializing `Data` objects
|
||||
pub mod helpers;
|
||||
/// Contains trait for converting `reqwest::Request`s to `reqwest::Response`s
|
||||
pub mod http_send;
|
||||
mod mastodon_client;
|
||||
/// Constructing media attachments for a status.
|
||||
pub mod media_builder;
|
||||
@@ -143,14 +137,13 @@ pub mod prelude {
|
||||
|
||||
/// Your mastodon application client, handles all requests to and from Mastodon.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Mastodon<H: HttpSend = HttpSender> {
|
||||
pub struct Mastodon {
|
||||
client: Client,
|
||||
http_sender: H,
|
||||
/// Raw data about your mastodon instance.
|
||||
pub data: Data,
|
||||
}
|
||||
|
||||
impl<H: HttpSend> Mastodon<H> {
|
||||
impl Mastodon {
|
||||
methods![get, post, delete,];
|
||||
|
||||
fn route(&self, url: &str) -> String {
|
||||
@@ -158,16 +151,15 @@ impl<H: HttpSend> Mastodon<H> {
|
||||
}
|
||||
|
||||
pub(crate) fn send(&self, req: RequestBuilder) -> Result<Response> {
|
||||
Ok(self
|
||||
.http_sender
|
||||
.send(&self.client, req.bearer_auth(&self.token))?)
|
||||
let request = req.bearer_auth(&self.token).build()?;
|
||||
Ok(self.client.execute(request)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Data> for Mastodon<HttpSender> {
|
||||
impl From<Data> for Mastodon {
|
||||
/// Creates a mastodon instance from the data struct.
|
||||
fn from(data: Data) -> Mastodon<HttpSender> {
|
||||
let mut builder = MastodonBuilder::new(HttpSender);
|
||||
fn from(data: Data) -> Mastodon {
|
||||
let mut builder = MastodonBuilder::new();
|
||||
builder.data(data);
|
||||
builder
|
||||
.build()
|
||||
@@ -175,7 +167,7 @@ impl From<Data> for Mastodon<HttpSender> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
impl MastodonClient for Mastodon {
|
||||
type Stream = EventReader<WebSocket>;
|
||||
|
||||
paged_routes! {
|
||||
@@ -307,7 +299,7 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
|
||||
/// Get timeline filtered by a hashtag(eg. `#coffee`) either locally or
|
||||
/// federated.
|
||||
fn get_hashtag_timeline(&self, hashtag: &str, local: bool) -> Result<Page<Status, H>> {
|
||||
fn get_hashtag_timeline(&self, hashtag: &str, local: bool) -> Result<Page<Status>> {
|
||||
let base = "/api/v1/timelines/tag/";
|
||||
let url = if local {
|
||||
self.route(&format!("{}{}?local=1", base, hashtag))
|
||||
@@ -327,7 +319,7 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
/// # extern crate elefren;
|
||||
/// # use elefren::prelude::*;
|
||||
/// # use std::error::Error;
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// # let data = Data {
|
||||
/// # base: "".into(),
|
||||
/// # client_id: "".into(),
|
||||
@@ -345,7 +337,7 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
/// # extern crate elefren;
|
||||
/// # use elefren::prelude::*;
|
||||
/// # use std::error::Error;
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// # let data = Data {
|
||||
/// # base: "".into(),
|
||||
/// # client_id: "".into(),
|
||||
@@ -360,7 +352,7 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status, H>>
|
||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
|
||||
where
|
||||
S: Into<Option<StatusesRequest<'a>>>,
|
||||
{
|
||||
@@ -377,7 +369,7 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
|
||||
/// Returns the client account's relationship to a list of other accounts.
|
||||
/// Such as whether they follow them or vice versa.
|
||||
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship, H>> {
|
||||
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> {
|
||||
let mut url = self.route("/api/v1/accounts/relationships?");
|
||||
|
||||
if ids.len() == 1 {
|
||||
@@ -423,13 +415,13 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
}
|
||||
|
||||
/// Get all accounts that follow the authenticated user
|
||||
fn follows_me(&self) -> Result<Page<Account, H>> {
|
||||
fn follows_me(&self) -> Result<Page<Account>> {
|
||||
let me = self.verify_credentials()?;
|
||||
Ok(self.followers(&me.id)?)
|
||||
}
|
||||
|
||||
/// Get all accounts that the authenticated user follows
|
||||
fn followed_by_me(&self) -> Result<Page<Account, H>> {
|
||||
fn followed_by_me(&self) -> Result<Page<Account>> {
|
||||
let me = self.verify_credentials()?;
|
||||
Ok(self.following(&me.id)?)
|
||||
}
|
||||
@@ -444,7 +436,7 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
|
||||
/// # use elefren::prelude::*;
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::entities::event::Event;
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// # let data = Data {
|
||||
/// # base: "".into(),
|
||||
/// # client_id: "".into(),
|
||||
@@ -737,7 +729,7 @@ impl<R: EventStream> EventReader<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: HttpSend> ops::Deref for Mastodon<H> {
|
||||
impl ops::Deref for Mastodon {
|
||||
type Target = Data;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@@ -745,16 +737,14 @@ impl<H: HttpSend> ops::Deref for Mastodon<H> {
|
||||
}
|
||||
}
|
||||
|
||||
struct MastodonBuilder<H: HttpSend> {
|
||||
struct MastodonBuilder {
|
||||
client: Option<Client>,
|
||||
http_sender: H,
|
||||
data: Option<Data>,
|
||||
}
|
||||
|
||||
impl<H: HttpSend> MastodonBuilder<H> {
|
||||
pub fn new(sender: H) -> Self {
|
||||
impl MastodonBuilder {
|
||||
pub fn new() -> Self {
|
||||
MastodonBuilder {
|
||||
http_sender: sender,
|
||||
client: None,
|
||||
data: None,
|
||||
}
|
||||
@@ -770,11 +760,10 @@ impl<H: HttpSend> MastodonBuilder<H> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<Mastodon<H>> {
|
||||
pub fn build(self) -> Result<Mastodon> {
|
||||
Ok(if let Some(data) = self.data {
|
||||
Mastodon {
|
||||
client: self.client.unwrap_or_else(Client::new),
|
||||
http_sender: self.http_sender,
|
||||
data,
|
||||
}
|
||||
} else {
|
||||
@@ -785,15 +774,14 @@ impl<H: HttpSend> MastodonBuilder<H> {
|
||||
|
||||
/// Client that can make unauthenticated calls to a mastodon instance
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MastodonUnauth<H: HttpSend = HttpSender> {
|
||||
pub struct MastodonUnauth {
|
||||
client: Client,
|
||||
http_sender: H,
|
||||
base: url::Url,
|
||||
}
|
||||
|
||||
impl MastodonUnauth<HttpSender> {
|
||||
impl MastodonUnauth {
|
||||
/// Create a new unauthenticated client
|
||||
pub fn new(base: &str) -> Result<MastodonUnauth<HttpSender>> {
|
||||
pub fn new(base: &str) -> Result<MastodonUnauth> {
|
||||
let base = if base.starts_with("https://") {
|
||||
base.to_string()
|
||||
} else {
|
||||
@@ -801,19 +789,19 @@ impl MastodonUnauth<HttpSender> {
|
||||
};
|
||||
Ok(MastodonUnauth {
|
||||
client: Client::new(),
|
||||
http_sender: HttpSender,
|
||||
base: url::Url::parse(&base)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: HttpSend> MastodonUnauth<H> {
|
||||
impl MastodonUnauth {
|
||||
fn route(&self, url: &str) -> Result<url::Url> {
|
||||
Ok(self.base.join(url)?)
|
||||
}
|
||||
|
||||
fn send(&self, req: RequestBuilder) -> Result<Response> {
|
||||
Ok(self.http_sender.send(&self.client, req)?)
|
||||
let req = req.build()?;
|
||||
Ok(self.client.execute(req)?)
|
||||
}
|
||||
|
||||
/// Get a stream of the public timeline
|
||||
@@ -835,7 +823,7 @@ impl<H: HttpSend> MastodonUnauth<H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: HttpSend> MastodonUnauthenticated<H> for MastodonUnauth<H> {
|
||||
impl MastodonUnauthenticated for MastodonUnauth {
|
||||
/// GET /api/v1/statuses/:id
|
||||
fn get_status(&self, id: &str) -> Result<Status> {
|
||||
let route = self.route("/api/v1/statuses")?;
|
||||
|
||||
+3
-3
@@ -40,7 +40,7 @@ macro_rules! paged_routes {
|
||||
"# }\n",
|
||||
"```"
|
||||
),
|
||||
fn $name(&self) -> Result<Page<$ret, H>> {
|
||||
fn $name(&self) -> Result<Page<$ret>> {
|
||||
let url = self.route(concat!("/api/v1/", $url));
|
||||
let response = self.send(
|
||||
self.client.$method(&url)
|
||||
@@ -61,7 +61,7 @@ macro_rules! paged_routes {
|
||||
$url,
|
||||
"`\n# Errors\nIf `access_token` is not set."
|
||||
),
|
||||
fn $name<'a>(&self, $($param: $typ,)*) -> Result<Page<$ret, H>> {
|
||||
fn $name<'a>(&self, $($param: $typ,)*) -> Result<Page<$ret>> {
|
||||
use serde_urlencoded;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -315,7 +315,7 @@ macro_rules! paged_routes_with_id {
|
||||
"# }\n",
|
||||
"```"
|
||||
),
|
||||
fn $name(&self, id: &str) -> Result<Page<$ret, H>> {
|
||||
fn $name(&self, id: &str) -> Result<Page<$ret>> {
|
||||
let url = self.route(&format!(concat!("/api/v1/", $url), id));
|
||||
let response = self.send(
|
||||
self.client.$method(&url)
|
||||
|
||||
+28
-29
@@ -3,7 +3,6 @@ use std::borrow::Cow;
|
||||
use crate::{
|
||||
entities::prelude::*,
|
||||
errors::Result,
|
||||
http_send::{HttpSend, HttpSender},
|
||||
media_builder::MediaBuilder,
|
||||
page::Page,
|
||||
requests::{
|
||||
@@ -19,60 +18,60 @@ use crate::{
|
||||
/// Represents the set of methods that a Mastodon Client can do, so that
|
||||
/// implementations might be swapped out for testing
|
||||
#[allow(unused)]
|
||||
pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
pub trait MastodonClient {
|
||||
/// Type that wraps streaming API streams
|
||||
type Stream: Iterator<Item = Event>;
|
||||
|
||||
/// GET /api/v1/favourites
|
||||
fn favourites(&self) -> Result<Page<Status, H>> {
|
||||
fn favourites(&self) -> Result<Page<Status>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/blocks
|
||||
fn blocks(&self) -> Result<Page<Account, H>> {
|
||||
fn blocks(&self) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/domain_blocks
|
||||
fn domain_blocks(&self) -> Result<Page<String, H>> {
|
||||
fn domain_blocks(&self) -> Result<Page<String>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/follow_requests
|
||||
fn follow_requests(&self) -> Result<Page<Account, H>> {
|
||||
fn follow_requests(&self) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/timelines/home
|
||||
fn get_home_timeline(&self) -> Result<Page<Status, H>> {
|
||||
fn get_home_timeline(&self) -> Result<Page<Status>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/custom_emojis
|
||||
fn get_emojis(&self) -> Result<Page<Emoji, H>> {
|
||||
fn get_emojis(&self) -> Result<Page<Emoji>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/mutes
|
||||
fn mutes(&self) -> Result<Page<Account, H>> {
|
||||
fn mutes(&self) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/notifications
|
||||
fn notifications(&self) -> Result<Page<Notification, H>> {
|
||||
fn notifications(&self) -> Result<Page<Notification>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/reports
|
||||
fn reports(&self) -> Result<Page<Report, H>> {
|
||||
fn reports(&self) -> Result<Page<Report>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/accounts/:id/followers
|
||||
fn followers(&self, id: &str) -> Result<Page<Account, H>> {
|
||||
fn followers(&self, id: &str) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/accounts/:id/following
|
||||
fn following(&self, id: &str) -> Result<Page<Account, H>> {
|
||||
fn following(&self, id: &str) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/statuses/:id/reblogged_by
|
||||
fn reblogged_by(&self, id: &str) -> Result<Page<Account, H>> {
|
||||
fn reblogged_by(&self, id: &str) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/statuses/:id/favourited_by
|
||||
fn favourited_by(&self, id: &str) -> Result<Page<Account, H>> {
|
||||
fn favourited_by(&self, id: &str) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// DELETE /api/v1/domain_blocks
|
||||
@@ -200,26 +199,26 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/timelines/public?local=true
|
||||
fn get_local_timeline(&self) -> Result<Page<Status, H>> {
|
||||
fn get_local_timeline(&self) -> Result<Page<Status>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/timelines/public?local=false
|
||||
fn get_federated_timeline(&self) -> Result<Page<Status, H>> {
|
||||
fn get_federated_timeline(&self) -> Result<Page<Status>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/timelines/tag/:hashtag
|
||||
fn get_hashtag_timeline(&self, hashtag: &str, local: bool) -> Result<Page<Status, H>> {
|
||||
fn get_hashtag_timeline(&self, hashtag: &str, local: bool) -> Result<Page<Status>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/accounts/:id/statuses
|
||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status, H>>
|
||||
fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
|
||||
where
|
||||
S: Into<Option<StatusesRequest<'a>>>,
|
||||
{
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/accounts/relationships
|
||||
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship, H>> {
|
||||
fn relationships(&self, ids: &[&str]) -> Result<Page<Relationship>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/accounts/search?q=:query&limit=:limit&following=:following
|
||||
@@ -228,7 +227,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
query: &str,
|
||||
limit: Option<u64>,
|
||||
following: bool,
|
||||
) -> Result<Page<Account, H>> {
|
||||
) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// POST /api/v1/push/subscription
|
||||
@@ -276,7 +275,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/endorsements
|
||||
fn get_endorsements(&self) -> Result<Page<Account, H>> {
|
||||
fn get_endorsements(&self) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// POST /api/v1/accounts/:id/pin
|
||||
@@ -293,7 +292,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
/// # extern crate elefren;
|
||||
/// # use std::error::Error;
|
||||
/// # use elefren::prelude::*;
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// # let data = Data {
|
||||
/// # base: "".into(),
|
||||
/// # client_id: "".into(),
|
||||
@@ -305,7 +304,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
/// let follows_me = client.follows_me()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
fn follows_me(&self) -> Result<Page<Account, H>> {
|
||||
fn follows_me(&self) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// Shortcut for
|
||||
@@ -315,7 +314,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
/// # extern crate elefren;
|
||||
/// # use std::error::Error;
|
||||
/// # use elefren::prelude::*;
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// # let data = Data {
|
||||
/// # base: "".into(),
|
||||
/// # client_id: "".into(),
|
||||
@@ -327,7 +326,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
/// let follows_me = client.followed_by_me()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
fn followed_by_me(&self) -> Result<Page<Account, H>> {
|
||||
fn followed_by_me(&self) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
|
||||
@@ -371,7 +370,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
|
||||
/// Trait that represents clients that can make unauthenticated calls to a
|
||||
/// mastodon instance
|
||||
#[allow(unused)]
|
||||
pub trait MastodonUnauthenticated<H: HttpSend> {
|
||||
pub trait MastodonUnauthenticated {
|
||||
/// GET /api/v1/statuses/:id
|
||||
fn get_status(&self, id: &str) -> Result<Status> {
|
||||
unimplemented!("This method was not implemented");
|
||||
@@ -385,11 +384,11 @@ pub trait MastodonUnauthenticated<H: HttpSend> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/statuses/:id/reblogged_by
|
||||
fn reblogged_by(&self, id: &str) -> Result<Page<Account, H>> {
|
||||
fn reblogged_by(&self, id: &str) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
/// GET /api/v1/statuses/:id/favourited_by
|
||||
fn favourited_by(&self, id: &str) -> Result<Page<Account, H>> {
|
||||
fn favourited_by(&self, id: &str) -> Result<Page<Account>> {
|
||||
unimplemented!("This method was not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
+14
-18
@@ -5,8 +5,6 @@ use reqwest::{header::LINK, Response};
|
||||
use serde::Deserialize;
|
||||
use url::Url;
|
||||
|
||||
use crate::http_send::HttpSend;
|
||||
|
||||
macro_rules! pages {
|
||||
($($direction:ident: $fun:ident),*) => {
|
||||
|
||||
@@ -42,7 +40,6 @@ macro_rules! pages {
|
||||
/// # 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::*;
|
||||
@@ -56,7 +53,7 @@ macro_rules! pages {
|
||||
/// # };
|
||||
/// struct HomeTimeline {
|
||||
/// client: Mastodon,
|
||||
/// page: RefCell<Option<OwnedPage<Status, HttpSender>>>,
|
||||
/// page: RefCell<Option<OwnedPage<Status>>>,
|
||||
/// }
|
||||
/// let client = Mastodon::from(data);
|
||||
/// let home = client.get_home_timeline()?.into_owned();
|
||||
@@ -68,23 +65,23 @@ macro_rules! pages {
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OwnedPage<T: for<'de> Deserialize<'de>, H: HttpSend> {
|
||||
mastodon: Mastodon<H>,
|
||||
pub struct OwnedPage<T: for<'de> Deserialize<'de>> {
|
||||
mastodon: Mastodon,
|
||||
next: Option<Url>,
|
||||
prev: Option<Url>,
|
||||
/// Initial set of items
|
||||
pub initial_items: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: for<'de> Deserialize<'de>, H: HttpSend> OwnedPage<T, H> {
|
||||
impl<T: for<'de> Deserialize<'de>> OwnedPage<T> {
|
||||
pages! {
|
||||
next: next_page,
|
||||
prev: prev_page
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: for<'de> Deserialize<'de>, H: HttpSend> From<Page<'a, T, H>> for OwnedPage<T, H> {
|
||||
fn from(page: Page<'a, T, H>) -> OwnedPage<T, H> {
|
||||
impl<'a, T: for<'de> Deserialize<'de>> From<Page<'a, T>> for OwnedPage<T> {
|
||||
fn from(page: Page<'a, T>) -> OwnedPage<T> {
|
||||
OwnedPage {
|
||||
mastodon: page.mastodon.clone(),
|
||||
next: page.next,
|
||||
@@ -96,21 +93,21 @@ impl<'a, T: for<'de> Deserialize<'de>, H: HttpSend> From<Page<'a, T, H>> for Own
|
||||
|
||||
/// Represents a single page of API results
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Page<'a, T: for<'de> Deserialize<'de>, H: 'a + HttpSend> {
|
||||
mastodon: &'a Mastodon<H>,
|
||||
pub struct Page<'a, T: for<'de> Deserialize<'de>> {
|
||||
mastodon: &'a Mastodon,
|
||||
next: Option<Url>,
|
||||
prev: Option<Url>,
|
||||
/// Initial set of items
|
||||
pub initial_items: Vec<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
impl<'a, T: for<'de> Deserialize<'de>> Page<'a, T> {
|
||||
pages! {
|
||||
next: next_page,
|
||||
prev: prev_page
|
||||
}
|
||||
|
||||
pub(crate) fn new(mastodon: &'a Mastodon<H>, response: Response) -> Result<Self> {
|
||||
pub(crate) fn new(mastodon: &'a Mastodon, response: Response) -> Result<Self> {
|
||||
let (prev, next) = get_links(&response)?;
|
||||
Ok(Page {
|
||||
initial_items: deserialise(response)?,
|
||||
@@ -121,7 +118,7 @@ impl<'a, T: for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
impl<'a, T: Clone + for<'de> Deserialize<'de>> Page<'a, T> {
|
||||
/// Returns an owned version of this struct that doesn't borrow the client
|
||||
/// that created it
|
||||
///
|
||||
@@ -131,7 +128,6 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
/// # 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::*;
|
||||
@@ -145,7 +141,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
/// # };
|
||||
/// struct HomeTimeline {
|
||||
/// client: Mastodon,
|
||||
/// page: RefCell<Option<OwnedPage<Status, HttpSender>>>,
|
||||
/// page: RefCell<Option<OwnedPage<Status>>>,
|
||||
/// }
|
||||
/// let client = Mastodon::from(data);
|
||||
/// let home = client.get_home_timeline()?.into_owned();
|
||||
@@ -156,7 +152,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn into_owned(self) -> OwnedPage<T, H> {
|
||||
pub fn into_owned(self) -> OwnedPage<T> {
|
||||
OwnedPage::from(self)
|
||||
}
|
||||
|
||||
@@ -176,7 +172,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>, H: HttpSend> Page<'a, T, H> {
|
||||
/// # extern crate elefren;
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::prelude::*;
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// # let data = Data {
|
||||
/// # base: "".into(),
|
||||
/// # client_id: "".into(),
|
||||
|
||||
+16
-34
@@ -7,7 +7,6 @@ use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
|
||||
|
||||
use crate::{
|
||||
apps::{App, AppBuilder},
|
||||
http_send::{HttpSend, HttpSender},
|
||||
scopes::Scopes,
|
||||
Data,
|
||||
Error,
|
||||
@@ -21,12 +20,11 @@ const DEFAULT_REDIRECT_URI: &str = "urn:ietf:wg:oauth:2.0:oob";
|
||||
/// Handles registering your mastodon app to your instance. It is recommended
|
||||
/// you cache your data struct to avoid registering on every run.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Registration<'a, H: HttpSend = HttpSender> {
|
||||
pub struct Registration<'a> {
|
||||
base: String,
|
||||
client: Client,
|
||||
app_builder: AppBuilder<'a>,
|
||||
force_login: bool,
|
||||
http_sender: H,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -46,7 +44,7 @@ struct AccessToken {
|
||||
access_token: String,
|
||||
}
|
||||
|
||||
impl<'a> Registration<'a, HttpSender> {
|
||||
impl<'a> Registration<'a> {
|
||||
/// Construct a new registration process to the instance of the `base` url.
|
||||
/// ```
|
||||
/// use elefren::prelude::*;
|
||||
@@ -59,23 +57,11 @@ impl<'a> Registration<'a, HttpSender> {
|
||||
client: Client::new(),
|
||||
app_builder: AppBuilder::new(),
|
||||
force_login: false,
|
||||
http_sender: HttpSender,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, H: HttpSend> Registration<'a, H> {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn with_sender<I: Into<String>>(base: I, http_sender: H) -> Self {
|
||||
Registration {
|
||||
base: base.into(),
|
||||
client: Client::new(),
|
||||
app_builder: AppBuilder::new(),
|
||||
force_login: false,
|
||||
http_sender,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Registration<'a> {
|
||||
/// Sets the name of this app
|
||||
///
|
||||
/// This is required, and if this isn't set then the AppBuilder::build
|
||||
@@ -113,7 +99,8 @@ impl<'a, H: HttpSend> Registration<'a, H> {
|
||||
}
|
||||
|
||||
fn send(&self, req: RequestBuilder) -> Result<Response> {
|
||||
Ok(self.http_sender.send(&self.client, req)?)
|
||||
let req = req.build()?;
|
||||
Ok(self.client.execute(req)?)
|
||||
}
|
||||
|
||||
/// Register the given application
|
||||
@@ -137,7 +124,7 @@ impl<'a, H: HttpSend> Registration<'a, H> {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn register<I: TryInto<App>>(&mut self, app: I) -> Result<Registered<H>>
|
||||
pub fn register<I: TryInto<App>>(&mut self, app: I) -> Result<Registered>
|
||||
where
|
||||
Error: From<<I as TryInto<App>>::Err>,
|
||||
{
|
||||
@@ -152,7 +139,6 @@ impl<'a, H: HttpSend> Registration<'a, H> {
|
||||
redirect: oauth.redirect_uri,
|
||||
scopes: app.scopes().clone(),
|
||||
force_login: self.force_login,
|
||||
http_sender: self.http_sender.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -176,7 +162,7 @@ impl<'a, H: HttpSend> Registration<'a, H> {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn build(&mut self) -> Result<Registered<H>> {
|
||||
pub fn build(&mut self) -> Result<Registered> {
|
||||
let app: App = self.app_builder.clone().build()?;
|
||||
let oauth = self.send_app(&app)?;
|
||||
|
||||
@@ -188,7 +174,6 @@ impl<'a, H: HttpSend> Registration<'a, H> {
|
||||
redirect: oauth.redirect_uri,
|
||||
scopes: app.scopes().clone(),
|
||||
force_login: self.force_login,
|
||||
http_sender: self.http_sender.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -198,7 +183,7 @@ impl<'a, H: HttpSend> Registration<'a, H> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Registered<HttpSender> {
|
||||
impl Registered {
|
||||
/// Skip having to retrieve the client id and secret from the server by
|
||||
/// creating a `Registered` struct directly
|
||||
///
|
||||
@@ -234,7 +219,7 @@ impl Registered<HttpSender> {
|
||||
redirect: &str,
|
||||
scopes: Scopes,
|
||||
force_login: bool,
|
||||
) -> Registered<HttpSender> {
|
||||
) -> Registered {
|
||||
Registered {
|
||||
base: base.to_string(),
|
||||
client: Client::new(),
|
||||
@@ -243,14 +228,14 @@ impl Registered<HttpSender> {
|
||||
redirect: redirect.to_string(),
|
||||
scopes,
|
||||
force_login,
|
||||
http_sender: HttpSender,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H: HttpSend> Registered<H> {
|
||||
impl Registered {
|
||||
fn send(&self, req: RequestBuilder) -> Result<Response> {
|
||||
Ok(self.http_sender.send(&self.client, req)?)
|
||||
let req = req.build()?;
|
||||
Ok(self.client.execute(req)?)
|
||||
}
|
||||
|
||||
/// Returns the parts of the `Registered` struct that can be used to
|
||||
@@ -324,7 +309,7 @@ impl<H: HttpSend> Registered<H> {
|
||||
|
||||
/// Create an access token from the client id, client secret, and code
|
||||
/// provided by the authorisation url.
|
||||
pub fn complete(&self, code: &str) -> Result<Mastodon<H>> {
|
||||
pub fn complete(&self, code: &str) -> Result<Mastodon> {
|
||||
let url = format!(
|
||||
"{}/oauth/token?client_id={}&client_secret={}&code={}&grant_type=authorization_code&\
|
||||
redirect_uri={}",
|
||||
@@ -341,7 +326,7 @@ impl<H: HttpSend> Registered<H> {
|
||||
token: token.access_token.into(),
|
||||
};
|
||||
|
||||
let mut builder = MastodonBuilder::new(self.http_sender.clone());
|
||||
let mut builder = MastodonBuilder::new();
|
||||
builder.client(self.client.clone()).data(data);
|
||||
Ok(builder.build()?)
|
||||
}
|
||||
@@ -350,7 +335,7 @@ impl<H: HttpSend> Registered<H> {
|
||||
/// Represents the state of the auth flow when the app has been registered but
|
||||
/// the user is not authenticated
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Registered<H: HttpSend> {
|
||||
pub struct Registered {
|
||||
base: String,
|
||||
client: Client,
|
||||
client_id: String,
|
||||
@@ -358,7 +343,6 @@ pub struct Registered<H: HttpSend> {
|
||||
redirect: String,
|
||||
scopes: Scopes,
|
||||
force_login: bool,
|
||||
http_sender: H,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -370,15 +354,13 @@ mod tests {
|
||||
let r = Registration::new("https://example.com");
|
||||
assert_eq!(r.base, "https://example.com".to_string());
|
||||
assert_eq!(r.app_builder, AppBuilder::new());
|
||||
assert_eq!(r.http_sender, HttpSender);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_registration_with_sender() {
|
||||
let r = Registration::with_sender("https://example.com", HttpSender);
|
||||
let r = Registration::new("https://example.com");
|
||||
assert_eq!(r.base, "https://example.com".to_string());
|
||||
assert_eq!(r.app_builder, AppBuilder::new());
|
||||
assert_eq!(r.http_sender, HttpSender);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -10,7 +10,7 @@ use std::time::Duration;
|
||||
/// # extern crate elefren;
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::{entities::filter::FilterContext, requests::AddFilterRequest};
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let request = AddFilterRequest::new("foo", FilterContext::Home);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
|
||||
+7
-7
@@ -90,7 +90,7 @@ impl Scopes {
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::scopes::Scopes;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let scope = Scopes::all();
|
||||
/// assert_eq!(&format!("{}", scope), "read write follow push");
|
||||
/// # Ok(())
|
||||
@@ -107,7 +107,7 @@ impl Scopes {
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::scopes::Scopes;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let scope = Scopes::read_all();
|
||||
/// assert_eq!(&format!("{}", scope), "read");
|
||||
/// # Ok(())
|
||||
@@ -124,7 +124,7 @@ impl Scopes {
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::scopes::{Read, Scopes};
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let scope = Scopes::read(Read::Accounts);
|
||||
/// assert_eq!(&format!("{}", scope), "read:accounts");
|
||||
/// # Ok(())
|
||||
@@ -141,7 +141,7 @@ impl Scopes {
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::scopes::Scopes;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let scope = Scopes::write_all();
|
||||
/// assert_eq!(&format!("{}", scope), "write");
|
||||
/// # Ok(())
|
||||
@@ -158,7 +158,7 @@ impl Scopes {
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::scopes::{Scopes, Write};
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let scope = Scopes::write(Write::Accounts);
|
||||
/// assert_eq!(&format!("{}", scope), "write:accounts");
|
||||
/// # Ok(())
|
||||
@@ -175,7 +175,7 @@ impl Scopes {
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::scopes::Scopes;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let scope = Scopes::follow();
|
||||
/// assert_eq!(&format!("{}", scope), "follow");
|
||||
/// # Ok(())
|
||||
@@ -192,7 +192,7 @@ impl Scopes {
|
||||
/// # use std::error::Error;
|
||||
/// use elefren::scopes::Scopes;
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<Error>> {
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let scope = Scopes::push();
|
||||
/// assert_eq!(&format!("{}", scope), "push");
|
||||
/// # Ok(())
|
||||
|
||||
Reference in New Issue
Block a user