forked from MightyPork/elefren-fork
all asyncified except for streaming
This commit is contained in:
+9
-25
@@ -12,36 +12,20 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
doc-comment = "0.3"
|
doc-comment = "0.3"
|
||||||
envy = { version = "0.4.0", optional = true }
|
#envy = { version = "0.4.0", optional = true }
|
||||||
hyper-old-types = "0.11.0"
|
hyper-old-types = "0.11.0" # Used to parse the link header
|
||||||
isolang = { version = "1.0", features = ["serde_serialize"] }
|
isolang = { version = "1.0", features = ["serde_serialize"] }
|
||||||
log = "^0.4"
|
log = "^0.4"
|
||||||
reqwest = { version = "0.11.4", default-features = false, features = ["json", "blocking", "multipart"] }
|
reqwest = { version = "0.11.4", default-features = false, features = ["json", "blocking", "multipart", "rustls-tls", "stream"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_urlencoded = "0.6.1"
|
serde_urlencoded = "0.6.1"
|
||||||
serde_qs = "0.8.4"
|
serde_qs = "0.8.4"
|
||||||
url = "2.1.1"
|
url = "2.1.1"
|
||||||
tap-reader = "1"
|
#tap-reader = "1"
|
||||||
toml = { version = "^0.5.0", optional = true }
|
toml = { version = "^0.5.0", optional = true }
|
||||||
tungstenite = "0.15.0"
|
tokio-tungstenite = { version = "0.15.0", features = ["rustls-tls"] }
|
||||||
|
futures = { version = "0.3" }
|
||||||
[dependencies.chrono]
|
tokio = {version = "1", features = ["full"] }
|
||||||
version = "0.4"
|
tokio-util = { version = "0.6", features = [ "compat", "io" ] }
|
||||||
features = ["serde"]
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["reqwest/default-tls","tungstenite/native-tls"]
|
|
||||||
json = []
|
|
||||||
env = ["envy"]
|
|
||||||
all = ["toml", "json", "env"]
|
|
||||||
rustls-tls = ["reqwest/rustls-tls","tungstenite/__rustls-tls"]
|
|
||||||
nightly = []
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tempfile = "3.0.3"
|
|
||||||
indoc = "1.0.2"
|
|
||||||
pretty_env_logger = "0.4.0"
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
features = ["all"]
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ use serde::Deserialize;
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>> {
|
pub struct ItemsIter<'a, T: Clone + for<'de> Deserialize<'de>> {
|
||||||
page: Page<'a, T>,
|
page: Page<'a, T>,
|
||||||
buffer: Vec<T>,
|
buffer: Vec<T>,
|
||||||
cur_idx: usize,
|
cur_idx: usize,
|
||||||
@@ -45,8 +45,8 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
|
|||||||
self.buffer.is_empty() || self.cur_idx == self.buffer.len()
|
self.buffer.is_empty() || self.cur_idx == self.buffer.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_next_page(&mut self) -> Option<()> {
|
async fn fill_next_page(&mut self) -> Option<()> {
|
||||||
let items = if let Ok(items) = self.page.next_page() {
|
let items = if let Ok(items) = self.page.next_page().await {
|
||||||
items
|
items
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
@@ -62,12 +62,8 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> ItemsIter<'a, T> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Clone + for<'de> Deserialize<'de>> Iterator for ItemsIter<'a, T> {
|
pub async fn next_item(&mut self) -> Option<T> {
|
||||||
type Item = T;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if self.use_initial {
|
if self.use_initial {
|
||||||
if self.page.initial_items.is_empty() || self.cur_idx == self.page.initial_items.len() {
|
if self.page.initial_items.is_empty() || self.cur_idx == self.page.initial_items.len() {
|
||||||
return None;
|
return None;
|
||||||
@@ -81,7 +77,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> Iterator for ItemsIter<'a, T> {
|
|||||||
}
|
}
|
||||||
Some(self.page.initial_items[idx].clone())
|
Some(self.page.initial_items[idx].clone())
|
||||||
} else {
|
} else {
|
||||||
if self.need_next_page() && self.fill_next_page().is_none() {
|
if self.need_next_page() && self.fill_next_page().await.is_none() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let idx = self.cur_idx;
|
let idx = self.cur_idx;
|
||||||
|
|||||||
+8
-8
@@ -12,7 +12,7 @@ use reqwest::{header::ToStrError as HeaderStrError, Error as HttpError, StatusCo
|
|||||||
use serde_json::Error as SerdeError;
|
use serde_json::Error as SerdeError;
|
||||||
use serde_qs::Error as SerdeQsError;
|
use serde_qs::Error as SerdeQsError;
|
||||||
use serde_urlencoded::ser::Error as UrlEncodedError;
|
use serde_urlencoded::ser::Error as UrlEncodedError;
|
||||||
use tungstenite::error::Error as WebSocketError;
|
// use tungstenite::error::Error as WebSocketError;
|
||||||
use url::ParseError as UrlError;
|
use url::ParseError as UrlError;
|
||||||
|
|
||||||
/// Convience type over `std::result::Result` with `Error` as the error type.
|
/// Convience type over `std::result::Result` with `Error` as the error type.
|
||||||
@@ -57,14 +57,14 @@ pub enum Error {
|
|||||||
HeaderStrError(HeaderStrError),
|
HeaderStrError(HeaderStrError),
|
||||||
/// Error parsing the http Link header
|
/// Error parsing the http Link header
|
||||||
HeaderParseError(HeaderParseError),
|
HeaderParseError(HeaderParseError),
|
||||||
#[cfg(feature = "env")]
|
// #[cfg(feature = "env")]
|
||||||
/// Error deserializing from the environment
|
// /// Error deserializing from the environment
|
||||||
Envy(EnvyError),
|
// Envy(EnvyError),
|
||||||
/// Error serializing to a query string
|
/// Error serializing to a query string
|
||||||
SerdeQs(SerdeQsError),
|
SerdeQs(SerdeQsError),
|
||||||
/// WebSocket error
|
/// WebSocket error
|
||||||
WebSocket(WebSocketError),
|
// WebSocket(WebSocketError),
|
||||||
/// Other errors
|
// /// Other errors
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ impl error::Error for Error {
|
|||||||
#[cfg(feature = "env")]
|
#[cfg(feature = "env")]
|
||||||
Error::Envy(ref e) => e,
|
Error::Envy(ref e) => e,
|
||||||
Error::SerdeQs(ref e) => e,
|
Error::SerdeQs(ref e) => e,
|
||||||
Error::WebSocket(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::ClientIdRequired => return None,
|
||||||
@@ -148,7 +148,7 @@ from! {
|
|||||||
HeaderParseError, HeaderParseError,
|
HeaderParseError, HeaderParseError,
|
||||||
#[cfg(feature = "env")] EnvyError, Envy,
|
#[cfg(feature = "env")] EnvyError, Envy,
|
||||||
SerdeQsError, SerdeQs,
|
SerdeQsError, SerdeQs,
|
||||||
WebSocketError, WebSocket,
|
// WebSocketError, WebSocket,
|
||||||
String, Other,
|
String, Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ use crate::{errors::Result, registration::Registered, Mastodon};
|
|||||||
|
|
||||||
/// Finishes the authentication process for the given `Registered` object,
|
/// Finishes the authentication process for the given `Registered` object,
|
||||||
/// using the command-line
|
/// using the command-line
|
||||||
pub fn authenticate(registration: Registered) -> Result<Mastodon> {
|
pub async fn authenticate(registration: Registered) -> Result<Mastodon> {
|
||||||
let url = registration.authorize_url()?;
|
let url = registration.authorize_url()?;
|
||||||
|
|
||||||
let stdout = io::stdout();
|
let stdout = io::stdout();
|
||||||
@@ -20,5 +20,5 @@ pub fn authenticate(registration: Registered) -> Result<Mastodon> {
|
|||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
stdin.read_line(&mut input)?;
|
stdin.read_line(&mut input)?;
|
||||||
let code = input.trim();
|
let code = input.trim();
|
||||||
registration.complete(code)
|
registration.complete(code).await
|
||||||
}
|
}
|
||||||
|
|||||||
+101
-91
@@ -57,31 +57,30 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![deny(
|
// #![deny(
|
||||||
missing_docs,
|
// missing_docs,
|
||||||
warnings,
|
// warnings,
|
||||||
missing_debug_implementations,
|
// missing_debug_implementations,
|
||||||
missing_copy_implementations,
|
// missing_copy_implementations,
|
||||||
trivial_casts,
|
// trivial_casts,
|
||||||
trivial_numeric_casts,
|
// trivial_numeric_casts,
|
||||||
unsafe_code,
|
// unsafe_code,
|
||||||
unstable_features,
|
// unstable_features,
|
||||||
unused_import_braces,
|
// unused_import_braces,
|
||||||
unused_qualifications
|
// unused_qualifications
|
||||||
)]
|
// )]
|
||||||
// #![cfg_attr(feature = "nightly", allow(broken_intra_doc_links))]
|
// #![cfg_attr(feature = "nightly", allow(broken_intra_doc_links))]
|
||||||
// #![allow(broken_intra_doc_links)]
|
// #![allow(broken_intra_doc_links)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
use std::{borrow::Cow, io::BufRead, ops};
|
use std::{borrow::Cow, ops};
|
||||||
use std::net::TcpStream;
|
|
||||||
|
|
||||||
pub use isolang::Language;
|
pub use isolang::Language;
|
||||||
use reqwest::blocking::{Client, multipart, RequestBuilder, Response};
|
use reqwest::{Client, multipart, RequestBuilder, Response, Body};
|
||||||
use tap_reader::Tap;
|
// use tap_reader::Tap;
|
||||||
use tungstenite::stream::MaybeTlsStream;
|
// use tungstenite::stream::MaybeTlsStream;
|
||||||
|
|
||||||
use crate::{entities::prelude::*, page::Page};
|
use crate::{entities::prelude::*, page::Page};
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
@@ -104,7 +103,6 @@ pub mod entities;
|
|||||||
pub mod errors;
|
pub mod errors;
|
||||||
/// Collection of helpers for serializing/deserializing `Data` objects
|
/// Collection of helpers for serializing/deserializing `Data` objects
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
mod mastodon_client;
|
|
||||||
/// Constructing media attachments for a status.
|
/// Constructing media attachments for a status.
|
||||||
pub mod media_builder;
|
pub mod media_builder;
|
||||||
/// Handling multiple pages of entities.
|
/// Handling multiple pages of entities.
|
||||||
@@ -132,26 +130,11 @@ pub mod prelude {
|
|||||||
/// Your mastodon application client, handles all requests to and from Mastodon.
|
/// Your mastodon application client, handles all requests to and from Mastodon.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Mastodon {
|
pub struct Mastodon {
|
||||||
|
|
||||||
client: Client,
|
client: Client,
|
||||||
/// Raw data about your mastodon instance.
|
/// Raw data about your mastodon instance.
|
||||||
pub data: Data,
|
pub data: Data,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mastodon {
|
|
||||||
|
|
||||||
methods![get, post, delete,];
|
|
||||||
|
|
||||||
fn route(&self, url: &str) -> String {
|
|
||||||
format!("{}{}", self.base, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn send(&self, req: RequestBuilder) -> Result<Response> {
|
|
||||||
let request = req.bearer_auth(&self.token).build()?;
|
|
||||||
Ok(self.client.execute(request)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Data> for Mastodon {
|
impl From<Data> for Mastodon {
|
||||||
/// Creates a mastodon instance from the data struct.
|
/// Creates a mastodon instance from the data struct.
|
||||||
fn from(data: Data) -> Mastodon {
|
fn from(data: Data) -> Mastodon {
|
||||||
@@ -161,7 +144,20 @@ impl From<Data> for Mastodon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type MastodonStream = EventReader<WebSocket>;
|
// type MastodonStream = EventReader<WebSocket>;
|
||||||
|
|
||||||
|
impl Mastodon {
|
||||||
|
methods![get, post, delete,];
|
||||||
|
|
||||||
|
fn route(&self, url: &str) -> String {
|
||||||
|
format!("{}{}", self.base, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn send(&self, req: RequestBuilder) -> Result<Response> {
|
||||||
|
let request = req.bearer_auth(&self.token).build()?;
|
||||||
|
Ok(self.client.execute(request).await?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mastodon {
|
impl Mastodon {
|
||||||
route_v1_paged!((get) favourites: "favourites" => Status);
|
route_v1_paged!((get) favourites: "favourites" => Status);
|
||||||
@@ -224,9 +220,9 @@ impl Mastodon {
|
|||||||
route_v1_id!((post) unendorse_user: "accounts/{}/unpin" => Relationship);
|
route_v1_id!((post) unendorse_user: "accounts/{}/unpin" => Relationship);
|
||||||
|
|
||||||
/// POST /api/v1/filters
|
/// POST /api/v1/filters
|
||||||
pub fn add_filter(&self, request: &mut AddFilterRequest) -> Result<Filter> {
|
pub async fn add_filter(&self, request: &mut AddFilterRequest) -> Result<Filter> {
|
||||||
let url = self.route("/api/v1/filters");
|
let url = self.route("/api/v1/filters");
|
||||||
let response = self.send(self.client.post(&url).json(&request))?;
|
let response = self.send(self.client.post(&url).json(&request)).await?;
|
||||||
|
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
|
|
||||||
@@ -236,13 +232,13 @@ impl Mastodon {
|
|||||||
return Err(Error::Server(status));
|
return Err(Error::Server(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PUT /api/v1/filters/:id
|
/// PUT /api/v1/filters/:id
|
||||||
pub fn update_filter(&self, id: &str, request: &mut AddFilterRequest) -> Result<Filter> {
|
pub async fn update_filter(&self, id: &str, request: &mut AddFilterRequest) -> Result<Filter> {
|
||||||
let url = self.route(&format!("/api/v1/filters/{}", id));
|
let url = self.route(&format!("/api/v1/filters/{}", id));
|
||||||
let response = self.send(self.client.put(&url).json(&request))?;
|
let response = self.send(self.client.put(&url).json(&request)).await?;
|
||||||
|
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
|
|
||||||
@@ -252,14 +248,14 @@ impl Mastodon {
|
|||||||
return Err(Error::Server(status));
|
return Err(Error::Server(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PATCH /api/v1/accounts/update_credentials
|
/// PATCH /api/v1/accounts/update_credentials
|
||||||
pub fn update_credentials(&self, builder: &mut UpdateCredsRequest) -> Result<Account> {
|
pub async fn update_credentials(&self, builder: &mut UpdateCredsRequest) -> Result<Account> {
|
||||||
let changes = builder.build()?;
|
let changes = builder.build()?;
|
||||||
let url = self.route("/api/v1/accounts/update_credentials");
|
let url = self.route("/api/v1/accounts/update_credentials");
|
||||||
let response = self.send(self.client.patch(&url).json(&changes))?;
|
let response = self.send(self.client.patch(&url).json(&changes)).await?;
|
||||||
|
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
|
|
||||||
@@ -269,19 +265,19 @@ impl Mastodon {
|
|||||||
return Err(Error::Server(status));
|
return Err(Error::Server(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Post a new status to the account.
|
/// Post a new status to the account.
|
||||||
pub fn new_status(&self, status: NewStatus) -> Result<Status> {
|
pub async fn new_status(&self, status: NewStatus) -> Result<Status> {
|
||||||
let response = self.send(self.client.post(&self.route("/api/v1/statuses")).json(&status))?;
|
let response = self.send(self.client.post(&self.route("/api/v1/statuses")).json(&status)).await?;
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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_hashtag_timeline(&self, hashtag: &str, local: bool) -> Result<Page<Status>> {
|
pub async fn get_hashtag_timeline<'a>(&'a self, hashtag: &str, local: bool) -> Result<Page<'a, Status>> {
|
||||||
let base = "/api/v1/timelines/tag/";
|
let base = "/api/v1/timelines/tag/";
|
||||||
let url = if local {
|
let url = if local {
|
||||||
self.route(&format!("{}{}?local=1", base, hashtag))
|
self.route(&format!("{}{}?local=1", base, hashtag))
|
||||||
@@ -289,12 +285,12 @@ impl Mastodon {
|
|||||||
self.route(&format!("{}{}", base, hashtag))
|
self.route(&format!("{}{}", base, hashtag))
|
||||||
};
|
};
|
||||||
|
|
||||||
Page::new(self, self.send(self.client.get(&url))?)
|
Page::new(self, self.send(self.client.get(&url)).await?).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get statuses of a single account by id. Optionally only with pictures
|
/// Get statuses of a single account by id. Optionally only with pictures
|
||||||
/// and or excluding replies.
|
/// and or excluding replies.
|
||||||
pub fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<Status>>
|
pub async fn statuses<'a, 'b: 'a, S>(&'b self, id: &'b str, request: S) -> Result<Page<'b, Status>>
|
||||||
where
|
where
|
||||||
S: Into<Option<StatusesRequest<'a>>>,
|
S: Into<Option<StatusesRequest<'a>>>,
|
||||||
{
|
{
|
||||||
@@ -304,14 +300,14 @@ impl Mastodon {
|
|||||||
url = format!("{}{}", url, request.to_querystring()?);
|
url = format!("{}{}", url, request.to_querystring()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = self.send(self.client.get(&url))?;
|
let response = self.send(self.client.get(&url)).await?;
|
||||||
|
|
||||||
Page::new(self, response)
|
Page::new(self, response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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>> {
|
pub async fn relationships<'a>(&'a self, ids: &[&str]) -> Result<Page<'a, 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 {
|
||||||
@@ -326,40 +322,42 @@ impl Mastodon {
|
|||||||
url.pop();
|
url.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = self.send(self.client.get(&url))?;
|
let response = self.send(self.client.get(&url)).await?;
|
||||||
|
|
||||||
Page::new(self, response)
|
Page::new(self, response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a push notifications subscription
|
/// Add a push notifications subscription
|
||||||
pub fn add_push_subscription(&self, request: &AddPushRequest) -> Result<Subscription> {
|
pub async fn add_push_subscription(&self, request: &AddPushRequest) -> Result<Subscription> {
|
||||||
let request = request.build()?;
|
let request = request.build()?;
|
||||||
let response = self.send(self.client.post(&self.route("/api/v1/push/subscription")).json(&request))?;
|
let response = self.send(self.client.post(&self.route("/api/v1/push/subscription")).json(&request)).await?;
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the `data` portion of the push subscription associated with this
|
/// Update the `data` portion of the push subscription associated with this
|
||||||
/// access token
|
/// access token
|
||||||
pub fn update_push_data(&self, request: &UpdatePushRequest) -> Result<Subscription> {
|
pub async fn update_push_data(&self, request: &UpdatePushRequest) -> Result<Subscription> {
|
||||||
let request = request.build();
|
let request = request.build();
|
||||||
let response = self.send(self.client.put(&self.route("/api/v1/push/subscription")).json(&request))?;
|
let response = self.send(self.client.put(&self.route("/api/v1/push/subscription")).json(&request)).await?;
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get all accounts that follow the authenticated user
|
/// Get all accounts that follow the authenticated user
|
||||||
pub fn follows_me(&self) -> Result<Page<Account>> {
|
pub async fn follows_me<'a>(&'a self) -> Result<Page<'a, Account>> {
|
||||||
let me = self.verify_credentials()?;
|
let me = self.verify_credentials().await?;
|
||||||
self.followers(&me.id)
|
self.followers(&me.id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get all accounts that the authenticated user follows
|
/// Get all accounts that the authenticated user follows
|
||||||
pub fn followed_by_me(&self) -> Result<Page<Account>> {
|
pub async fn followed_by_me<'a>(&'a self) -> Result<Page<'a, Account>> {
|
||||||
let me = self.verify_credentials()?;
|
let me = self.verify_credentials().await?;
|
||||||
self.following(&me.id)
|
self.following(&me.id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
/// returns events that are relevant to the authorized user, i.e. home
|
/// returns events that are relevant to the authorized user, i.e. home
|
||||||
/// timeline & notifications
|
/// timeline & notifications
|
||||||
pub fn streaming_user(&self) -> Result<MastodonStream> {
|
pub fn streaming_user(&self) -> Result<MastodonStream> {
|
||||||
@@ -367,7 +365,7 @@ impl Mastodon {
|
|||||||
url.query_pairs_mut()
|
url.query_pairs_mut()
|
||||||
.append_pair("access_token", &self.token)
|
.append_pair("access_token", &self.token)
|
||||||
.append_pair("stream", "user");
|
.append_pair("stream", "user");
|
||||||
let mut url: url::Url = reqwest::blocking::get(url.as_str())?.url().as_str().parse()?;
|
let mut url: url::Url = reqwest::get(url.as_str())?.url().as_str().parse()?;
|
||||||
let new_scheme = match url.scheme() {
|
let new_scheme = match url.scheme() {
|
||||||
"http" => "ws",
|
"http" => "ws",
|
||||||
"https" => "wss",
|
"https" => "wss",
|
||||||
@@ -503,6 +501,7 @@ impl Mastodon {
|
|||||||
|
|
||||||
Ok(EventReader(WebSocket(client)))
|
Ok(EventReader(WebSocket(client)))
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// Upload some media to the server for possible attaching to a new status
|
/// Upload some media to the server for possible attaching to a new status
|
||||||
///
|
///
|
||||||
@@ -544,14 +543,13 @@ impl Mastodon {
|
|||||||
/// ## Errors
|
/// ## Errors
|
||||||
/// This function may return an `Error::Http` before sending anything over the network if the
|
/// This function may return an `Error::Http` before sending anything over the network if the
|
||||||
/// `MediaBuilder` was supplied with a reader and a `mimetype` string which cannot be pasrsed.
|
/// `MediaBuilder` was supplied with a reader and a `mimetype` string which cannot be pasrsed.
|
||||||
pub fn media(&self, media: MediaBuilder) -> Result<Attachment> {
|
pub async fn media(&self, media: MediaBuilder) -> Result<Attachment> {
|
||||||
use media_builder::MediaBuilderData;
|
use media_builder::MediaBuilderData;
|
||||||
|
|
||||||
let mut form = multipart::Form::new();
|
let mut form = multipart::Form::new();
|
||||||
form = match media.data {
|
form = match media.data {
|
||||||
MediaBuilderData::Reader(reader) => {
|
MediaBuilderData::Reader(reader) => {
|
||||||
let mut part = multipart::Part::reader(reader);
|
let mut part = multipart::Part::stream(Body::wrap_stream(tokio_util::io::ReaderStream::new(reader)));
|
||||||
|
|
||||||
if let Some(filename) = media.filename {
|
if let Some(filename) = media.filename {
|
||||||
part = part.file_name(filename);
|
part = part.file_name(filename);
|
||||||
}
|
}
|
||||||
@@ -562,7 +560,12 @@ impl Mastodon {
|
|||||||
|
|
||||||
form.part("file", part)
|
form.part("file", part)
|
||||||
}
|
}
|
||||||
MediaBuilderData::File(file) => form.file("file", &file)?,
|
MediaBuilderData::File(file) => {
|
||||||
|
let f = tokio::fs::OpenOptions::new().read(true).open(file).await?;
|
||||||
|
let part = multipart::Part::stream(Body::wrap_stream(tokio_util::io::ReaderStream::new(f)));
|
||||||
|
form.part("file", part)
|
||||||
|
// form.file("file", &file)?
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(description) = media.description {
|
if let Some(description) = media.description {
|
||||||
@@ -573,12 +576,14 @@ impl Mastodon {
|
|||||||
form = form.text("focus", format!("{},{}", x, y));
|
form = form.text("focus", format!("{},{}", x, y));
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = self.send(self.client.post(&self.route("/api/v1/media")).multipart(form))?;
|
let response = self.send(self.client.post(&self.route("/api/v1/media")).multipart(form)).await?;
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// WebSocket newtype so that EventStream can be implemented without coherency
|
/// WebSocket newtype so that EventStream can be implemented without coherency
|
||||||
/// issues
|
/// issues
|
||||||
@@ -680,6 +685,8 @@ impl<R: EventStream> EventReader<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
impl ops::Deref for Mastodon {
|
impl ops::Deref for Mastodon {
|
||||||
type Target = Data;
|
type Target = Data;
|
||||||
|
|
||||||
@@ -750,11 +757,13 @@ impl MastodonUnauth {
|
|||||||
Ok(self.base.join(url)?)
|
Ok(self.base.join(url)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&self, req: RequestBuilder) -> Result<Response> {
|
async fn send(&self, req: RequestBuilder) -> Result<Response> {
|
||||||
let req = req.build()?;
|
let req = req.build()?;
|
||||||
Ok(self.client.execute(req)?)
|
Ok(self.client.execute(req).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
/// Get a stream of the public timeline
|
/// Get a stream of the public timeline
|
||||||
pub fn streaming_public(&self) -> Result<EventReader<WebSocket>> {
|
pub fn streaming_public(&self) -> Result<EventReader<WebSocket>> {
|
||||||
let mut url: url::Url = self.route("/api/v1/streaming/public/local")?;
|
let mut url: url::Url = self.route("/api/v1/streaming/public/local")?;
|
||||||
@@ -773,48 +782,49 @@ impl MastodonUnauth {
|
|||||||
Ok(EventReader(WebSocket(client)))
|
Ok(EventReader(WebSocket(client)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
/// GET /api/v1/statuses/:id
|
/// GET /api/v1/statuses/:id
|
||||||
pub fn get_status(&self, id: &str) -> Result<Status> {
|
pub async fn get_status(&self, id: &str) -> Result<Status> {
|
||||||
let route = self.route("/api/v1/statuses")?;
|
let route = self.route("/api/v1/statuses")?;
|
||||||
let route = route.join(id)?;
|
let route = route.join(id)?;
|
||||||
let response = self.send(self.client.get(route))?;
|
let response = self.send(self.client.get(route)).await?;
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET /api/v1/statuses/:id/context
|
/// GET /api/v1/statuses/:id/context
|
||||||
pub fn get_context(&self, id: &str) -> Result<Context> {
|
pub async fn get_context(&self, id: &str) -> Result<Context> {
|
||||||
let route = self.route("/api/v1/statuses")?;
|
let route = self.route("/api/v1/statuses")?;
|
||||||
let route = route.join(id)?;
|
let route = route.join(id)?;
|
||||||
let route = route.join("context")?;
|
let route = route.join("context")?;
|
||||||
let response = self.send(self.client.get(route))?;
|
let response = self.send(self.client.get(route)).await?;
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET /api/v1/statuses/:id/card
|
/// GET /api/v1/statuses/:id/card
|
||||||
pub fn get_card(&self, id: &str) -> Result<Card> {
|
pub async fn get_card(&self, id: &str) -> Result<Card> {
|
||||||
let route = self.route("/api/v1/statuses")?;
|
let route = self.route("/api/v1/statuses")?;
|
||||||
let route = route.join(id)?;
|
let route = route.join(id)?;
|
||||||
let route = route.join("card")?;
|
let route = route.join("card")?;
|
||||||
let response = self.send(self.client.get(route))?;
|
let response = self.send(self.client.get(route)).await?;
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the HTTP response body from JSON. Pass up deserialization errors
|
// Convert the HTTP response body from JSON. Pass up deserialization errors
|
||||||
// transparently.
|
// transparently.
|
||||||
fn deserialise<T: for<'de> serde::Deserialize<'de>>(response: Response) -> Result<T> {
|
async fn deserialise_response<T: for<'de> serde::Deserialize<'de>>(response: Response) -> Result<T> {
|
||||||
let mut reader = Tap::new(response);
|
let bytes = response.bytes().await?;
|
||||||
|
match serde_json::from_slice(&bytes) {
|
||||||
match serde_json::from_reader(&mut reader) {
|
|
||||||
Ok(t) => {
|
Ok(t) => {
|
||||||
log::debug!("{}", String::from_utf8_lossy(&reader.bytes));
|
debug!("{}", String::from_utf8_lossy(&bytes));
|
||||||
Ok(t)
|
Ok(t)
|
||||||
}
|
}
|
||||||
// If deserializing into the desired type fails try again to
|
// If deserializing into the desired type fails try again to
|
||||||
// see if this is an error response.
|
// see if this is an error response.
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("{}", String::from_utf8_lossy(&reader.bytes));
|
error!("{}", String::from_utf8_lossy(&bytes));
|
||||||
if let Ok(error) = serde_json::from_slice(&reader.bytes) {
|
if let Ok(error) = serde_json::from_slice(&bytes) {
|
||||||
return Err(Error::Api(error));
|
return Err(Error::Api(error));
|
||||||
}
|
}
|
||||||
Err(e.into())
|
Err(e.into())
|
||||||
|
|||||||
+23
-23
@@ -1,14 +1,14 @@
|
|||||||
macro_rules! methods {
|
macro_rules! methods {
|
||||||
($($method:ident,)+) => {
|
($($method:ident,)+) => {
|
||||||
$(
|
$(
|
||||||
fn $method<T: for<'de> serde::Deserialize<'de>>(&self, url: String)
|
async fn $method<T: for<'de> serde::Deserialize<'de>>(&self, url: String)
|
||||||
-> Result<T>
|
-> Result<T>
|
||||||
{
|
{
|
||||||
let response = self.send(
|
let response = self.send(
|
||||||
self.client.$method(&url)
|
self.client.$method(&url)
|
||||||
)?;
|
).await?;
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
@@ -22,13 +22,13 @@ macro_rules! route_v1_paged {
|
|||||||
"# Errors\n",
|
"# Errors\n",
|
||||||
"If `access_token` is not set.",
|
"If `access_token` is not set.",
|
||||||
),
|
),
|
||||||
pub fn $name(&self) -> Result<Page<$ret>> {
|
pub async fn $name<'a>(&'a self) -> Result<Page<'a, $ret>> {
|
||||||
let url = self.route(concat!("/api/v1/", $url));
|
let url = self.route(concat!("/api/v1/", $url));
|
||||||
let response = self.send(
|
let response = self.send(
|
||||||
self.client.$method(&url)
|
self.client.$method(&url)
|
||||||
)?;
|
).await?;
|
||||||
|
|
||||||
Page::new(self, response)
|
Page::new(self, response).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -40,7 +40,7 @@ macro_rules! route_v1_paged {
|
|||||||
"# Errors\n",
|
"# Errors\n",
|
||||||
"If `access_token` is not set.",
|
"If `access_token` is not set.",
|
||||||
),
|
),
|
||||||
pub fn $name<'a>(&self, $($param: $typ,)*) -> Result<Page<$ret>> {
|
pub async fn $name<'a, 'b>(&'b self, $($param: $typ,)*) -> Result<Page<'b, $ret>> {
|
||||||
use serde_urlencoded;
|
use serde_urlencoded;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@@ -69,9 +69,9 @@ macro_rules! route_v1_paged {
|
|||||||
|
|
||||||
let response = self.send(
|
let response = self.send(
|
||||||
self.client.get(&url)
|
self.client.get(&url)
|
||||||
)?;
|
).await?;
|
||||||
|
|
||||||
Page::new(self, response)
|
Page::new(self, response).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -85,7 +85,7 @@ macro_rules! route_v2 {
|
|||||||
"# Errors\n",
|
"# Errors\n",
|
||||||
"If `access_token` is not set."
|
"If `access_token` is not set."
|
||||||
),
|
),
|
||||||
pub fn $name<'a>(&self, $($param: $typ,)*) -> Result<$ret> {
|
pub async fn $name<'a>(&self, $($param: $typ,)*) -> Result<$ret> {
|
||||||
use serde_urlencoded;
|
use serde_urlencoded;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ macro_rules! route_v2 {
|
|||||||
|
|
||||||
let url = format!(concat!("/api/v2/", $url, "?{}"), &qs);
|
let url = format!(concat!("/api/v2/", $url, "?{}"), &qs);
|
||||||
|
|
||||||
self.get(self.route(&url))
|
self.get(self.route(&url)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -123,7 +123,7 @@ macro_rules! route_v1 {
|
|||||||
"# Errors\n",
|
"# Errors\n",
|
||||||
"If `access_token` is not set."
|
"If `access_token` is not set."
|
||||||
),
|
),
|
||||||
pub fn $name<'a>(&self, $($param: $typ,)*) -> Result<$ret> {
|
pub async fn $name<'a>(&self, $($param: $typ,)*) -> Result<$ret> {
|
||||||
use serde_urlencoded;
|
use serde_urlencoded;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ macro_rules! route_v1 {
|
|||||||
|
|
||||||
let url = format!(concat!("/api/v1/", $url, "?{}"), &qs);
|
let url = format!(concat!("/api/v1/", $url, "?{}"), &qs);
|
||||||
|
|
||||||
self.get(self.route(&url))
|
self.get(self.route(&url)).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -159,7 +159,7 @@ macro_rules! route_v1 {
|
|||||||
"# Errors\n",
|
"# Errors\n",
|
||||||
"If `access_token` is not set."
|
"If `access_token` is not set."
|
||||||
),
|
),
|
||||||
pub fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
|
pub async fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
|
||||||
|
|
||||||
let form_data = serde_json::json!({
|
let form_data = serde_json::json!({
|
||||||
$(
|
$(
|
||||||
@@ -170,7 +170,7 @@ macro_rules! route_v1 {
|
|||||||
let response = self.send(
|
let response = self.send(
|
||||||
self.client.$method(&self.route(concat!("/api/v1/", $url)))
|
self.client.$method(&self.route(concat!("/api/v1/", $url)))
|
||||||
.json(&form_data)
|
.json(&form_data)
|
||||||
)?;
|
).await?;
|
||||||
|
|
||||||
let status = response.status().clone();
|
let status = response.status().clone();
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ macro_rules! route_v1 {
|
|||||||
return Err(Error::Server(status));
|
return Err(Error::Server(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -192,8 +192,8 @@ macro_rules! route_v1 {
|
|||||||
"# Errors\n",
|
"# Errors\n",
|
||||||
"If `access_token` is not set."
|
"If `access_token` is not set."
|
||||||
),
|
),
|
||||||
pub fn $name(&self) -> Result<$ret> {
|
pub async fn $name(&self) -> Result<$ret> {
|
||||||
self.$method(self.route(concat!("/api/v1/", $url)))
|
self.$method(self.route(concat!("/api/v1/", $url))).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -207,8 +207,8 @@ macro_rules! route_v1_id {
|
|||||||
"# Errors\n",
|
"# Errors\n",
|
||||||
"If `access_token` is not set."
|
"If `access_token` is not set."
|
||||||
),
|
),
|
||||||
pub fn $name(&self, id: &str) -> Result<$ret> {
|
pub async fn $name(&self, id: &str) -> Result<$ret> {
|
||||||
self.$method(self.route(&format!(concat!("/api/v1/", $url), id)))
|
self.$method(self.route(&format!(concat!("/api/v1/", $url), id))).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,13 +221,13 @@ macro_rules! route_v1_paged_id {
|
|||||||
"# Errors\n",
|
"# Errors\n",
|
||||||
"If `access_token` is not set."
|
"If `access_token` is not set."
|
||||||
),
|
),
|
||||||
pub fn $name(&self, id: &str) -> Result<Page<$ret>> {
|
pub async fn $name<'a>(&'a self, id: &str) -> Result<Page<'a, $ret>> {
|
||||||
let url = self.route(&format!(concat!("/api/v1/", $url), id));
|
let url = self.route(&format!(concat!("/api/v1/", $url), id));
|
||||||
let response = self.send(
|
let response = self.send(
|
||||||
self.client.$method(&url)
|
self.client.$method(&url)
|
||||||
)?;
|
).await?;
|
||||||
|
|
||||||
Page::new(self, response)
|
Page::new(self, response).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,383 +0,0 @@
|
|||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
entities::prelude::*,
|
|
||||||
errors::Result,
|
|
||||||
media_builder::MediaBuilder,
|
|
||||||
page::Page,
|
|
||||||
requests::{AddFilterRequest, AddPushRequest, StatusesRequest, UpdateCredsRequest, UpdatePushRequest},
|
|
||||||
status_builder::NewStatus,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// 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 {
|
|
||||||
/// Type that wraps streaming API streams
|
|
||||||
type Stream: Iterator<Item = Event>;
|
|
||||||
|
|
||||||
/// GET /api/v1/favourites
|
|
||||||
fn favourites(&self) -> Result<Page<Status>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/blocks
|
|
||||||
fn blocks(&self) -> Result<Page<Account>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/domain_blocks
|
|
||||||
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>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/timelines/home
|
|
||||||
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>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/mutes
|
|
||||||
fn mutes(&self) -> Result<Page<Account>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/notifications
|
|
||||||
fn notifications(&self) -> Result<Page<Notification>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/reports
|
|
||||||
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>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/accounts/:id/following
|
|
||||||
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>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/statuses/:id/favourited_by
|
|
||||||
fn favourited_by(&self, id: &str) -> Result<Page<Account>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// DELETE /api/v1/domain_blocks
|
|
||||||
fn unblock_domain(&self, domain: String) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/instance
|
|
||||||
fn instance(&self) -> Result<Instance> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/accounts/verify_credentials
|
|
||||||
fn verify_credentials(&self) -> Result<Account> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/reports
|
|
||||||
fn report(&self, account_id: &str, status_ids: Vec<&str>, comment: String) -> Result<Report> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/domain_blocks
|
|
||||||
fn block_domain(&self, domain: String) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/accounts/follow_requests/authorize
|
|
||||||
fn authorize_follow_request(&self, id: &str) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/accounts/follow_requests/reject
|
|
||||||
fn reject_follow_request(&self, id: &str) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/search
|
|
||||||
fn search(&self, q: &'_ str, resolve: bool) -> Result<SearchResult> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v2/search
|
|
||||||
fn search_v2(&self, q: &'_ str, resolve: bool) -> Result<SearchResultV2> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/follows
|
|
||||||
fn follows(&self, uri: Cow<'static, str>) -> Result<Account> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/media
|
|
||||||
fn media(&self, media_builder: MediaBuilder) -> Result<Attachment> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/notifications/clear
|
|
||||||
fn clear_notifications(&self) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/notifications/dismiss
|
|
||||||
fn dismiss_notification(&self, id: &str) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/accounts/:id
|
|
||||||
fn get_account(&self, id: &str) -> Result<Account> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/accounts/:id/follow
|
|
||||||
fn follow(&self, id: &str) -> Result<Relationship> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/accounts/:id/unfollow
|
|
||||||
fn unfollow(&self, id: &str) -> Result<Relationship> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/accounts/:id/block
|
|
||||||
fn block(&self, id: &str) -> Result<Relationship> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/accounts/:id/unblock
|
|
||||||
fn unblock(&self, id: &str) -> Result<Relationship> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/accounts/:id/mute
|
|
||||||
fn mute(&self, id: &str) -> Result<Relationship> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/accounts/:id/unmute
|
|
||||||
fn unmute(&self, id: &str) -> Result<Relationship> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/notifications/:id
|
|
||||||
fn get_notification(&self, id: &str) -> Result<Notification> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/statuses/:id
|
|
||||||
fn get_status(&self, id: &str) -> Result<Status> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/statuses/:id/context
|
|
||||||
fn get_context(&self, id: &str) -> Result<Context> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/statuses/:id/card
|
|
||||||
fn get_card(&self, id: &str) -> Result<Card> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/statuses/:id/reblog
|
|
||||||
fn reblog(&self, id: &str) -> Result<Status> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/statuses/:id/unreblog
|
|
||||||
fn unreblog(&self, id: &str) -> Result<Status> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/statuses/:id/favourite
|
|
||||||
fn favourite(&self, id: &str) -> Result<Status> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/statuses/:id/unfavourite
|
|
||||||
fn unfavourite(&self, id: &str) -> Result<Status> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// DELETE /api/v1/statuses/:id
|
|
||||||
fn delete_status(&self, id: &str) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// PATCH /api/v1/accounts/update_credentials
|
|
||||||
fn update_credentials(&self, builder: &mut UpdateCredsRequest) -> Result<Account> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/statuses
|
|
||||||
fn new_status(&self, status: NewStatus) -> Result<Status> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/timelines/public?local=true
|
|
||||||
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>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/timelines/tag/:hashtag
|
|
||||||
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>>
|
|
||||||
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>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/accounts/search?q=:query&limit=:limit&following=:following
|
|
||||||
fn search_accounts(&self, query: &str, limit: Option<u64>, following: bool) -> Result<Page<Account>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/push/subscription
|
|
||||||
fn add_push_subscription(&self, request: &AddPushRequest) -> Result<Subscription> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// PUT /api/v1/push/subscription
|
|
||||||
fn update_push_data(&self, request: &UpdatePushRequest) -> Result<Subscription> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/push/subscription
|
|
||||||
fn get_push_subscription(&self) -> Result<Subscription> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// DELETE /api/v1/push/subscription
|
|
||||||
fn delete_push_subscription(&self) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/filters
|
|
||||||
fn get_filters(&self) -> Result<Vec<Filter>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/filters
|
|
||||||
fn add_filter(&self, request: &mut AddFilterRequest) -> Result<Filter> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/filters/:id
|
|
||||||
fn get_filter(&self, id: &str) -> Result<Filter> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// PUT /api/v1/filters/:id
|
|
||||||
fn update_filter(&self, id: &str, request: &mut AddFilterRequest) -> Result<Filter> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// DELETE /api/v1/filters/:id
|
|
||||||
fn delete_filter(&self, id: &str) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/suggestions
|
|
||||||
fn get_follow_suggestions(&self) -> Result<Vec<Account>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// DELETE /api/v1/suggestions/:account_id
|
|
||||||
fn delete_from_suggestions(&self, id: &str) -> Result<Empty> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/endorsements
|
|
||||||
fn get_endorsements(&self) -> Result<Page<Account>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/accounts/:id/pin
|
|
||||||
fn endorse_user(&self, id: &str) -> Result<Relationship> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// POST /api/v1/accounts/:id/unpin
|
|
||||||
fn unendorse_user(&self, id: &str) -> Result<Relationship> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// 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<dyn 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(())
|
|
||||||
/// # }
|
|
||||||
fn follows_me(&self) -> Result<Page<Account>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// Shortcut for
|
|
||||||
/// `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<dyn 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(())
|
|
||||||
/// # }
|
|
||||||
fn followed_by_me(&self) -> Result<Page<Account>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns events that are relevant to the authorized user, i.e. home
|
|
||||||
/// timeline and notifications
|
|
||||||
fn streaming_user(&self) -> Result<Self::Stream> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all public statuses
|
|
||||||
fn streaming_public(&self) -> Result<Self::Stream> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all local statuses
|
|
||||||
fn streaming_local(&self) -> Result<Self::Stream> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all public statuses for a particular hashtag
|
|
||||||
fn streaming_public_hashtag(&self, hashtag: &str) -> Result<Self::Stream> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all local statuses for a particular hashtag
|
|
||||||
fn streaming_local_hashtag(&self, hashtag: &str) -> Result<Self::Stream> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns statuses for a list
|
|
||||||
fn streaming_list(&self, list_id: &str) -> Result<Self::Stream> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all direct messages
|
|
||||||
fn streaming_direct(&self) -> Result<Self::Stream> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait that represents clients that can make unauthenticated calls to a
|
|
||||||
/// mastodon instance
|
|
||||||
#[allow(unused)]
|
|
||||||
pub trait MastodonUnauthenticated {
|
|
||||||
/// GET /api/v1/statuses/:id
|
|
||||||
fn get_status(&self, id: &str) -> Result<Status> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/statuses/:id/context
|
|
||||||
fn get_context(&self, id: &str) -> Result<Context> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/statuses/:id/card
|
|
||||||
fn get_card(&self, id: &str) -> Result<Card> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
/// GET /api/v1/statuses/:id/reblogged_by
|
|
||||||
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>> {
|
|
||||||
unimplemented!("This method was not implemented");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Read;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use tokio::io::AsyncRead;
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// A builder pattern struct for preparing a single attachment for upload.
|
/// A builder pattern struct for preparing a single attachment for upload.
|
||||||
@@ -28,7 +29,7 @@ pub struct MediaBuilder {
|
|||||||
/// Enum representing possible sources of attachments to upload
|
/// Enum representing possible sources of attachments to upload
|
||||||
pub enum MediaBuilderData {
|
pub enum MediaBuilderData {
|
||||||
/// An arbitrary reader. It is useful for reading from media already in memory.
|
/// An arbitrary reader. It is useful for reading from media already in memory.
|
||||||
Reader(Box<dyn Read + Send>),
|
Reader(Pin<Box<dyn AsyncRead + Send + Sync>>),
|
||||||
|
|
||||||
/// Variant represening a file path of the file to attach.
|
/// Variant represening a file path of the file to attach.
|
||||||
File(PathBuf),
|
File(PathBuf),
|
||||||
@@ -45,9 +46,9 @@ impl fmt::Debug for MediaBuilderData {
|
|||||||
|
|
||||||
impl MediaBuilder {
|
impl MediaBuilder {
|
||||||
/// Create a new MediaBuilder from a reader `data`
|
/// Create a new MediaBuilder from a reader `data`
|
||||||
pub fn from_reader<R: Read + Send + 'static>(data: R) -> MediaBuilder {
|
pub fn from_reader<R: AsyncRead + Send + Sync + 'static>(data: R) -> MediaBuilder {
|
||||||
MediaBuilder {
|
MediaBuilder {
|
||||||
data: MediaBuilderData::Reader(Box::from(data)),
|
data: MediaBuilderData::Reader(Box::pin(data)),
|
||||||
filename: None,
|
filename: None,
|
||||||
mimetype: None,
|
mimetype: None,
|
||||||
description: None,
|
description: None,
|
||||||
|
|||||||
+8
-8
@@ -1,7 +1,7 @@
|
|||||||
use super::{deserialise, Mastodon, Result};
|
use super::{deserialise_response, Mastodon, Result};
|
||||||
use crate::entities::itemsiter::ItemsIter;
|
use crate::entities::itemsiter::ItemsIter;
|
||||||
use hyper_old_types::header::{parsing, Link, RelationType};
|
use hyper_old_types::header::{parsing, Link, RelationType};
|
||||||
use reqwest::{blocking::Response, header::LINK};
|
use reqwest::{Response, header::LINK};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ macro_rules! pages {
|
|||||||
$(
|
$(
|
||||||
doc_comment::doc_comment!(concat!(
|
doc_comment::doc_comment!(concat!(
|
||||||
"Method to retrieve the ", stringify!($direction), " page of results"),
|
"Method to retrieve the ", stringify!($direction), " page of results"),
|
||||||
pub fn $fun(&mut self) -> Result<Option<Vec<T>>> {
|
pub async fn $fun(&mut self) -> Result<Option<Vec<T>>> {
|
||||||
let url = match self.$direction.take() {
|
let url = match self.$direction.take() {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
@@ -19,13 +19,13 @@ macro_rules! pages {
|
|||||||
|
|
||||||
let response = self.mastodon.send(
|
let response = self.mastodon.send(
|
||||||
self.mastodon.client.get(url)
|
self.mastodon.client.get(url)
|
||||||
)?;
|
).await?;
|
||||||
|
|
||||||
let (prev, next) = get_links(&response)?;
|
let (prev, next) = get_links(&response)?;
|
||||||
self.next = next;
|
self.next = next;
|
||||||
self.prev = prev;
|
self.prev = prev;
|
||||||
|
|
||||||
deserialise(response)
|
deserialise_response(response).await
|
||||||
});
|
});
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
@@ -107,10 +107,10 @@ impl<'a, T: for<'de> Deserialize<'de>> Page<'a, T> {
|
|||||||
prev: prev_page
|
prev: prev_page
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(mastodon: &'a Mastodon, response: Response) -> Result<Self> {
|
pub(crate) async fn new<'m>(mastodon: &'m Mastodon, response: Response) -> Result<Page<'m, T>> {
|
||||||
let (prev, next) = get_links(&response)?;
|
let (prev, next) = get_links(&response)?;
|
||||||
Ok(Page {
|
Ok(Page {
|
||||||
initial_items: deserialise(response)?,
|
initial_items: deserialise_response(response).await?,
|
||||||
next,
|
next,
|
||||||
prev,
|
prev,
|
||||||
mastodon,
|
mastodon,
|
||||||
@@ -189,7 +189,7 @@ impl<'a, T: Clone + for<'de> Deserialize<'de>> Page<'a, T> {
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn items_iter(self) -> impl Iterator<Item = T> + 'a
|
pub fn items_iter(self) -> ItemsIter<'a, T>
|
||||||
where
|
where
|
||||||
T: 'a,
|
T: 'a,
|
||||||
{
|
{
|
||||||
|
|||||||
+14
-13
@@ -1,6 +1,6 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use reqwest::blocking::{Client, RequestBuilder, Response};
|
use reqwest::{Client, RequestBuilder, Response};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
@@ -93,9 +93,9 @@ impl<'a> Registration<'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&self, req: RequestBuilder) -> Result<Response> {
|
async fn send(&self, req: RequestBuilder) -> Result<Response> {
|
||||||
let req = req.build()?;
|
let req = req.build()?;
|
||||||
Ok(self.client.execute(req)?)
|
Ok(self.client.execute(req).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register the given application
|
/// Register the given application
|
||||||
@@ -119,12 +119,12 @@ impl<'a> Registration<'a> {
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn register<I: TryInto<App>>(&mut self, app: I) -> Result<Registered>
|
pub async fn register<I: TryInto<App>>(&mut self, app: I) -> Result<Registered>
|
||||||
where
|
where
|
||||||
Error: From<<I as TryInto<App>>::Error>,
|
Error: From<<I as TryInto<App>>::Error>,
|
||||||
{
|
{
|
||||||
let app = app.try_into()?;
|
let app = app.try_into()?;
|
||||||
let oauth = self.send_app(&app)?;
|
let oauth = self.send_app(&app).await?;
|
||||||
|
|
||||||
Ok(Registered {
|
Ok(Registered {
|
||||||
base: self.base.clone(),
|
base: self.base.clone(),
|
||||||
@@ -157,9 +157,9 @@ impl<'a> Registration<'a> {
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn build(&mut self) -> Result<Registered> {
|
pub async fn build(&mut self) -> Result<Registered> {
|
||||||
let app: App = self.app_builder.clone().build()?;
|
let app: App = self.app_builder.clone().build()?;
|
||||||
let oauth = self.send_app(&app)?;
|
let oauth = self.send_app(&app).await?;
|
||||||
|
|
||||||
Ok(Registered {
|
Ok(Registered {
|
||||||
base: self.base.clone(),
|
base: self.base.clone(),
|
||||||
@@ -172,9 +172,10 @@ impl<'a> Registration<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_app(&self, app: &App) -> Result<OAuth> {
|
async fn send_app(&self, app: &App) -> Result<OAuth> {
|
||||||
let url = format!("{}/api/v1/apps", self.base);
|
let url = format!("{}/api/v1/apps", self.base);
|
||||||
Ok(self.send(self.client.post(&url).json(&app))?.json()?)
|
Ok(self.send(self.client.post(&url).json(&app)).await?
|
||||||
|
.json().await?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,9 +229,9 @@ impl Registered {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Registered {
|
impl Registered {
|
||||||
fn send(&self, req: RequestBuilder) -> Result<Response> {
|
async fn send(&self, req: RequestBuilder) -> Result<Response> {
|
||||||
let req = req.build()?;
|
let req = req.build()?;
|
||||||
Ok(self.client.execute(req)?)
|
Ok(self.client.execute(req).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the parts of the `Registered` struct that can be used to
|
/// Returns the parts of the `Registered` struct that can be used to
|
||||||
@@ -298,14 +299,14 @@ impl Registered {
|
|||||||
|
|
||||||
/// Create an access token from the client id, client secret, and code
|
/// Create an access token from the client id, client secret, and code
|
||||||
/// provided by the authorisation url.
|
/// provided by the authorisation url.
|
||||||
pub fn complete(&self, code: &str) -> Result<Mastodon> {
|
pub async fn complete(&self, code: &str) -> Result<Mastodon> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/oauth/token?client_id={}&client_secret={}&code={}&grant_type=authorization_code&\
|
"{}/oauth/token?client_id={}&client_secret={}&code={}&grant_type=authorization_code&\
|
||||||
redirect_uri={}",
|
redirect_uri={}",
|
||||||
self.base, self.client_id, self.client_secret, code, self.redirect
|
self.base, self.client_id, self.client_secret, code, self.redirect
|
||||||
);
|
);
|
||||||
|
|
||||||
let token: AccessToken = self.send(self.client.post(&url))?.json()?;
|
let token: AccessToken = self.send(self.client.post(&url)).await?.json().await?;
|
||||||
|
|
||||||
let data = Data {
|
let data = Data {
|
||||||
base: self.base.clone().into(),
|
base: self.base.clone().into(),
|
||||||
|
|||||||
Reference in New Issue
Block a user