client: Put client-api specific functionality behind a feature flag
This commit is contained in:
parent
2b04cacc82
commit
e2be614552
@ -14,32 +14,11 @@ readme = "README.md"
|
|||||||
repository = "https://github.com/ruma/ruma"
|
repository = "https://github.com/ruma/ruma"
|
||||||
version = "0.5.0-alpha.2"
|
version = "0.5.0-alpha.2"
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
assign = "1.1.1"
|
|
||||||
async-stream = "0.3.0"
|
|
||||||
futures-core = "0.3.8"
|
|
||||||
http = "0.2.2"
|
|
||||||
hyper = { version = "0.14.2", features = ["client", "tcp"] }
|
|
||||||
hyper-tls = { version = "0.5.0", optional = true }
|
|
||||||
hyper-rustls = { version = "0.22.1", optional = true, default-features = false }
|
|
||||||
ruma-api = { version = "=0.17.0-alpha.4", path = "../ruma-api" }
|
|
||||||
ruma-client-api = { version = "=0.10.0-alpha.3", path = "../ruma-client-api", features = ["client"] }
|
|
||||||
ruma-common = { version = "0.5.0", path = "../ruma-common" }
|
|
||||||
ruma-events = { version = "=0.22.0-alpha.3", path = "../ruma-events" }
|
|
||||||
ruma-identifiers = { version = "0.19.0", path = "../ruma-identifiers" }
|
|
||||||
ruma-serde = { version = "0.3.1", path = "../ruma-serde" }
|
|
||||||
serde = { version = "1.0.118", features = ["derive"] }
|
|
||||||
serde_json = "1.0.61"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
anyhow = "1.0.37"
|
|
||||||
ruma = { version = "0.0.3", path = "../ruma", features = ["client-api-c"] }
|
|
||||||
tokio = { version = "1.0.1", features = ["macros", "rt"] }
|
|
||||||
tokio-stream = { version = "0.1.1", default-features = false }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["http1", "http2", "tls-native"]
|
default = ["http1", "http2", "tls-native"]
|
||||||
|
|
||||||
|
client-api = ["ruma-client-api"]
|
||||||
|
|
||||||
http1 = ["hyper/http1"]
|
http1 = ["hyper/http1"]
|
||||||
http2 = ["hyper/http2"]
|
http2 = ["hyper/http2"]
|
||||||
tls-native = ["hyper-tls", "_tls"]
|
tls-native = ["hyper-tls", "_tls"]
|
||||||
@ -57,3 +36,34 @@ tls-rustls-webpki-roots = [
|
|||||||
# Internal, not meant to be used directly
|
# Internal, not meant to be used directly
|
||||||
_tls = []
|
_tls = []
|
||||||
_tls-rustls = ["_tls"]
|
_tls-rustls = ["_tls"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
assign = "1.1.1"
|
||||||
|
async-stream = "0.3.0"
|
||||||
|
futures-core = "0.3.8"
|
||||||
|
http = "0.2.2"
|
||||||
|
hyper = { version = "0.14.2", features = ["client", "tcp"] }
|
||||||
|
hyper-tls = { version = "0.5.0", optional = true }
|
||||||
|
hyper-rustls = { version = "0.22.1", optional = true, default-features = false }
|
||||||
|
ruma-api = { version = "=0.17.0-alpha.4", path = "../ruma-api" }
|
||||||
|
ruma-client-api = { version = "=0.10.0-alpha.3", path = "../ruma-client-api", optional = true, features = ["client"] }
|
||||||
|
ruma-common = { version = "0.5.0", path = "../ruma-common" }
|
||||||
|
ruma-events = { version = "=0.22.0-alpha.3", path = "../ruma-events" }
|
||||||
|
ruma-identifiers = { version = "0.19.0", path = "../ruma-identifiers" }
|
||||||
|
ruma-serde = { version = "0.3.1", path = "../ruma-serde" }
|
||||||
|
serde = { version = "1.0.118", features = ["derive"] }
|
||||||
|
serde_json = "1.0.61"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
anyhow = "1.0.37"
|
||||||
|
ruma = { version = "0.0.3", path = "../ruma", features = ["client-api-c"] }
|
||||||
|
tokio = { version = "1.0.1", features = ["macros", "rt"] }
|
||||||
|
tokio-stream = { version = "0.1.1", default-features = false }
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "hello_world"
|
||||||
|
required-features = ["client-api"]
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "message_log"
|
||||||
|
required-features = ["client-api"]
|
||||||
|
140
ruma-client/src/client_api.rs
Normal file
140
ruma-client/src/client_api.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use assign::assign;
|
||||||
|
use async_stream::try_stream;
|
||||||
|
use futures_core::stream::Stream;
|
||||||
|
use ruma_client_api::r0::sync::sync_events::{
|
||||||
|
Filter as SyncFilter, Request as SyncRequest, Response as SyncResponse,
|
||||||
|
};
|
||||||
|
use ruma_common::presence::PresenceState;
|
||||||
|
use ruma_identifiers::DeviceId;
|
||||||
|
|
||||||
|
use super::{Client, Error, Identification, Session};
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
/// Log in with a username and password.
|
||||||
|
///
|
||||||
|
/// In contrast to `api::r0::session::login::call()`, this method stores the
|
||||||
|
/// session data returned by the endpoint in this client, instead of
|
||||||
|
/// returning it.
|
||||||
|
pub async fn log_in(
|
||||||
|
&self,
|
||||||
|
user: &str,
|
||||||
|
password: &str,
|
||||||
|
device_id: Option<&DeviceId>,
|
||||||
|
initial_device_display_name: Option<&str>,
|
||||||
|
) -> Result<Session, Error<ruma_client_api::Error>> {
|
||||||
|
use ruma_client_api::r0::session::login::{
|
||||||
|
LoginInfo, Request as LoginRequest, UserIdentifier,
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.request(assign!(
|
||||||
|
LoginRequest::new(
|
||||||
|
LoginInfo::Password { identifier: UserIdentifier::MatrixId(user), password }
|
||||||
|
), {
|
||||||
|
device_id,
|
||||||
|
initial_device_display_name,
|
||||||
|
}
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let session = Session {
|
||||||
|
access_token: response.access_token,
|
||||||
|
identification: Some(Identification {
|
||||||
|
device_id: response.device_id,
|
||||||
|
user_id: response.user_id,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
*self.0.session.lock().unwrap() = Some(session.clone());
|
||||||
|
|
||||||
|
Ok(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register as a guest. In contrast to `api::r0::account::register::call()`,
|
||||||
|
/// this method stores the session data returned by the endpoint in this
|
||||||
|
/// client, instead of returning it.
|
||||||
|
pub async fn register_guest(
|
||||||
|
&self,
|
||||||
|
) -> Result<Session, Error<ruma_client_api::r0::uiaa::UiaaResponse>> {
|
||||||
|
use ruma_client_api::r0::account::register::{self, RegistrationKind};
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.request(assign!(register::Request::new(), { kind: RegistrationKind::Guest }))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let session = Session {
|
||||||
|
// since we supply inhibit_login: false above, the access token needs to be there
|
||||||
|
// TODO: maybe unwrap is not the best solution though
|
||||||
|
access_token: response.access_token.unwrap(),
|
||||||
|
identification: Some(Identification {
|
||||||
|
// same as access_token
|
||||||
|
device_id: response.device_id.unwrap(),
|
||||||
|
user_id: response.user_id,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
*self.0.session.lock().unwrap() = Some(session.clone());
|
||||||
|
|
||||||
|
Ok(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register as a new user on this server.
|
||||||
|
///
|
||||||
|
/// In contrast to `api::r0::account::register::call()`, this method stores
|
||||||
|
/// the session data returned by the endpoint in this client, instead of
|
||||||
|
/// returning it.
|
||||||
|
///
|
||||||
|
/// The username is the local part of the returned user_id. If it is
|
||||||
|
/// omitted from this request, the server will generate one.
|
||||||
|
pub async fn register_user(
|
||||||
|
&self,
|
||||||
|
username: Option<&str>,
|
||||||
|
password: &str,
|
||||||
|
) -> Result<Session, Error<ruma_client_api::r0::uiaa::UiaaResponse>> {
|
||||||
|
use ruma_client_api::r0::account::register;
|
||||||
|
|
||||||
|
let response = self
|
||||||
|
.request(assign!(register::Request::new(), { username, password: Some(password) }))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let session = Session {
|
||||||
|
// since we supply inhibit_login: false above, the access token needs to be there
|
||||||
|
// TODO: maybe unwrap is not the best solution though
|
||||||
|
access_token: response.access_token.unwrap(),
|
||||||
|
identification: Some(Identification {
|
||||||
|
// same as access_token
|
||||||
|
device_id: response.device_id.unwrap(),
|
||||||
|
user_id: response.user_id,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
*self.0.session.lock().unwrap() = Some(session.clone());
|
||||||
|
|
||||||
|
Ok(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method that represents repeated calls to the sync_events endpoint as a stream.
|
||||||
|
pub fn sync<'a>(
|
||||||
|
&self,
|
||||||
|
filter: Option<&'a SyncFilter<'a>>,
|
||||||
|
mut since: String,
|
||||||
|
set_presence: &'a PresenceState,
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
) -> impl Stream<Item = Result<SyncResponse, Error<ruma_client_api::Error>>> + 'a {
|
||||||
|
let client = self.clone();
|
||||||
|
try_stream! {
|
||||||
|
loop {
|
||||||
|
let response = client
|
||||||
|
.request(assign!(SyncRequest::new(), {
|
||||||
|
filter,
|
||||||
|
since: Some(&since),
|
||||||
|
set_presence,
|
||||||
|
timeout,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
since = response.next_batch.clone();
|
||||||
|
yield response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@
|
|||||||
//! Begin by creating a `Client` type, usually using the `https` method for a client that supports
|
//! Begin by creating a `Client` type, usually using the `https` method for a client that supports
|
||||||
//! secure connections, and then logging in:
|
//! secure connections, and then logging in:
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```ignore
|
||||||
//! use ruma_client::Client;
|
//! use ruma_client::Client;
|
||||||
//!
|
//!
|
||||||
//! let work = async {
|
//! let work = async {
|
||||||
@ -43,7 +43,7 @@
|
|||||||
//! For the standard use case of synchronizing with the homeserver (i.e. getting all the latest
|
//! For the standard use case of synchronizing with the homeserver (i.e. getting all the latest
|
||||||
//! events), use the `Client::sync`:
|
//! events), use the `Client::sync`:
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```ignore
|
||||||
//! use std::time::Duration;
|
//! use std::time::Duration;
|
||||||
//!
|
//!
|
||||||
//! # use ruma_client::Client;
|
//! # use ruma_client::Client;
|
||||||
@ -105,22 +105,16 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use assign::assign;
|
use assign::assign;
|
||||||
use async_stream::try_stream;
|
|
||||||
use futures_core::stream::Stream;
|
|
||||||
use http::{uri::Uri, Response as HttpResponse};
|
use http::{uri::Uri, Response as HttpResponse};
|
||||||
use hyper::client::{Client as HyperClient, HttpConnector};
|
use hyper::client::{Client as HyperClient, HttpConnector};
|
||||||
use ruma_api::{AuthScheme, OutgoingRequest, SendAccessToken};
|
use ruma_api::{AuthScheme, OutgoingRequest, SendAccessToken};
|
||||||
use ruma_client_api::r0::sync::sync_events::{
|
|
||||||
Filter as SyncFilter, Request as SyncRequest, Response as SyncResponse,
|
|
||||||
};
|
|
||||||
use ruma_common::presence::PresenceState;
|
|
||||||
use ruma_identifiers::DeviceId;
|
|
||||||
use ruma_serde::urlencoded;
|
use ruma_serde::urlencoded;
|
||||||
|
|
||||||
|
#[cfg(feature = "client-api")]
|
||||||
|
mod client_api;
|
||||||
mod error;
|
mod error;
|
||||||
mod session;
|
mod session;
|
||||||
|
|
||||||
@ -203,132 +197,6 @@ impl Client {
|
|||||||
self.0.session.lock().expect("session mutex was poisoned").clone()
|
self.0.session.lock().expect("session mutex was poisoned").clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Log in with a username and password.
|
|
||||||
///
|
|
||||||
/// In contrast to `api::r0::session::login::call()`, this method stores the
|
|
||||||
/// session data returned by the endpoint in this client, instead of
|
|
||||||
/// returning it.
|
|
||||||
pub async fn log_in(
|
|
||||||
&self,
|
|
||||||
user: &str,
|
|
||||||
password: &str,
|
|
||||||
device_id: Option<&DeviceId>,
|
|
||||||
initial_device_display_name: Option<&str>,
|
|
||||||
) -> Result<Session, Error<ruma_client_api::Error>> {
|
|
||||||
use ruma_client_api::r0::session::login::{
|
|
||||||
LoginInfo, Request as LoginRequest, UserIdentifier,
|
|
||||||
};
|
|
||||||
|
|
||||||
let response = self
|
|
||||||
.request(assign!(
|
|
||||||
LoginRequest::new(
|
|
||||||
LoginInfo::Password { identifier: UserIdentifier::MatrixId(user), password }
|
|
||||||
), {
|
|
||||||
device_id,
|
|
||||||
initial_device_display_name,
|
|
||||||
}
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let session = Session {
|
|
||||||
access_token: response.access_token,
|
|
||||||
identification: Some(Identification {
|
|
||||||
device_id: response.device_id,
|
|
||||||
user_id: response.user_id,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
*self.0.session.lock().unwrap() = Some(session.clone());
|
|
||||||
|
|
||||||
Ok(session)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register as a guest. In contrast to `api::r0::account::register::call()`,
|
|
||||||
/// this method stores the session data returned by the endpoint in this
|
|
||||||
/// client, instead of returning it.
|
|
||||||
pub async fn register_guest(
|
|
||||||
&self,
|
|
||||||
) -> Result<Session, Error<ruma_client_api::r0::uiaa::UiaaResponse>> {
|
|
||||||
use ruma_client_api::r0::account::register::{self, RegistrationKind};
|
|
||||||
|
|
||||||
let response = self
|
|
||||||
.request(assign!(register::Request::new(), { kind: RegistrationKind::Guest }))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let session = Session {
|
|
||||||
// since we supply inhibit_login: false above, the access token needs to be there
|
|
||||||
// TODO: maybe unwrap is not the best solution though
|
|
||||||
access_token: response.access_token.unwrap(),
|
|
||||||
identification: Some(Identification {
|
|
||||||
// same as access_token
|
|
||||||
device_id: response.device_id.unwrap(),
|
|
||||||
user_id: response.user_id,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
*self.0.session.lock().unwrap() = Some(session.clone());
|
|
||||||
|
|
||||||
Ok(session)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register as a new user on this server.
|
|
||||||
///
|
|
||||||
/// In contrast to `api::r0::account::register::call()`, this method stores
|
|
||||||
/// the session data returned by the endpoint in this client, instead of
|
|
||||||
/// returning it.
|
|
||||||
///
|
|
||||||
/// The username is the local part of the returned user_id. If it is
|
|
||||||
/// omitted from this request, the server will generate one.
|
|
||||||
pub async fn register_user(
|
|
||||||
&self,
|
|
||||||
username: Option<&str>,
|
|
||||||
password: &str,
|
|
||||||
) -> Result<Session, Error<ruma_client_api::r0::uiaa::UiaaResponse>> {
|
|
||||||
use ruma_client_api::r0::account::register;
|
|
||||||
|
|
||||||
let response = self
|
|
||||||
.request(assign!(register::Request::new(), { username, password: Some(password) }))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let session = Session {
|
|
||||||
// since we supply inhibit_login: false above, the access token needs to be there
|
|
||||||
// TODO: maybe unwrap is not the best solution though
|
|
||||||
access_token: response.access_token.unwrap(),
|
|
||||||
identification: Some(Identification {
|
|
||||||
// same as access_token
|
|
||||||
device_id: response.device_id.unwrap(),
|
|
||||||
user_id: response.user_id,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
*self.0.session.lock().unwrap() = Some(session.clone());
|
|
||||||
|
|
||||||
Ok(session)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convenience method that represents repeated calls to the sync_events endpoint as a stream.
|
|
||||||
pub fn sync<'a>(
|
|
||||||
&self,
|
|
||||||
filter: Option<&'a SyncFilter<'a>>,
|
|
||||||
mut since: String,
|
|
||||||
set_presence: &'a PresenceState,
|
|
||||||
timeout: Option<Duration>,
|
|
||||||
) -> impl Stream<Item = Result<SyncResponse, Error<ruma_client_api::Error>>> + 'a {
|
|
||||||
let client = self.clone();
|
|
||||||
try_stream! {
|
|
||||||
loop {
|
|
||||||
let response = client
|
|
||||||
.request(assign!(SyncRequest::new(), {
|
|
||||||
filter,
|
|
||||||
since: Some(&since),
|
|
||||||
set_presence,
|
|
||||||
timeout,
|
|
||||||
}))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
since = response.next_batch.clone();
|
|
||||||
yield response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Makes a request to a Matrix API endpoint.
|
/// Makes a request to a Matrix API endpoint.
|
||||||
pub async fn request<Request: OutgoingRequest>(
|
pub async fn request<Request: OutgoingRequest>(
|
||||||
&self,
|
&self,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user