request_builder: test GetMessageBuilder

master
Devin R 2020-04-11 08:46:45 -04:00
parent 6358db94c7
commit 7aeeeea432
3 changed files with 214 additions and 26 deletions

View File

@ -40,7 +40,7 @@ pub use ruma_events::EventType;
use ruma_identifiers::{RoomId, RoomIdOrAliasId, UserId}; use ruma_identifiers::{RoomId, RoomIdOrAliasId, UserId};
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
use ruma_identifiers::{DeviceId, UserId}; use ruma_identifiers::DeviceId;
use crate::api; use crate::api;
use crate::base_client::Client as BaseClient; use crate::base_client::Client as BaseClient;
@ -190,6 +190,7 @@ use api::r0::membership::{
Invite3pid, Invite3pid,
}; };
use api::r0::message::create_message_event; use api::r0::message::create_message_event;
use api::r0::message::get_message_events;
use api::r0::room::create_room; use api::r0::room::create_room;
use api::r0::session::login; use api::r0::session::login;
use api::r0::sync::sync_events; use api::r0::sync::sync_events;
@ -472,7 +473,7 @@ impl AsyncClient {
/// ///
/// # Arguments /// # Arguments
/// ///
/// * room - the easiest way to create this request is using `RoomBuilder` struct. /// * room - the easiest way to create this request is using the `RoomBuilder`.
/// ///
/// # Examples /// # Examples
/// ```ignore /// ```ignore
@ -497,6 +498,34 @@ impl AsyncClient {
self.send(request).await self.send(request).await
} }
/// Invite the specified user by third party id to the given room.
///
/// Returns a `invite_user::Response`, an empty response.
///
/// # Arguments
///
/// * request - The easiest way to create a `Request` is using the `GetMessageBuilder`
pub async fn get_message_events<R: Into<get_message_events::Request>>(
&mut self,
request: R,
) -> Result<get_message_events::IncomingResponse> {
let req = request.into();
let room_id = req.room_id.clone();
let mut res = self.send(req).await?;
let mut client = self.base_client.write().await;
// TODO should we support this event? to keep emitting these msg events this is needed
for mut event in &mut res.chunk {
client
.receive_joined_timeline_event(&room_id, &mut event)
.await;
if let EventResult::Ok(e) = event {
client.emit_timeline_event(&room_id, e).await;
}
}
Ok(res)
}
/// Synchronize the client's state with the latest state on the server. /// Synchronize the client's state with the latest state on the server.
/// ///
/// # Arguments /// # Arguments

View File

@ -51,6 +51,6 @@ pub use async_client::{AsyncClient, AsyncClientConfig, SyncSettings};
pub use base_client::Client; pub use base_client::Client;
pub use event_emitter::EventEmitter; pub use event_emitter::EventEmitter;
pub use models::Room; pub use models::Room;
pub use request_builder::RoomBuilder; pub use request_builder::{GetMessageBuilder, RoomBuilder};
pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION"); pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION");

View File

@ -1,20 +1,28 @@
use crate::events::room::power_levels::PowerLevelsEventContent;
use crate::identifiers::UserId;
use crate::api; use crate::api;
use crate::events::room::power_levels::PowerLevelsEventContent;
use crate::identifiers::{RoomId, UserId};
use api::r0::filter::RoomEventFilter;
use api::r0::membership::Invite3pid; use api::r0::membership::Invite3pid;
use api::r0::message::get_message_events::{self, Direction};
use api::r0::room::{ use api::r0::room::{
create_room::{self, CreationContent, InitialStateEvent, RoomPreset}, create_room::{self, CreationContent, InitialStateEvent, RoomPreset},
Visibility, Visibility,
}; };
use js_int::UInt;
/// A builder used to create rooms. /// A builder used to create rooms.
/// ///
/// # Examples /// # Examples
/// ``` /// ```
/// # use std::convert::TryFrom;
/// # use matrix_sdk::{AsyncClient, RoomBuilder}; /// # use matrix_sdk::{AsyncClient, RoomBuilder};
/// # use matrix_sdk::api::r0::room::Visibility; /// # use matrix_sdk::api::r0::room::Visibility;
/// # use matrix_sdk::identifiers::UserId;
/// # use url::Url; /// # use url::Url;
/// # let homeserver = Url::parse("http://example.com").unwrap(); /// # let homeserver = Url::parse("http://example.com").unwrap();
/// # let mut rt = tokio::runtime::Runtime::new().unwrap();
/// # rt.block_on(async {
/// let mut bldr = RoomBuilder::default(); /// let mut bldr = RoomBuilder::default();
/// bldr.creation_content(false) /// bldr.creation_content(false)
/// .initial_state(vec![]) /// .initial_state(vec![])
@ -22,9 +30,7 @@ use api::r0::room::{
/// .name("name") /// .name("name")
/// .room_version("v1.0"); /// .room_version("v1.0");
/// let mut cli = AsyncClient::new(homeserver, None).unwrap(); /// let mut cli = AsyncClient::new(homeserver, None).unwrap();
/// # use futures::executor::block_on; /// cli.create_room(bldr).await;
/// # block_on(async {
/// assert!(cli.create_room(bldr).await.is_err());
/// # }) /// # })
/// ``` /// ```
#[derive(Clone, Default)] #[derive(Clone, Default)]
@ -80,70 +86,60 @@ impl RoomBuilder {
} }
/// Set the `InitialStateEvent` vector. /// Set the `InitialStateEvent` vector.
///
pub fn initial_state(&mut self, state: Vec<InitialStateEvent>) -> &mut Self { pub fn initial_state(&mut self, state: Vec<InitialStateEvent>) -> &mut Self {
self.initial_state = state; self.initial_state = state;
self self
} }
/// Set the vec of `UserId`s. /// Set the vec of `UserId`s.
///
pub fn invite(&mut self, invite: Vec<UserId>) -> &mut Self { pub fn invite(&mut self, invite: Vec<UserId>) -> &mut Self {
self.invite = invite; self.invite = invite;
self self
} }
/// Set the vec of `Invite3pid`s. /// Set the vec of `Invite3pid`s.
///
pub fn invite_3pid(&mut self, invite: Vec<Invite3pid>) -> &mut Self { pub fn invite_3pid(&mut self, invite: Vec<Invite3pid>) -> &mut Self {
self.invite_3pid = invite; self.invite_3pid = invite;
self self
} }
/// Set the vec of `Invite3pid`s. /// Set the vec of `Invite3pid`s.
///
pub fn is_direct(&mut self, direct: bool) -> &mut Self { pub fn is_direct(&mut self, direct: bool) -> &mut Self {
self.is_direct = Some(direct); self.is_direct = Some(direct);
self self
} }
/// Set the room name. A `m.room.name` event will be sent to the room. /// Set the room name. A `m.room.name` event will be sent to the room.
///
pub fn name<S: Into<String>>(&mut self, name: S) -> &mut Self { pub fn name<S: Into<String>>(&mut self, name: S) -> &mut Self {
self.name = Some(name.into()); self.name = Some(name.into());
self self
} }
/// Set the room's power levels. /// Set the room's power levels.
///
pub fn power_level_override(&mut self, power: PowerLevelsEventContent) -> &mut Self { pub fn power_level_override(&mut self, power: PowerLevelsEventContent) -> &mut Self {
self.power_level_content_override = Some(power); self.power_level_content_override = Some(power);
self self
} }
/// Convenience for setting various default state events based on a preset. /// Convenience for setting various default state events based on a preset.
///
pub fn preset(&mut self, preset: RoomPreset) -> &mut Self { pub fn preset(&mut self, preset: RoomPreset) -> &mut Self {
self.preset = Some(preset); self.preset = Some(preset);
self self
} }
/// The local part of a room alias. /// The local part of a room alias.
///
pub fn room_alias_name<S: Into<String>>(&mut self, alias: S) -> &mut Self { pub fn room_alias_name<S: Into<String>>(&mut self, alias: S) -> &mut Self {
self.room_alias_name = Some(alias.into()); self.room_alias_name = Some(alias.into());
self self
} }
/// Room version, defaults to homeserver's version if left unspecified. /// Room version, defaults to homeserver's version if left unspecified.
///
pub fn room_version<S: Into<String>>(&mut self, version: S) -> &mut Self { pub fn room_version<S: Into<String>>(&mut self, version: S) -> &mut Self {
self.room_version = Some(version.into()); self.room_version = Some(version.into());
self self
} }
/// If included, a `m.room.topic` event will be sent to the room. /// If included, a `m.room.topic` event will be sent to the room.
///
pub fn topic<S: Into<String>>(&mut self, topic: S) -> &mut Self { pub fn topic<S: Into<String>>(&mut self, topic: S) -> &mut Self {
self.topic = Some(topic.into()); self.topic = Some(topic.into());
self self
@ -152,7 +148,6 @@ impl RoomBuilder {
/// A public visibility indicates that the room will be shown in the published /// A public visibility indicates that the room will be shown in the published
/// room list. A private visibility will hide the room from the published room list. /// room list. A private visibility will hide the room from the published room list.
/// Rooms default to private visibility if this key is not included. /// Rooms default to private visibility if this key is not included.
///
pub fn visibility(&mut self, vis: Visibility) -> &mut Self { pub fn visibility(&mut self, vis: Visibility) -> &mut Self {
self.visibility = Some(vis); self.visibility = Some(vis);
self self
@ -178,14 +173,131 @@ impl Into<create_room::Request> for RoomBuilder {
} }
} }
/// Create a builder for making get_message_event requests.
#[derive(Clone, Default)]
pub struct GetMessageBuilder {
/// The room to get events from.
room_id: Option<RoomId>,
/// The token to start returning events from.
///
/// This token can be obtained from a
/// prev_batch token returned for each room by the sync API, or from a start or end token
/// returned by a previous request to this endpoint.
from: Option<String>,
/// The token to stop returning events at.
///
/// This token can be obtained from a prev_batch
/// token returned for each room by the sync endpoint, or from a start or end token returned
/// by a previous request to this endpoint.
to: Option<String>,
/// The direction to return events from.
direction: Option<Direction>,
/// The maximum number of events to return.
///
/// Default: 10.
limit: Option<UInt>,
/// A filter of the returned events with.
filter: Option<RoomEventFilter>,
}
impl GetMessageBuilder {
/// Create a `GetMessageBuilder` builder to make a `get_message_events::Request`.
///
/// The `room_id` and `from`` fields **need to be set** to create the request.
///
/// # Examples
/// ```
/// # use matrix_sdk::{AsyncClient, GetMessageBuilder};
/// # use matrix_sdk::api::r0::message::get_message_events::{self, Direction};
/// # use matrix_sdk::identifiers::RoomId;
/// # use url::Url;
/// # let homeserver = Url::parse("http://example.com").unwrap();
/// # let mut rt = tokio::runtime::Runtime::new().unwrap();
/// # rt.block_on(async {
/// # let room_id = RoomId::new(homeserver.as_str()).unwrap();
/// # let last_sync_token = "".to_string();;
/// let mut cli = AsyncClient::new(homeserver, None).unwrap();
///
/// let mut bldr = GetMessageBuilder::new();
/// bldr.room_id(room_id)
/// .from(last_sync_token)
/// .direction(Direction::Forward);
///
/// cli.get_message_events(bldr).await.is_err();
/// # })
/// ```
pub fn new() -> Self {
Self::default()
}
/// RoomId is required to create a `get_message_events::Request`.
pub fn room_id(&mut self, room_id: RoomId) -> &mut Self {
self.room_id = Some(room_id);
self
}
/// A `next_batch` token or `start` or `end` from a previous `get_message_events` request.
///
/// This is required to create a `get_message_events::Request`.
pub fn from(&mut self, from: String) -> &mut Self {
self.from = Some(from);
self
}
/// A `next_batch` token or `start` or `end` from a previous `get_message_events` request.
///
/// This token signals when to stop receiving events.
pub fn to(&mut self, to: String) -> &mut Self {
self.to = Some(to);
self
}
/// The direction to return events from.
///
/// If not specified `Direction::Backward` is used.
pub fn direction(&mut self, direction: Direction) -> &mut Self {
self.direction = Some(direction);
self
}
/// The maximum number of events to return.
pub fn limit(&mut self, limit: UInt) -> &mut Self {
self.limit = Some(limit);
self
}
/// Filter events by the given `RoomEventFilter`.
pub fn filter(&mut self, filter: RoomEventFilter) -> &mut Self {
self.filter = Some(filter);
self
}
}
impl Into<get_message_events::Request> for GetMessageBuilder {
fn into(self) -> get_message_events::Request {
get_message_events::Request {
room_id: self.room_id.expect("`room_id` and `from` need to be set"),
from: self.from.expect("`room_id` and `from` need to be set"),
to: self.to,
dir: self.direction.unwrap_or(Direction::Backward),
limit: self.limit,
filter: self.filter,
}
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use std::collections::HashMap;
use crate::{AsyncClient, Session}; use super::*;
use mockito::mock; use crate::{AsyncClient, Session, identifiers::RoomId};
use url::Url; use crate::events::room::power_levels::NotificationPowerLevels;
use js_int::Int;
use mockito::{mock, Matcher};
use std::convert::TryFrom; use std::convert::TryFrom;
use url::Url;
#[tokio::test] #[tokio::test]
async fn create_room_builder() { async fn create_room_builder() {
@ -202,13 +314,60 @@ mod test {
device_id: "DEVICEID".to_owned(), device_id: "DEVICEID".to_owned(),
}; };
let mut bldr = RoomBuilder::default(); let mut bldr = RoomBuilder::new();
bldr.creation_content(false) bldr.creation_content(false)
.initial_state(vec![]) .initial_state(vec![])
.visibility(Visibility::Public) .visibility(Visibility::Public)
.name("name") .name("room_name")
.room_version("v1.0"); .room_version("v1.0")
.invite_3pid(vec![])
.is_direct(true)
.power_level_override(PowerLevelsEventContent {
ban: Int::max_value(),
events: HashMap::default(),
events_default: Int::min_value(),
invite: Int::min_value(),
kick: Int::min_value(),
redact: Int::max_value(),
state_default: Int::min_value(),
users_default: Int::min_value(),
notifications: NotificationPowerLevels { room: Int::min_value() },
users: HashMap::default(),
})
.preset(RoomPreset::PrivateChat)
.room_alias_name("room_alias")
.topic("room topic")
.visibility(Visibility::Private);
let mut cli = AsyncClient::new(homeserver, Some(session)).unwrap(); let mut cli = AsyncClient::new(homeserver, Some(session)).unwrap();
assert!(cli.create_room(bldr).await.is_ok()); assert!(cli.create_room(bldr).await.is_ok());
} }
#[tokio::test]
async fn get_message_events() {
let homeserver = Url::parse(&mockito::server_url()).unwrap();
let _m = mock("GET", Matcher::Regex(r"^/_matrix/client/r0/rooms/.*/messages".to_string()))
.with_status(200)
.with_body_from_file("./tests/data/room_messages.json")
.create();
let session = Session {
access_token: "1234".to_owned(),
user_id: UserId::try_from("@example:localhost").unwrap(),
device_id: "DEVICEID".to_owned(),
};
let mut bldr = GetMessageBuilder::new();
bldr
.room_id(RoomId::try_from("!roomid:example.com").unwrap())
.from("t47429-4392820_219380_26003_2265".to_string())
.to("t4357353_219380_26003_2265".to_string())
.direction(Direction::Backward)
.limit(UInt::new(10).unwrap());
// TODO this makes ruma error `Err(IntoHttp(IntoHttpError(Query(Custom("unsupported value")))))`??
// .filter(RoomEventFilter::default());
let mut cli = AsyncClient::new(homeserver, Some(session)).unwrap();
assert!(cli.get_message_events(bldr).await.is_ok());
}
} }