client: Put client-api specific functionality behind a feature flag

This commit is contained in:
Jonas Platte 2021-04-26 22:25:56 +02:00
parent 2b04cacc82
commit e2be614552
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
3 changed files with 177 additions and 159 deletions

View File

@ -14,32 +14,11 @@ readme = "README.md"
repository = "https://github.com/ruma/ruma"
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]
default = ["http1", "http2", "tls-native"]
client-api = ["ruma-client-api"]
http1 = ["hyper/http1"]
http2 = ["hyper/http2"]
tls-native = ["hyper-tls", "_tls"]
@ -57,3 +36,34 @@ tls-rustls-webpki-roots = [
# Internal, not meant to be used directly
_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"]

View 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;
}
}
}
}

View File

@ -7,7 +7,7 @@
//! Begin by creating a `Client` type, usually using the `https` method for a client that supports
//! secure connections, and then logging in:
//!
//! ```no_run
//! ```ignore
//! use ruma_client::Client;
//!
//! let work = async {
@ -43,7 +43,7 @@
//! For the standard use case of synchronizing with the homeserver (i.e. getting all the latest
//! events), use the `Client::sync`:
//!
//! ```no_run
//! ```ignore
//! use std::time::Duration;
//!
//! # use ruma_client::Client;
@ -105,22 +105,16 @@
use std::{
collections::BTreeMap,
sync::{Arc, Mutex},
time::Duration,
};
use assign::assign;
use async_stream::try_stream;
use futures_core::stream::Stream;
use http::{uri::Uri, Response as HttpResponse};
use hyper::client::{Client as HyperClient, HttpConnector};
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;
#[cfg(feature = "client-api")]
mod client_api;
mod error;
mod session;
@ -203,132 +197,6 @@ impl Client {
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.
pub async fn request<Request: OutgoingRequest>(
&self,