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"
|
||||
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"]
|
||||
|
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
|
||||
//! 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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user