Merge branch 'api-endpoints'
commit
6bdf8e522e
|
@ -3,7 +3,7 @@
|
||||||
## Design and Layout
|
## Design and Layout
|
||||||
|
|
||||||
#### Async Client
|
#### Async Client
|
||||||
The highest level structure that ties the other pieces of functionality together. The client is responsible for the Request/Response cycle. It can be thought of as a thin layer atop the `BaseClient` passing requests along for the `BaseClient` to handle. A user should be able to write their own `AsyncClient` using the `BaseClient`. It knows how to
|
The highest level structure that ties the other pieces of functionality together. The client is responsible for the Request/Response cycle. It can be thought of as a thin layer atop the `BaseClient` passing requests along for the `BaseClient` to handle. A user should be able to write their own `AsyncClient` using the `BaseClient`. It knows how to
|
||||||
- login
|
- login
|
||||||
- send messages
|
- send messages
|
||||||
- encryption ...
|
- encryption ...
|
||||||
|
|
|
@ -37,10 +37,10 @@ use ruma_api::{Endpoint, Outgoing};
|
||||||
use ruma_events::room::message::MessageEventContent;
|
use ruma_events::room::message::MessageEventContent;
|
||||||
use ruma_events::EventResult;
|
use ruma_events::EventResult;
|
||||||
pub use ruma_events::EventType;
|
pub use ruma_events::EventType;
|
||||||
use ruma_identifiers::RoomId;
|
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;
|
||||||
|
@ -181,7 +181,17 @@ impl SyncSettings {
|
||||||
use api::r0::client_exchange::send_event_to_device;
|
use api::r0::client_exchange::send_event_to_device;
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use api::r0::keys::{claim_keys, get_keys, upload_keys, KeyAlgorithm};
|
use api::r0::keys::{claim_keys, get_keys, upload_keys, KeyAlgorithm};
|
||||||
|
use api::r0::membership::join_room_by_id;
|
||||||
|
use api::r0::membership::join_room_by_id_or_alias;
|
||||||
|
use api::r0::membership::kick_user;
|
||||||
|
use api::r0::membership::leave_room;
|
||||||
|
use api::r0::membership::{
|
||||||
|
invite_user::{self, InvitationRecipient},
|
||||||
|
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::session::login;
|
use api::r0::session::login;
|
||||||
use api::r0::sync::sync_events;
|
use api::r0::sync::sync_events;
|
||||||
|
|
||||||
|
@ -333,6 +343,207 @@ impl AsyncClient {
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Join a room by `RoomId`.
|
||||||
|
///
|
||||||
|
/// Returns a `join_room_by_id::Response` consisting of the
|
||||||
|
/// joined rooms `RoomId`.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * room_id - The `RoomId` of the room to be joined.
|
||||||
|
pub async fn join_room_by_id(&mut self, room_id: &RoomId) -> Result<join_room_by_id::Response> {
|
||||||
|
let request = join_room_by_id::Request {
|
||||||
|
room_id: room_id.clone(),
|
||||||
|
third_party_signed: None,
|
||||||
|
};
|
||||||
|
self.send(request).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Join a room by `RoomId`.
|
||||||
|
///
|
||||||
|
/// Returns a `join_room_by_id_or_alias::Response` consisting of the
|
||||||
|
/// joined rooms `RoomId`.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * alias - The `RoomId` or `RoomAliasId` of the room to be joined.
|
||||||
|
/// An alias looks like this `#name:example.com`
|
||||||
|
pub async fn join_room_by_id_or_alias(
|
||||||
|
&mut self,
|
||||||
|
alias: &RoomIdOrAliasId,
|
||||||
|
) -> Result<join_room_by_id_or_alias::Response> {
|
||||||
|
let request = join_room_by_id_or_alias::Request {
|
||||||
|
room_id_or_alias: alias.clone(),
|
||||||
|
third_party_signed: None,
|
||||||
|
};
|
||||||
|
self.send(request).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Kick a user out of the specified room.
|
||||||
|
///
|
||||||
|
/// Returns a `kick_user::Response`, an empty response.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * room_id - The `RoomId` of the room the user should be kicked out of.
|
||||||
|
///
|
||||||
|
/// * user_id - The `UserId` of the user that should be kicked out of the room.
|
||||||
|
///
|
||||||
|
/// * reason - Optional reason why the room member is being kicked out.
|
||||||
|
pub async fn kick_user(
|
||||||
|
&mut self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
user_id: &UserId,
|
||||||
|
reason: Option<String>,
|
||||||
|
) -> Result<kick_user::Response> {
|
||||||
|
let request = kick_user::Request {
|
||||||
|
reason,
|
||||||
|
room_id: room_id.clone(),
|
||||||
|
user_id: user_id.clone(),
|
||||||
|
};
|
||||||
|
self.send(request).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Leave the specified room.
|
||||||
|
///
|
||||||
|
/// Returns a `leave_room::Response`, an empty response.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * room_id - The `RoomId` of the room to leave.
|
||||||
|
///
|
||||||
|
pub async fn leave_room(&mut self, room_id: &RoomId) -> Result<leave_room::Response> {
|
||||||
|
let request = leave_room::Request {
|
||||||
|
room_id: room_id.clone(),
|
||||||
|
};
|
||||||
|
self.send(request).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invite the specified user by `UserId` to the given room.
|
||||||
|
///
|
||||||
|
/// Returns a `invite_user::Response`, an empty response.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * room_id - The `RoomId` of the room to invite the specified user to.
|
||||||
|
///
|
||||||
|
/// * user_id - The `UserId` of the user to invite to the room.
|
||||||
|
pub async fn invite_user_by_id(
|
||||||
|
&mut self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
user_id: &UserId,
|
||||||
|
) -> Result<invite_user::Response> {
|
||||||
|
let request = invite_user::Request {
|
||||||
|
room_id: room_id.clone(),
|
||||||
|
recipient: InvitationRecipient::UserId {
|
||||||
|
user_id: user_id.clone(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
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
|
||||||
|
///
|
||||||
|
/// * room_id - The `RoomId` of the room to invite the specified user to.
|
||||||
|
///
|
||||||
|
/// * invite_id - A third party id of a user to invite to the room.
|
||||||
|
pub async fn invite_user_by_3pid(
|
||||||
|
&mut self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
invite_id: &Invite3pid,
|
||||||
|
) -> Result<invite_user::Response> {
|
||||||
|
let request = invite_user::Request {
|
||||||
|
room_id: room_id.clone(),
|
||||||
|
recipient: InvitationRecipient::ThirdPartyId(invite_id.clone()),
|
||||||
|
};
|
||||||
|
self.send(request).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a room using the `RoomBuilder` and send the request.
|
||||||
|
///
|
||||||
|
/// Sends a request to `/_matrix/client/r0/createRoom`, returns a `create_room::Response`,
|
||||||
|
/// this is an empty response.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * room - The easiest way to create this request is using the `RoomBuilder`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```no_run
|
||||||
|
/// use matrix_sdk::{AsyncClient, RoomBuilder};
|
||||||
|
/// # use matrix_sdk::api::r0::room::Visibility;
|
||||||
|
/// # use url::Url;
|
||||||
|
///
|
||||||
|
/// # let homeserver = Url::parse("http://example.com").unwrap();
|
||||||
|
/// let mut builder = RoomBuilder::default();
|
||||||
|
/// builder.creation_content(false)
|
||||||
|
/// .initial_state(vec![])
|
||||||
|
/// .visibility(Visibility::Public)
|
||||||
|
/// .name("name")
|
||||||
|
/// .room_version("v1.0");
|
||||||
|
///
|
||||||
|
/// let mut cli = AsyncClient::new(homeserver, None).unwrap();
|
||||||
|
/// # use futures::executor::block_on;
|
||||||
|
/// # block_on(async {
|
||||||
|
/// assert!(cli.create_room(builder).await.is_ok());
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
pub async fn create_room<R: Into<create_room::Request>>(
|
||||||
|
&mut self,
|
||||||
|
room: R,
|
||||||
|
) -> Result<create_room::Response> {
|
||||||
|
let request = room.into();
|
||||||
|
self.send(request).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get messages starting at a specific sync point using the
|
||||||
|
/// `MessagesRequestBuilder`s `from` field as a starting point.
|
||||||
|
///
|
||||||
|
/// Sends a request to `/_matrix/client/r0/rooms/{room_id}/messages` and
|
||||||
|
/// returns a `get_message_events::IncomingResponse` that contains chunks
|
||||||
|
/// of `RoomEvents`.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * request - The easiest way to create a `Request` is using the
|
||||||
|
/// `MessagesRequestBuilder`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```no_run
|
||||||
|
/// # use std::convert::TryFrom;
|
||||||
|
/// use matrix_sdk::{AsyncClient, MessagesRequestBuilder};
|
||||||
|
/// # use matrix_sdk::identifiers::RoomId;
|
||||||
|
/// # use matrix_sdk::api::r0::filter::RoomEventFilter;
|
||||||
|
/// # use matrix_sdk::api::r0::message::get_message_events::Direction;
|
||||||
|
/// # use url::Url;
|
||||||
|
/// # use js_int::UInt;
|
||||||
|
///
|
||||||
|
/// # let homeserver = Url::parse("http://example.com").unwrap();
|
||||||
|
/// let mut builder = MessagesRequestBuilder::new();
|
||||||
|
/// builder.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());
|
||||||
|
///
|
||||||
|
/// let mut cli = AsyncClient::new(homeserver, None).unwrap();
|
||||||
|
/// # use futures::executor::block_on;
|
||||||
|
/// # block_on(async {
|
||||||
|
/// assert!(cli.room_messages(builder).await.is_ok());
|
||||||
|
/// # });
|
||||||
|
/// ```
|
||||||
|
pub async fn room_messages<R: Into<get_message_events::Request>>(
|
||||||
|
&mut self,
|
||||||
|
request: R,
|
||||||
|
) -> Result<get_message_events::IncomingResponse> {
|
||||||
|
let req = request.into();
|
||||||
|
self.send(req).await
|
||||||
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
|
@ -635,6 +846,10 @@ impl AsyncClient {
|
||||||
///
|
///
|
||||||
/// * `content` - The content of the message event.
|
/// * `content` - The content of the message event.
|
||||||
///
|
///
|
||||||
|
/// * `txn_id` - A unique `Uuid` that can be attached to a `MessageEvent` held
|
||||||
|
/// in it's unsigned field as `transaction_id`. If not given one is created for the
|
||||||
|
/// message.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use matrix_sdk::Room;
|
/// # use matrix_sdk::Room;
|
||||||
|
@ -649,6 +864,7 @@ impl AsyncClient {
|
||||||
/// # let homeserver = Url::parse("http://localhost:8080").unwrap();
|
/// # let homeserver = Url::parse("http://localhost:8080").unwrap();
|
||||||
/// # let mut client = AsyncClient::new(homeserver, None).unwrap();
|
/// # let mut client = AsyncClient::new(homeserver, None).unwrap();
|
||||||
/// # let room_id = RoomId::try_from("!test:localhost").unwrap();
|
/// # let room_id = RoomId::try_from("!test:localhost").unwrap();
|
||||||
|
/// use uuid::Uuid;
|
||||||
///
|
///
|
||||||
/// let content = MessageEventContent::Text(TextMessageEventContent {
|
/// let content = MessageEventContent::Text(TextMessageEventContent {
|
||||||
/// body: "Hello world".to_owned(),
|
/// body: "Hello world".to_owned(),
|
||||||
|
@ -656,14 +872,15 @@ impl AsyncClient {
|
||||||
/// formatted_body: None,
|
/// formatted_body: None,
|
||||||
/// relates_to: None,
|
/// relates_to: None,
|
||||||
/// });
|
/// });
|
||||||
///
|
/// let txn_id = Uuid::new_v4();
|
||||||
/// client.room_send(&room_id, content).await.unwrap();
|
/// client.room_send(&room_id, content, Some(txn_id)).await.unwrap();
|
||||||
/// })
|
/// })
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn room_send(
|
pub async fn room_send(
|
||||||
&mut self,
|
&mut self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
#[allow(unused_mut)] mut content: MessageEventContent,
|
#[allow(unused_mut)] mut content: MessageEventContent,
|
||||||
|
txn_id: Option<Uuid>,
|
||||||
) -> Result<create_message_event::Response> {
|
) -> Result<create_message_event::Response> {
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut event_type = EventType::RoomMessage;
|
let mut event_type = EventType::RoomMessage;
|
||||||
|
@ -722,7 +939,7 @@ impl AsyncClient {
|
||||||
let request = create_message_event::Request {
|
let request = create_message_event::Request {
|
||||||
room_id: room_id.clone(),
|
room_id: room_id.clone(),
|
||||||
event_type,
|
event_type,
|
||||||
txn_id: Uuid::new_v4().to_string(),
|
txn_id: txn_id.unwrap_or_else(Uuid::new_v4).to_string(),
|
||||||
data: content,
|
data: content,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ mod base_client;
|
||||||
mod error;
|
mod error;
|
||||||
mod event_emitter;
|
mod event_emitter;
|
||||||
mod models;
|
mod models;
|
||||||
|
mod request_builder;
|
||||||
mod session;
|
mod session;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -50,5 +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::{MessagesRequestBuilder, RoomBuilder};
|
||||||
|
|
||||||
pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
|
@ -0,0 +1,379 @@
|
||||||
|
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::message::get_message_events::{self, Direction};
|
||||||
|
use api::r0::room::{
|
||||||
|
create_room::{self, CreationContent, InitialStateEvent, RoomPreset},
|
||||||
|
Visibility,
|
||||||
|
};
|
||||||
|
|
||||||
|
use js_int::UInt;
|
||||||
|
|
||||||
|
/// A builder used to create rooms.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # use std::convert::TryFrom;
|
||||||
|
/// # use matrix_sdk::{AsyncClient, RoomBuilder};
|
||||||
|
/// # use matrix_sdk::api::r0::room::Visibility;
|
||||||
|
/// # use matrix_sdk::identifiers::UserId;
|
||||||
|
/// # use url::Url;
|
||||||
|
/// # let homeserver = Url::parse("http://example.com").unwrap();
|
||||||
|
/// # let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
/// # rt.block_on(async {
|
||||||
|
/// let mut builder = RoomBuilder::default();
|
||||||
|
/// builder.creation_content(false)
|
||||||
|
/// .initial_state(vec![])
|
||||||
|
/// .visibility(Visibility::Public)
|
||||||
|
/// .name("name")
|
||||||
|
/// .room_version("v1.0");
|
||||||
|
/// let mut cli = AsyncClient::new(homeserver, None).unwrap();
|
||||||
|
/// cli.create_room(builder).await;
|
||||||
|
/// # })
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct RoomBuilder {
|
||||||
|
/// Extra keys to be added to the content of the `m.room.create`.
|
||||||
|
creation_content: Option<CreationContent>,
|
||||||
|
/// List of state events to send to the new room.
|
||||||
|
///
|
||||||
|
/// Takes precedence over events set by preset, but gets overriden by
|
||||||
|
/// name and topic keys.
|
||||||
|
initial_state: Vec<InitialStateEvent>,
|
||||||
|
/// A list of user IDs to invite to the room.
|
||||||
|
///
|
||||||
|
/// This will tell the server to invite everyone in the list to the newly created room.
|
||||||
|
invite: Vec<UserId>,
|
||||||
|
/// List of third party IDs of users to invite.
|
||||||
|
invite_3pid: Vec<Invite3pid>,
|
||||||
|
/// If set, this sets the `is_direct` flag on room invites.
|
||||||
|
is_direct: Option<bool>,
|
||||||
|
/// If this is included, an `m.room.name` event will be sent into the room to indicate
|
||||||
|
/// the name of the room.
|
||||||
|
name: Option<String>,
|
||||||
|
/// Power level content to override in the default power level event.
|
||||||
|
power_level_content_override: Option<PowerLevelsEventContent>,
|
||||||
|
/// Convenience parameter for setting various default state events based on a preset.
|
||||||
|
preset: Option<RoomPreset>,
|
||||||
|
/// The desired room alias local part.
|
||||||
|
room_alias_name: Option<String>,
|
||||||
|
/// Room version to set for the room. Defaults to homeserver's default if not specified.
|
||||||
|
room_version: Option<String>,
|
||||||
|
/// If this is included, an `m.room.topic` event will be sent into the room to indicate
|
||||||
|
/// the topic for the room.
|
||||||
|
topic: Option<String>,
|
||||||
|
/// 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. Rooms
|
||||||
|
/// default to private visibility if this key is not included.
|
||||||
|
visibility: Option<Visibility>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RoomBuilder {
|
||||||
|
/// Returns an empty `RoomBuilder` for creating rooms.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the `CreationContent`.
|
||||||
|
///
|
||||||
|
/// Weather users on other servers can join this room.
|
||||||
|
pub fn creation_content(&mut self, federate: bool) -> &mut Self {
|
||||||
|
let federate = Some(federate);
|
||||||
|
self.creation_content = Some(CreationContent { federate });
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the `InitialStateEvent` vector.
|
||||||
|
pub fn initial_state(&mut self, state: Vec<InitialStateEvent>) -> &mut Self {
|
||||||
|
self.initial_state = state;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the vec of `UserId`s.
|
||||||
|
pub fn invite(&mut self, invite: Vec<UserId>) -> &mut Self {
|
||||||
|
self.invite = invite;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the vec of `Invite3pid`s.
|
||||||
|
pub fn invite_3pid(&mut self, invite: Vec<Invite3pid>) -> &mut Self {
|
||||||
|
self.invite_3pid = invite;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the vec of `Invite3pid`s.
|
||||||
|
pub fn is_direct(&mut self, direct: bool) -> &mut Self {
|
||||||
|
self.is_direct = Some(direct);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 {
|
||||||
|
self.name = Some(name.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the room's power levels.
|
||||||
|
pub fn power_level_override(&mut self, power: PowerLevelsEventContent) -> &mut Self {
|
||||||
|
self.power_level_content_override = Some(power);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience for setting various default state events based on a preset.
|
||||||
|
pub fn preset(&mut self, preset: RoomPreset) -> &mut Self {
|
||||||
|
self.preset = Some(preset);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The local part of a room alias.
|
||||||
|
pub fn room_alias_name<S: Into<String>>(&mut self, alias: S) -> &mut Self {
|
||||||
|
self.room_alias_name = Some(alias.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Room version, defaults to homeserver's version if left unspecified.
|
||||||
|
pub fn room_version<S: Into<String>>(&mut self, version: S) -> &mut Self {
|
||||||
|
self.room_version = Some(version.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 {
|
||||||
|
self.topic = Some(topic.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
/// Rooms default to private visibility if this key is not included.
|
||||||
|
pub fn visibility(&mut self, vis: Visibility) -> &mut Self {
|
||||||
|
self.visibility = Some(vis);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<create_room::Request> for RoomBuilder {
|
||||||
|
fn into(self) -> create_room::Request {
|
||||||
|
create_room::Request {
|
||||||
|
creation_content: self.creation_content,
|
||||||
|
initial_state: self.initial_state,
|
||||||
|
invite: self.invite,
|
||||||
|
invite_3pid: self.invite_3pid,
|
||||||
|
is_direct: self.is_direct,
|
||||||
|
name: self.name,
|
||||||
|
power_level_content_override: self.power_level_content_override,
|
||||||
|
preset: self.preset,
|
||||||
|
room_alias_name: self.room_alias_name,
|
||||||
|
room_version: self.room_version,
|
||||||
|
topic: self.topic,
|
||||||
|
visibility: self.visibility,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a builder for making get_message_event requests.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # use matrix_sdk::{AsyncClient, MessagesRequestBuilder};
|
||||||
|
/// # 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 builder = MessagesRequestBuilder::new();
|
||||||
|
/// builder.room_id(room_id)
|
||||||
|
/// .from(last_sync_token)
|
||||||
|
/// .direction(Direction::Forward);
|
||||||
|
///
|
||||||
|
/// cli.room_messages(builder).await.is_err();
|
||||||
|
/// # })
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct MessagesRequestBuilder {
|
||||||
|
/// 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 MessagesRequestBuilder {
|
||||||
|
/// Create a `MessagesRequestBuilder` builder to make a `get_message_events::Request`.
|
||||||
|
///
|
||||||
|
/// The `room_id` and `from`` fields **need to be set** to create the request.
|
||||||
|
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 MessagesRequestBuilder {
|
||||||
|
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)]
|
||||||
|
mod test {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::events::room::power_levels::NotificationPowerLevels;
|
||||||
|
use crate::{identifiers::RoomId, AsyncClient, Session};
|
||||||
|
|
||||||
|
use js_int::Int;
|
||||||
|
use mockito::{mock, Matcher};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn create_room_builder() {
|
||||||
|
let homeserver = Url::parse(&mockito::server_url()).unwrap();
|
||||||
|
|
||||||
|
let _m = mock("POST", "/_matrix/client/r0/createRoom")
|
||||||
|
.with_status(200)
|
||||||
|
.with_body_from_file("./tests/data/room_id.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 builder = RoomBuilder::new();
|
||||||
|
builder
|
||||||
|
.creation_content(false)
|
||||||
|
.initial_state(vec![])
|
||||||
|
.visibility(Visibility::Public)
|
||||||
|
.name("room_name")
|
||||||
|
.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();
|
||||||
|
assert!(cli.create_room(builder).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 builder = MessagesRequestBuilder::new();
|
||||||
|
builder
|
||||||
|
.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.room_messages(builder).await.is_ok());
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,4 +18,3 @@
|
||||||
"age": 1234
|
"age": 1234
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
{
|
|
||||||
"next_batch": "s72595_4483_1934",
|
|
||||||
"presence": {
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"content": {
|
|
||||||
"avatar_url": "mxc://localhost:wefuiwegh8742w",
|
|
||||||
"last_active_ago": 2478593,
|
|
||||||
"presence": "online",
|
|
||||||
"currently_active": false,
|
|
||||||
"status_msg": "Making cupcakes"
|
|
||||||
},
|
|
||||||
"type": "m.presence",
|
|
||||||
"sender": "@example:localhost"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"account_data": {
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"type": "org.example.custom.config",
|
|
||||||
"content": {
|
|
||||||
"custom_config_key": "custom_config_value"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"rooms": {
|
|
||||||
"join": {
|
|
||||||
"!726s6s6q:example.com": {
|
|
||||||
"summary": {
|
|
||||||
"m.heroes": [
|
|
||||||
"@alice:example.com",
|
|
||||||
"@bob:example.com"
|
|
||||||
],
|
|
||||||
"m.joined_member_count": 2,
|
|
||||||
"m.invited_member_count": 0
|
|
||||||
},
|
|
||||||
"state": {
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"content": {
|
|
||||||
"membership": "join",
|
|
||||||
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
|
||||||
"displayname": "Alice Margatroid"
|
|
||||||
},
|
|
||||||
"type": "m.room.member",
|
|
||||||
"event_id": "$143273582443PhrSn:example.org",
|
|
||||||
"room_id": "!726s6s6q:example.com",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"origin_server_ts": 1432735824653,
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
},
|
|
||||||
"state_key": "@alice:example.org"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"timeline": {
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"content": {
|
|
||||||
"membership": "join",
|
|
||||||
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
|
|
||||||
"displayname": "Alice Margatroid"
|
|
||||||
},
|
|
||||||
"type": "m.room.member",
|
|
||||||
"event_id": "$143273582443PhrSn:example.org",
|
|
||||||
"room_id": "!726s6s6q:example.com",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"origin_server_ts": 1432735824653,
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
},
|
|
||||||
"state_key": "@alice:example.org"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"content": {
|
|
||||||
"body": "This is an example text message",
|
|
||||||
"msgtype": "m.text",
|
|
||||||
"format": "org.matrix.custom.html",
|
|
||||||
"formatted_body": "<b>This is an example text message</b>"
|
|
||||||
},
|
|
||||||
"type": "m.room.message",
|
|
||||||
"event_id": "$143273582443PhrSn:example.org",
|
|
||||||
"room_id": "!726s6s6q:example.com",
|
|
||||||
"sender": "@example:example.org",
|
|
||||||
"origin_server_ts": 1432735824653,
|
|
||||||
"unsigned": {
|
|
||||||
"age": 1234
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"limited": true,
|
|
||||||
"prev_batch": "t34-23535_0_0"
|
|
||||||
},
|
|
||||||
"ephemeral": {
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"content": {
|
|
||||||
"user_ids": [
|
|
||||||
"@alice:matrix.org",
|
|
||||||
"@bob:example.com"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"type": "m.typing",
|
|
||||||
"room_id": "!jEsUZKDJdhlrceRyVU:example.org"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"account_data": {
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"content": {
|
|
||||||
"tags": {
|
|
||||||
"u.work": {
|
|
||||||
"order": 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "m.tag"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "org.example.custom.room.config",
|
|
||||||
"content": {
|
|
||||||
"custom_config_key": "custom_config_value"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"invite": {
|
|
||||||
"!696r7674:example.com": {
|
|
||||||
"invite_state": {
|
|
||||||
"events": [
|
|
||||||
{
|
|
||||||
"sender": "@alice:example.com",
|
|
||||||
"type": "m.room.name",
|
|
||||||
"state_key": "",
|
|
||||||
"content": {
|
|
||||||
"name": "My Room Name"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sender": "@alice:example.com",
|
|
||||||
"type": "m.room.member",
|
|
||||||
"state_key": "@bob:example.com",
|
|
||||||
"content": {
|
|
||||||
"membership": "invite"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"leave": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue