Struct matrix_sdk::Client
source · pub struct Client { /* private fields */ }
Expand description
An async/await enabled Matrix client.
All of the state is held in an Arc
so the Client
can be cloned freely.
Implementations§
source§impl Client
impl Client
sourcepub async fn new(homeserver_url: Url) -> Result<Self, ClientBuildError>
pub async fn new(homeserver_url: Url) -> Result<Self, ClientBuildError>
sourcepub fn subscribe_to_ignore_user_list_changes(&self) -> Subscriber<Vec<String>>
pub fn subscribe_to_ignore_user_list_changes(&self) -> Subscriber<Vec<String>>
Returns a subscriber that publishes an event every time the ignore user list changes.
sourcepub fn builder() -> ClientBuilder
pub fn builder() -> ClientBuilder
Create a new ClientBuilder
.
sourcepub fn http_client(&self) -> &Client
pub fn http_client(&self) -> &Client
The underlying HTTP client.
sourcepub fn cross_process_store_locks_holder_name(&self) -> &str
pub fn cross_process_store_locks_holder_name(&self) -> &str
The cross-process store locks holder name.
The SDK provides cross-process store locks (see
matrix_sdk_common::store_locks::CrossProcessStoreLock
). The
holder_name
is the value used for all cross-process store locks
used by this Client
.
sourcepub async fn get_capabilities(&self) -> HttpResult<Capabilities>
pub async fn get_capabilities(&self) -> HttpResult<Capabilities>
Get the capabilities of the homeserver.
This method should be used to check what features are supported by the homeserver.
§Examples
let client = Client::new(homeserver).await?;
let capabilities = client.get_capabilities().await?;
if capabilities.change_password.enabled {
// Change password
}
sourcepub fn request_config(&self) -> RequestConfig
pub fn request_config(&self) -> RequestConfig
Get a copy of the default request config.
The default request config is what’s used when sending requests if no
RequestConfig
is explicitly passed to send
or another
function with such a parameter.
If the default request config was not customized through
ClientBuilder
when creating this Client
, the returned value will
be equivalent to RequestConfig::default()
.
sourcepub fn server(&self) -> Option<&Url>
pub fn server(&self) -> Option<&Url>
The server used by the client.
See Self::server
to learn more.
sourcepub fn homeserver(&self) -> Url
pub fn homeserver(&self) -> Url
The homeserver of the client.
sourcepub fn sliding_sync_version(&self) -> SlidingSyncVersion
pub fn sliding_sync_version(&self) -> SlidingSyncVersion
Get the sliding sync version.
sourcepub fn set_sliding_sync_version(&self, version: SlidingSyncVersion)
pub fn set_sliding_sync_version(&self, version: SlidingSyncVersion)
Override the sliding sync version.
sourcepub fn session_meta(&self) -> Option<&SessionMeta>
pub fn session_meta(&self) -> Option<&SessionMeta>
Get the Matrix user session meta information.
If the client is currently logged in, this will return a
SessionMeta
object which contains the user ID and device ID.
Otherwise it returns None
.
sourcepub fn room_info_notable_update_receiver(
&self,
) -> Receiver<RoomInfoNotableUpdate>
pub fn room_info_notable_update_receiver( &self, ) -> Receiver<RoomInfoNotableUpdate>
Returns a receiver that gets events for each room info update. To watch
for new events, use receiver.resubscribe()
. Each event contains the
room and a boolean whether this event should trigger a room list update.
sourcepub async fn search_users(
&self,
search_term: &str,
limit: u64,
) -> HttpResult<Response>
pub async fn search_users( &self, search_term: &str, limit: u64, ) -> HttpResult<Response>
Performs a search for users. The search is performed case-insensitively on user IDs and display names
§Arguments
search_term
- The search term for the searchlimit
- The maximum number of results to return. Defaults to 10.
sourcepub fn device_id(&self) -> Option<&DeviceId>
pub fn device_id(&self) -> Option<&DeviceId>
Get the device ID that identifies the current session.
sourcepub fn access_token(&self) -> Option<String>
pub fn access_token(&self) -> Option<String>
Get the current access token for this session, regardless of the authentication API used to log in.
Will be None
if the client has not been logged in.
sourcepub fn auth_api(&self) -> Option<AuthApi>
pub fn auth_api(&self) -> Option<AuthApi>
Access the authentication API used to log in this client.
Will be None
if the client has not been logged in.
sourcepub fn session(&self) -> Option<AuthSession>
pub fn session(&self) -> Option<AuthSession>
Get the whole session info of this client.
Will be None
if the client has not been logged in.
Can be used with Client::restore_session
to restore a previously
logged-in session.
sourcepub fn store(&self) -> &DynStateStore
pub fn store(&self) -> &DynStateStore
Get a reference to the state store.
sourcepub fn matrix_auth(&self) -> MatrixAuth
pub fn matrix_auth(&self) -> MatrixAuth
Access the native Matrix authentication API with this client.
sourcepub fn encryption(&self) -> Encryption
pub fn encryption(&self) -> Encryption
Get the encryption manager of the client.
sourcepub fn add_event_handler<Ev, Ctx, H>(&self, handler: H) -> EventHandlerHandle
pub fn add_event_handler<Ev, Ctx, H>(&self, handler: H) -> EventHandlerHandle
Register a handler for a specific event type.
The handler is a function or closure with one or more arguments. The
first argument is the event itself. All additional arguments are
“context” arguments: They have to implement EventHandlerContext
.
This trait is named that way because most of the types implementing it
give additional context about an event: The room it was in, its raw form
and other similar things. As two exceptions to this,
Client
and EventHandlerHandle
also implement the
EventHandlerContext
trait so you don’t have to clone your client
into the event handler manually and a handler can decide to remove
itself.
Some context arguments are not universally applicable. A context argument that isn’t available for the given event type will result in the event handler being skipped and an error being logged. The following context argument types are only available for a subset of event types:
Room
is only available for room-specific events, i.e. not for events like global account data events or presence events.
You can provide custom context via
add_event_handler_context
and
then use Ctx<T>
to extract the context
into the event handler.
§Examples
use matrix_sdk::{
deserialized_responses::EncryptionInfo,
event_handler::Ctx,
ruma::{
events::{
macros::EventContent,
push_rules::PushRulesEvent,
room::{message::SyncRoomMessageEvent, topic::SyncRoomTopicEvent},
},
push::Action,
Int, MilliSecondsSinceUnixEpoch,
},
Client, Room,
};
use serde::{Deserialize, Serialize};
client.add_event_handler(
|ev: SyncRoomMessageEvent, room: Room, client: Client| async move {
// Common usage: Room event plus room and client.
},
);
client.add_event_handler(
|ev: SyncRoomMessageEvent, room: Room, encryption_info: Option<EncryptionInfo>| {
async move {
// An `Option<EncryptionInfo>` parameter lets you distinguish between
// unencrypted events and events that were decrypted by the SDK.
}
},
);
client.add_event_handler(
|ev: SyncRoomMessageEvent, room: Room, push_actions: Vec<Action>| {
async move {
// A `Vec<Action>` parameter allows you to know which push actions
// are applicable for an event. For example, an event with
// `Action::SetTweak(Tweak::Highlight(true))` should be highlighted
// in the timeline.
}
},
);
client.add_event_handler(|ev: SyncRoomTopicEvent| async move {
// You can omit any or all arguments after the first.
});
// Registering a temporary event handler:
let handle = client.add_event_handler(|ev: SyncRoomMessageEvent| async move {
/* Event handler */
});
client.remove_event_handler(handle);
// Registering custom event handler context:
#[derive(Debug, Clone)] // The context will be cloned for event handler.
struct MyContext {
number: usize,
}
client.add_event_handler_context(MyContext { number: 5 });
client.add_event_handler(|ev: SyncRoomMessageEvent, context: Ctx<MyContext>| async move {
// Use the context
});
// Custom events work exactly the same way, you just need to declare
// the content struct and use the EventContent derive macro on it.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "org.shiny_new_2fa.token", kind = MessageLike)]
struct TokenEventContent {
token: String,
#[serde(rename = "exp")]
expires_at: MilliSecondsSinceUnixEpoch,
}
client.add_event_handler(|ev: SyncTokenEvent, room: Room| async move {
todo!("Display the token");
});
// Event handler closures can also capture local variables.
// Make sure they are cheap to clone though, because they will be cloned
// every time the closure is called.
let data: std::sync::Arc<str> = "MyCustomIdentifier".into();
client.add_event_handler(move |ev: SyncRoomMessageEvent | async move {
println!("Calling the handler with identifier {data}");
});
sourcepub fn add_room_event_handler<Ev, Ctx, H>(
&self,
room_id: &RoomId,
handler: H,
) -> EventHandlerHandle
pub fn add_room_event_handler<Ev, Ctx, H>( &self, room_id: &RoomId, handler: H, ) -> EventHandlerHandle
Register a handler for a specific room, and event type.
This method works the same way as
add_event_handler
, except that the handler
will only be called for events in the room with the specified ID. See
that method for more details on event handler functions.
client.add_room_event_handler(room_id, hdl)
is equivalent to
room.add_event_handler(hdl)
. Use whichever one is more convenient in
your use case.
sourcepub fn observe_events<Ev, Ctx>(&self) -> ObservableEventHandler<(Ev, Ctx)>where
Ev: SyncEvent + DeserializeOwned + SendOutsideWasm + SyncOutsideWasm + 'static,
Ctx: EventHandlerContext + SendOutsideWasm + SyncOutsideWasm + 'static,
pub fn observe_events<Ev, Ctx>(&self) -> ObservableEventHandler<(Ev, Ctx)>where
Ev: SyncEvent + DeserializeOwned + SendOutsideWasm + SyncOutsideWasm + 'static,
Ctx: EventHandlerContext + SendOutsideWasm + SyncOutsideWasm + 'static,
Observe a specific event type.
Ev
represents the kind of event that will be observed. Ctx
represents the context that will come with the event. It relies on the
same mechanism as Client::add_event_handler
. The main difference is
that it returns an ObservableEventHandler
and doesn’t require a
user-defined closure. It is possible to subscribe to the
ObservableEventHandler
to get an EventHandlerSubscriber
, which
implements a Stream
. The Stream::Item
will be of type (Ev, Ctx)
.
§Example
Let’s see a classical usage:
use futures_util::StreamExt as _;
use matrix_sdk::{
ruma::{events::room::message::SyncRoomMessageEvent, push::Action},
Client, Room,
};
let observer =
client.observe_events::<SyncRoomMessageEvent, (Room, Vec<Action>)>();
let mut subscriber = observer.subscribe();
let (event, (room, push_actions)) = subscriber.next().await?;
Now let’s see how to get several contexts that can be useful for you:
use matrix_sdk::{
deserialized_responses::EncryptionInfo,
ruma::{
events::room::{
message::SyncRoomMessageEvent, topic::SyncRoomTopicEvent,
},
push::Action,
},
Client, Room,
};
// Observe `SyncRoomMessageEvent` and fetch `Room` + `Client`.
let _ = client.observe_events::<SyncRoomMessageEvent, (Room, Client)>();
// Observe `SyncRoomMessageEvent` and fetch `Room` + `EncryptionInfo`
// to distinguish between unencrypted events and events that were decrypted
// by the SDK.
let _ = client
.observe_events::<SyncRoomMessageEvent, (Room, Option<EncryptionInfo>)>(
);
// Observe `SyncRoomMessageEvent` and fetch `Room` + push actions.
// For example, an event with `Action::SetTweak(Tweak::Highlight(true))`
// should be highlighted in the timeline.
let _ =
client.observe_events::<SyncRoomMessageEvent, (Room, Vec<Action>)>();
// Observe `SyncRoomTopicEvent` and fetch nothing else.
let _ = client.observe_events::<SyncRoomTopicEvent, ()>();
sourcepub fn observe_room_events<Ev, Ctx>(
&self,
room_id: &RoomId,
) -> ObservableEventHandler<(Ev, Ctx)>where
Ev: SyncEvent + DeserializeOwned + SendOutsideWasm + SyncOutsideWasm + 'static,
Ctx: EventHandlerContext + SendOutsideWasm + SyncOutsideWasm + 'static,
pub fn observe_room_events<Ev, Ctx>(
&self,
room_id: &RoomId,
) -> ObservableEventHandler<(Ev, Ctx)>where
Ev: SyncEvent + DeserializeOwned + SendOutsideWasm + SyncOutsideWasm + 'static,
Ctx: EventHandlerContext + SendOutsideWasm + SyncOutsideWasm + 'static,
Observe a specific room, and event type.
This method works the same way as Client::observe_events
, except
that the observability will only be applied for events in the room with
the specified ID. See that method for more details.
sourcepub fn remove_event_handler(&self, handle: EventHandlerHandle)
pub fn remove_event_handler(&self, handle: EventHandlerHandle)
Remove the event handler associated with the handle.
Note that you must not call remove_event_handler
from the
non-async part of an event handler, that is:
client.add_event_handler(|ev: SomeEvent, client: Client, handle: EventHandlerHandle| {
// ⚠ this will cause a deadlock ⚠
client.remove_event_handler(handle);
async move {
// removing the event handler here is fine
client.remove_event_handler(handle);
}
})
Note also that handlers that remove themselves will still execute with events received in the same sync cycle.
§Arguments
handle
- The EventHandlerHandle
that is returned when
registering the event handler with Client::add_event_handler
.
§Examples
use matrix_sdk::{
event_handler::EventHandlerHandle,
ruma::events::room::member::SyncRoomMemberEvent, Client,
};
client.add_event_handler(
|ev: SyncRoomMemberEvent,
client: Client,
handle: EventHandlerHandle| async move {
// Common usage: Check arriving Event is the expected one
println!("Expected RoomMemberEvent received!");
client.remove_event_handler(handle);
},
);
sourcepub fn event_handler_drop_guard(
&self,
handle: EventHandlerHandle,
) -> EventHandlerDropGuard
pub fn event_handler_drop_guard( &self, handle: EventHandlerHandle, ) -> EventHandlerDropGuard
Create an EventHandlerDropGuard
for the event handler identified by
the given handle.
When the returned value is dropped, the event handler will be removed.
sourcepub fn add_event_handler_context<T>(&self, ctx: T)
pub fn add_event_handler_context<T>(&self, ctx: T)
Add an arbitrary value for use as event handler context.
The value can be obtained in an event handler by adding an argument of
the type Ctx<T>
.
If a value of the same type has been added before, it will be overwritten.
§Examples
use matrix_sdk::{
event_handler::Ctx, ruma::events::room::message::SyncRoomMessageEvent,
Room,
};
// Handle used to send messages to the UI part of the app
let my_gui_handle: SomeType = obtain_gui_handle();
client.add_event_handler_context(my_gui_handle.clone());
client.add_event_handler(
|ev: SyncRoomMessageEvent, room: Room, gui_handle: Ctx<SomeType>| {
async move {
// gui_handle.send(DisplayMessage { message: ev });
}
},
);
sourcepub async fn register_notification_handler<H, Fut>(&self, handler: H) -> &Selfwhere
H: Fn(Notification, Room, Client) -> Fut + SendOutsideWasm + SyncOutsideWasm + 'static,
Fut: Future<Output = ()> + SendOutsideWasm + 'static,
pub async fn register_notification_handler<H, Fut>(&self, handler: H) -> &Selfwhere
H: Fn(Notification, Room, Client) -> Fut + SendOutsideWasm + SyncOutsideWasm + 'static,
Fut: Future<Output = ()> + SendOutsideWasm + 'static,
Register a handler for a notification.
Similar to Client::add_event_handler
, but only allows functions
or closures with exactly the three arguments Notification
, Room
,
Client
for now.
sourcepub fn subscribe_to_room_updates(
&self,
room_id: &RoomId,
) -> Receiver<RoomUpdate>
pub fn subscribe_to_room_updates( &self, room_id: &RoomId, ) -> Receiver<RoomUpdate>
Subscribe to all updates for the room with the given ID.
The returned receiver will receive a new message for each sync response that contains updates for that room.
sourcepub fn subscribe_to_all_room_updates(&self) -> Receiver<RoomUpdates>
pub fn subscribe_to_all_room_updates(&self) -> Receiver<RoomUpdates>
Subscribe to all updates to all rooms, whenever any has been received in a sync response.
sourcepub fn rooms(&self) -> Vec<Room>
pub fn rooms(&self) -> Vec<Room>
Get all the rooms the client knows about.
This will return the list of joined, invited, and left rooms.
sourcepub fn rooms_filtered(&self, filter: RoomStateFilter) -> Vec<Room>
pub fn rooms_filtered(&self, filter: RoomStateFilter) -> Vec<Room>
Get all the rooms the client knows about, filtered by room state.
sourcepub fn rooms_stream(
&self,
) -> (Vector<Room>, impl Stream<Item = Vec<VectorDiff<Room>>> + '_)
pub fn rooms_stream( &self, ) -> (Vector<Room>, impl Stream<Item = Vec<VectorDiff<Room>>> + '_)
Get a stream of all the rooms, in addition to the existing rooms.
sourcepub fn joined_rooms(&self) -> Vec<Room>
pub fn joined_rooms(&self) -> Vec<Room>
Returns the joined rooms this client knows about.
sourcepub fn invited_rooms(&self) -> Vec<Room>
pub fn invited_rooms(&self) -> Vec<Room>
Returns the invited rooms this client knows about.
sourcepub fn left_rooms(&self) -> Vec<Room>
pub fn left_rooms(&self) -> Vec<Room>
Returns the left rooms this client knows about.
sourcepub fn get_room(&self, room_id: &RoomId) -> Option<Room>
pub fn get_room(&self, room_id: &RoomId) -> Option<Room>
Get a room with the given room id.
§Arguments
room_id
- The unique id of the room that should be fetched.
sourcepub async fn get_room_preview(
&self,
room_or_alias_id: &RoomOrAliasId,
via: Vec<OwnedServerName>,
) -> Result<RoomPreview>
pub async fn get_room_preview( &self, room_or_alias_id: &RoomOrAliasId, via: Vec<OwnedServerName>, ) -> Result<RoomPreview>
Gets the preview of a room, whether the current user knows it (because they’ve joined/left/been invited to it) or not.
sourcepub async fn resolve_room_alias(
&self,
room_alias: &RoomAliasId,
) -> HttpResult<Response>
pub async fn resolve_room_alias( &self, room_alias: &RoomAliasId, ) -> HttpResult<Response>
Resolve a room alias to a room id and a list of servers which know about it.
§Arguments
room_alias
- The room alias to be resolved.
sourcepub async fn is_room_alias_available(
&self,
alias: &RoomAliasId,
) -> HttpResult<bool>
pub async fn is_room_alias_available( &self, alias: &RoomAliasId, ) -> HttpResult<bool>
Checks if a room alias is not in use yet.
Returns:
Ok(true)
if the room alias is available.Ok(false)
if it’s not (the resolve alias request returned a404
status code).- An
Err
otherwise.
sourcepub async fn create_room_alias(
&self,
alias: &RoomAliasId,
room_id: &RoomId,
) -> HttpResult<()>
pub async fn create_room_alias( &self, alias: &RoomAliasId, room_id: &RoomId, ) -> HttpResult<()>
Creates a new room alias associated with a room.
sourcepub async fn restore_session(
&self,
session: impl Into<AuthSession>,
) -> Result<()>
pub async fn restore_session( &self, session: impl Into<AuthSession>, ) -> Result<()>
Restore a session previously logged-in using one of the available authentication APIs.
See the documentation of the corresponding authentication API’s
restore_session
method for more information.
§Panics
Panics if a session was already restored or logged in.
sourcepub async fn refresh_access_token(&self) -> Result<(), RefreshTokenError>
pub async fn refresh_access_token(&self) -> Result<(), RefreshTokenError>
Refresh the access token using the authentication API used to log into this session.
See the documentation of the authentication API’s refresh_access_token
method for more information.
sourcepub async fn get_or_upload_filter(
&self,
filter_name: &str,
definition: FilterDefinition,
) -> Result<String>
pub async fn get_or_upload_filter( &self, filter_name: &str, definition: FilterDefinition, ) -> Result<String>
Get or upload a sync filter.
This method will either get a filter ID from the store or upload the filter definition to the homeserver and return the new filter ID.
§Arguments
-
filter_name
- The unique name of the filter, this name will be used locally to store and identify the filter ID returned by the server. -
definition
- The filter definition that should be uploaded to the server if no filter ID can be found in the store.
§Examples
let mut filter = FilterDefinition::default();
// Let's enable member lazy loading.
filter.room.state.lazy_load_options =
LazyLoadOptions::Enabled { include_redundant_members: false };
let filter_id = client
.get_or_upload_filter("sync", filter)
.await
.unwrap();
let sync_settings = SyncSettings::new()
.filter(Filter::FilterId(filter_id));
let response = client.sync_once(sync_settings).await.unwrap();
sourcepub async fn join_room_by_id(&self, room_id: &RoomId) -> Result<Room>
pub async fn join_room_by_id(&self, room_id: &RoomId) -> Result<Room>
Join a room by RoomId
.
Returns a join_room_by_id::Response
consisting of the
joined rooms RoomId
.
§Arguments
room_id
- TheRoomId
of the room to be joined.
sourcepub async fn join_room_by_id_or_alias(
&self,
alias: &RoomOrAliasId,
server_names: &[OwnedServerName],
) -> Result<Room>
pub async fn join_room_by_id_or_alias( &self, alias: &RoomOrAliasId, server_names: &[OwnedServerName], ) -> Result<Room>
Join a room by RoomId
.
Returns a join_room_by_id_or_alias::Response
consisting of the
joined rooms RoomId
.
§Arguments
alias
- TheRoomId
orRoomAliasId
of the room to be joined. An alias looks like#name:example.com
.
sourcepub async fn public_rooms(
&self,
limit: Option<u32>,
since: Option<&str>,
server: Option<&ServerName>,
) -> HttpResult<Response>
pub async fn public_rooms( &self, limit: Option<u32>, since: Option<&str>, server: Option<&ServerName>, ) -> HttpResult<Response>
Search the homeserver’s directory of public rooms.
Sends a request to “_matrix/client/r0/publicRooms”, returns
a get_public_rooms::Response
.
§Arguments
-
limit
- The number ofPublicRoomsChunk
s in each response. -
since
- Pagination token from a previous request. -
server
- The name of the server, ifNone
the requested server is used.
§Examples
use matrix_sdk::Client;
let mut client = Client::new(homeserver).await.unwrap();
client.public_rooms(limit, since, server).await;
sourcepub async fn create_room(&self, request: Request) -> Result<Room>
pub async fn create_room(&self, request: Request) -> Result<Room>
Create a room with the given parameters.
Sends a request to /_matrix/client/r0/createRoom
and returns the
created room.
If you want to create a direct message with one specific user, you can
use create_dm
, which is more convenient than
assembling the create_room::v3::Request
yourself.
If the is_direct
field of the request is set to true
and at least
one user is invited, the room will be automatically added to the direct
rooms in the account data.
§Examples
use matrix_sdk::{
ruma::api::client::room::create_room::v3::Request as CreateRoomRequest,
Client,
};
let request = CreateRoomRequest::new();
let client = Client::new(homeserver).await.unwrap();
assert!(client.create_room(request).await.is_ok());
sourcepub async fn create_dm(&self, user_id: &UserId) -> Result<Room>
pub async fn create_dm(&self, user_id: &UserId) -> Result<Room>
Create a DM room.
Convenience shorthand for create_room
with the
given user being invited, the room marked is_direct
and both the
creator and invitee getting the default maximum power level.
If the e2e-encryption
feature is enabled, the room will also be
encrypted.
§Arguments
user_id
- The ID of the user to create a DM for.
sourcepub async fn public_rooms_filtered(
&self,
request: Request,
) -> HttpResult<Response>
pub async fn public_rooms_filtered( &self, request: Request, ) -> HttpResult<Response>
Search the homeserver’s directory for public rooms with a filter.
§Arguments
room_search
- The easiest way to create this request is using theget_public_rooms_filtered::Request
itself.
§Examples
use matrix_sdk::ruma::{
api::client::directory::get_public_rooms_filtered, directory::Filter,
};
let mut filter = Filter::new();
filter.generic_search_term = Some("rust".to_owned());
let mut request = get_public_rooms_filtered::v3::Request::new();
request.filter = filter;
let response = client.public_rooms_filtered(request).await?;
for room in response.chunk {
println!("Found room {room:?}");
}
sourcepub fn send<Request>(
&self,
request: Request,
config: Option<RequestConfig>,
) -> SendRequest<Request>where
Request: OutgoingRequest + Clone + Debug,
HttpError: From<FromHttpResponseError<Request::EndpointError>>,
pub fn send<Request>(
&self,
request: Request,
config: Option<RequestConfig>,
) -> SendRequest<Request>where
Request: OutgoingRequest + Clone + Debug,
HttpError: From<FromHttpResponseError<Request::EndpointError>>,
Send an arbitrary request to the server, without updating client state.
Warning: Because this method does not update the client state, it is important to make sure that you account for this yourself, and use wrapper methods where available. This method should only be used if a wrapper method for the endpoint you’d like to use is not available.
§Arguments
-
request
- A filled out and valid request for the endpoint to be hit -
timeout
- An optional request timeout setting, this overrides the default request setting if one was set.
§Examples
use matrix_sdk::ruma::{api::client::profile, user_id};
// First construct the request you want to make
// See https://docs.rs/ruma-client-api/latest/ruma_client_api/index.html
// for all available Endpoints
let user_id = user_id!("@example:localhost").to_owned();
let request = profile::get_profile::v3::Request::new(user_id);
// Start the request using Client::send()
let response = client.send(request, None).await?;
// Check the corresponding Response struct to find out what types are
// returned
sourcepub async fn unstable_features(&self) -> HttpResult<BTreeMap<String, bool>>
pub async fn unstable_features(&self) -> HttpResult<BTreeMap<String, bool>>
Get unstable features from by fetching from the server or the cache.
§Examples
let unstable_features = client.unstable_features().await?;
let msc_x = unstable_features.get("msc_x").unwrap_or(&false);
sourcepub async fn reset_server_capabilities(&self) -> Result<()>
pub async fn reset_server_capabilities(&self) -> Result<()>
Empty the server version and unstable features cache.
Since the SDK caches server capabilities (versions and unstable features), it’s possible to have a stale entry in the cache. This functions makes it possible to force reset it.
sourcepub async fn can_homeserver_push_encrypted_event_to_device(
&self,
) -> HttpResult<bool>
pub async fn can_homeserver_push_encrypted_event_to_device( &self, ) -> HttpResult<bool>
Check whether MSC 4028 is enabled on the homeserver.
§Examples
let msc4028_enabled =
client.can_homeserver_push_encrypted_event_to_device().await?;
sourcepub async fn devices(&self) -> HttpResult<Response>
pub async fn devices(&self) -> HttpResult<Response>
Get information of all our own devices.
§Examples
let response = client.devices().await?;
for device in response.devices {
println!(
"Device: {} {}",
device.device_id,
device.display_name.as_deref().unwrap_or("")
);
}
sourcepub async fn delete_devices(
&self,
devices: &[OwnedDeviceId],
auth_data: Option<AuthData>,
) -> HttpResult<Response>
pub async fn delete_devices( &self, devices: &[OwnedDeviceId], auth_data: Option<AuthData>, ) -> HttpResult<Response>
Delete the given devices from the server.
§Arguments
-
devices
- The list of devices that should be deleted from the server. -
auth_data
- This request requires user interactive auth, the first request needs to set this toNone
and will always fail with anUiaaResponse
. The response will contain information for the interactive auth and the same request needs to be made but this time with someauth_data
provided.
let devices = &[device_id!("DEVICEID").to_owned()];
if let Err(e) = client.delete_devices(devices, None).await {
if let Some(info) = e.as_uiaa_response() {
let mut password = uiaa::Password::new(
uiaa::UserIdentifier::UserIdOrLocalpart("example".to_owned()),
"wordpass".to_owned(),
);
password.session = info.session.clone();
client
.delete_devices(devices, Some(uiaa::AuthData::Password(password)))
.await?;
}
}
sourcepub async fn rename_device(
&self,
device_id: &DeviceId,
display_name: &str,
) -> HttpResult<Response>
pub async fn rename_device( &self, device_id: &DeviceId, display_name: &str, ) -> HttpResult<Response>
Change the display name of a device owned by the current user.
Returns a update_device::Response
which specifies the result
of the operation.
§Arguments
device_id
- The ID of the device to change the display name of.display_name
- The new display name to set.
sourcepub async fn sync_once(
&self,
sync_settings: SyncSettings,
) -> Result<SyncResponse>
pub async fn sync_once( &self, sync_settings: SyncSettings, ) -> Result<SyncResponse>
Synchronize the client’s state with the latest state on the server.
§Syncing Events
Messages or any other type of event need to be periodically fetched from
the server, this is achieved by sending a /sync
request to the server.
The first sync is sent out without a token
. The response of the
first sync will contain a next_batch
field which should then be
used in the subsequent sync calls as the token
. This ensures that we
don’t receive the same events multiple times.
§Long Polling
A sync should in the usual case always be in flight. The
SyncSettings
have a timeout
option, which controls how
long the server will wait for new events before it will respond.
The server will respond immediately if some new events arrive before the
timeout has expired. If no changes arrive and the timeout expires an
empty sync response will be sent to the client.
This method of sending a request that may not receive a response immediately is called long polling.
§Filtering Events
The number or type of messages and events that the client should receive
from the server can be altered using a Filter
.
Filters can be non-trivial and, since they will be sent with every sync request, they may take up a bunch of unnecessary bandwidth.
Luckily filters can be uploaded to the server and reused using an unique
identifier, this can be achieved using the get_or_upload_filter()
method.
§Arguments
sync_settings
- Settings for the sync call, this allows us to set various options to configure the sync:filter
- To configure which events we receive and which get filtered by the servertimeout
- To configure our long polling setup.token
- To tell the server which events we already received and where we wish to continue syncing.full_state
- To tell the server that we wish to receive all state events, regardless of our configuredtoken
.set_presence
- To tell the server to set the presence and to which state.
§Examples
use matrix_sdk::{
config::SyncSettings,
ruma::events::room::message::OriginalSyncRoomMessageEvent, Client,
};
let client = Client::new(homeserver).await?;
client.matrix_auth().login_username(username, password).send().await?;
// Sync once so we receive the client state and old messages.
client.sync_once(SyncSettings::default()).await?;
// Register our handler so we start responding once we receive a new
// event.
client.add_event_handler(|ev: OriginalSyncRoomMessageEvent| async move {
println!("Received event {}: {:?}", ev.sender, ev.content);
});
// Now keep on syncing forever. `sync()` will use the stored sync token
// from our `sync_once()` call automatically.
client.sync(SyncSettings::default()).await;
sourcepub async fn sync(&self, sync_settings: SyncSettings) -> Result<(), Error>
pub async fn sync(&self, sync_settings: SyncSettings) -> Result<(), Error>
Repeatedly synchronize the client state with the server.
This method will only return on error, if cancellation is needed
the method should be wrapped in a cancelable task or the
Client::sync_with_callback
method can be used or
Client::sync_with_result_callback
if you want to handle error
cases in the loop, too.
This method will internally call Client::sync_once
in a loop.
This method can be used with the Client::add_event_handler
method to react to individual events. If you instead wish to handle
events in a bulk manner the Client::sync_with_callback
,
Client::sync_with_result_callback
and
Client::sync_stream
methods can be used instead. Those methods
repeatedly return the whole sync response.
§Arguments
sync_settings
- Settings for the sync call. Note that those settings will be only used for the first sync call. See the argument docs forClient::sync_once
for more info.
§Return
The sync runs until an error occurs, returning with Err(Error)
. It is
up to the user of the API to check the error and decide whether the sync
should continue or not.
§Examples
use matrix_sdk::{
config::SyncSettings,
ruma::events::room::message::OriginalSyncRoomMessageEvent, Client,
};
let client = Client::new(homeserver).await?;
client.matrix_auth().login_username(&username, &password).send().await?;
// Register our handler so we start responding once we receive a new
// event.
client.add_event_handler(|ev: OriginalSyncRoomMessageEvent| async move {
println!("Received event {}: {:?}", ev.sender, ev.content);
});
// Now keep on syncing forever. `sync()` will use the latest sync token
// automatically.
client.sync(SyncSettings::default()).await?;
sourcepub async fn sync_with_callback<C>(
&self,
sync_settings: SyncSettings,
callback: impl Fn(SyncResponse) -> C,
) -> Result<(), Error>
pub async fn sync_with_callback<C>( &self, sync_settings: SyncSettings, callback: impl Fn(SyncResponse) -> C, ) -> Result<(), Error>
Repeatedly call sync to synchronize the client state with the server.
§Arguments
-
sync_settings
- Settings for the sync call. Note that those settings will be only used for the first sync call. See the argument docs forClient::sync_once
for more info. -
callback
- A callback that will be called every time a successful response has been fetched from the server. The callback must return a boolean which signalizes if the method should stop syncing. If the callback returnsLoopCtrl::Continue
the sync will continue, if the callback returnsLoopCtrl::Break
the sync will be stopped.
§Return
The sync runs until an error occurs or the
callback indicates that the Loop should stop. If the callback asked for
a regular stop, the result will be Ok(())
otherwise the
Err(Error)
is returned.
§Examples
The following example demonstrates how to sync forever while sending all the interesting events through a mpsc channel to another thread e.g. a UI thread.
use tokio::sync::mpsc::channel;
let (tx, rx) = channel(100);
let sync_channel = &tx;
let sync_settings = SyncSettings::new()
.timeout(Duration::from_secs(30));
client
.sync_with_callback(sync_settings, |response| async move {
let channel = sync_channel;
for (room_id, room) in response.rooms.join {
for event in room.timeline.events {
channel.send(event).await.unwrap();
}
}
LoopCtrl::Continue
})
.await;
};
sourcepub async fn sync_with_result_callback<C>(
&self,
sync_settings: SyncSettings,
callback: impl Fn(Result<SyncResponse, Error>) -> C,
) -> Result<(), Error>
pub async fn sync_with_result_callback<C>( &self, sync_settings: SyncSettings, callback: impl Fn(Result<SyncResponse, Error>) -> C, ) -> Result<(), Error>
Repeatedly call sync to synchronize the client state with the server.
§Arguments
-
sync_settings
- Settings for the sync call. Note that those settings will be only used for the first sync call. See the argument docs forClient::sync_once
for more info. -
callback
- A callback that will be called every time after a response has been received, failure or not. The callback returns aResult<LoopCtrl, Error>
, too. When returningOk(LoopCtrl::Continue)
the sync will continue, if the callback returnsOk(LoopCtrl::Break)
the sync will be stopped and the function returnsOk(())
. In case the callback can’t handle theError
or has a different malfunction, it can return anErr(Error)
, which results in the sync ending and theErr(Error)
being returned.
§Return
The sync runs until an error occurs that the callback can’t handle or
the callback indicates that the Loop should stop. If the callback
asked for a regular stop, the result will be Ok(())
otherwise the
Err(Error)
is returned.
Note: Lower-level configuration (e.g. for retries) are not changed by
this, and are handled first without sending the result to the
callback. Only after they have exceeded is the Result
handed to
the callback.
§Examples
The following example demonstrates how to sync forever while sending all the interesting events through a mpsc channel to another thread e.g. a UI thread.
use tokio::sync::mpsc::channel;
let (tx, rx) = channel(100);
let sync_channel = &tx;
let sync_settings = SyncSettings::new()
.timeout(Duration::from_secs(30));
client
.sync_with_result_callback(sync_settings, |response| async move {
let channel = sync_channel;
let sync_response = response?;
for (room_id, room) in sync_response.rooms.join {
for event in room.timeline.events {
channel.send(event).await.unwrap();
}
}
Ok(LoopCtrl::Continue)
})
.await;
};
sourcepub async fn sync_stream(
&self,
sync_settings: SyncSettings,
) -> impl Stream<Item = Result<SyncResponse>> + '_
pub async fn sync_stream( &self, sync_settings: SyncSettings, ) -> impl Stream<Item = Result<SyncResponse>> + '_
This method will internally call Client::sync_once
in a loop and is
equivalent to the Client::sync
method but the responses are provided
as an async stream.
§Arguments
sync_settings
- Settings for the sync call. Note that those settings will be only used for the first sync call. See the argument docs forClient::sync_once
for more info.
§Examples
use futures_util::StreamExt;
use matrix_sdk::{config::SyncSettings, Client};
let client = Client::new(homeserver).await?;
client.matrix_auth().login_username(&username, &password).send().await?;
let mut sync_stream =
Box::pin(client.sync_stream(SyncSettings::default()).await);
while let Some(Ok(response)) = sync_stream.next().await {
for room in response.rooms.join.values() {
for e in &room.timeline.events {
if let Ok(event) = e.raw().deserialize() {
println!("Received event {:?}", event);
}
}
}
}
sourcepub async fn whoami(&self) -> HttpResult<Response>
pub async fn whoami(&self) -> HttpResult<Response>
Gets information about the owner of a given access token.
sourcepub fn subscribe_to_session_changes(&self) -> Receiver<SessionChange>
pub fn subscribe_to_session_changes(&self) -> Receiver<SessionChange>
Subscribes a new receiver to client SessionChange broadcasts.
sourcepub fn set_session_callbacks(
&self,
reload_session_callback: Box<dyn Fn(Client) -> Result<SessionTokens, Box<dyn Error + Send + Sync>> + Send + Sync>,
save_session_callback: Box<dyn Fn(Client) -> Result<(), Box<dyn Error + Send + Sync>> + Send + Sync>,
) -> Result<()>
pub fn set_session_callbacks( &self, reload_session_callback: Box<dyn Fn(Client) -> Result<SessionTokens, Box<dyn Error + Send + Sync>> + Send + Sync>, save_session_callback: Box<dyn Fn(Client) -> Result<(), Box<dyn Error + Send + Sync>> + Send + Sync>, ) -> Result<()>
Sets the save/restore session callbacks.
This is another mechanism to get synchronous updates to session tokens,
while Self::subscribe_to_session_changes
provides an async update.
sourcepub async fn notification_settings(&self) -> NotificationSettings
pub async fn notification_settings(&self) -> NotificationSettings
Get the notification settings of the current owner of the client.
sourcepub async fn notification_client(
&self,
cross_process_store_locks_holder_name: String,
) -> Result<Client>
pub async fn notification_client( &self, cross_process_store_locks_holder_name: String, ) -> Result<Client>
Create a new specialized Client
that can process notifications.
See CrossProcessStoreLock::new
to learn more about
cross_process_store_locks_holder_name
.
sourcepub fn event_cache(&self) -> &EventCache
pub fn event_cache(&self) -> &EventCache
The EventCache
instance for this Client
.
sourcepub async fn await_room_remote_echo(&self, room_id: &RoomId) -> Room
pub async fn await_room_remote_echo(&self, room_id: &RoomId) -> Room
Waits until an at least partially synced room is received, and returns it.
Note: this function will loop endlessly until either it finds the room or an externally set timeout happens.
sourcepub async fn knock(
&self,
room_id_or_alias: OwnedRoomOrAliasId,
reason: Option<String>,
server_names: Vec<OwnedServerName>,
) -> Result<Room>
pub async fn knock( &self, room_id_or_alias: OwnedRoomOrAliasId, reason: Option<String>, server_names: Vec<OwnedServerName>, ) -> Result<Room>
Knock on a room given its room_id_or_alias
to ask for permission to
join it.
source§impl Client
impl Client
sourcepub fn upload_encrypted_file<'a, R: Read + ?Sized + 'a>(
&'a self,
content_type: &'a Mime,
reader: &'a mut R,
) -> UploadEncryptedFile<'a, R>
pub fn upload_encrypted_file<'a, R: Read + ?Sized + 'a>( &'a self, content_type: &'a Mime, reader: &'a mut R, ) -> UploadEncryptedFile<'a, R>
Construct a EncryptedFile
by
encrypting and uploading a provided reader.
§Arguments
content_type
- The content type of the file.reader
- The reader that should be encrypted and uploaded.
§Examples
use serde::{Deserialize, Serialize};
use matrix_sdk::ruma::events::{macros::EventContent, room::EncryptedFile};
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "com.example.custom", kind = MessageLike)]
struct CustomEventContent {
encrypted_file: EncryptedFile,
}
let mut reader = std::io::Cursor::new(b"Hello, world!");
let encrypted_file = client.upload_encrypted_file(&mime::TEXT_PLAIN, &mut reader).await?;
room.send(CustomEventContent { encrypted_file }).await?;
sourcepub fn get_dm_room(&self, user_id: &UserId) -> Option<Room>
pub fn get_dm_room(&self, user_id: &UserId) -> Option<Room>
Get the existing DM room with the given user, if any.
source§impl Client
impl Client
sourcepub fn send_queue(&self) -> SendQueue
pub fn send_queue(&self) -> SendQueue
Returns a SendQueue
that handles sending, retrying and not
forgetting about requests that are to be sent.
source§impl Client
impl Client
sourcepub async fn available_sliding_sync_versions(&self) -> Vec<Version>
pub async fn available_sliding_sync_versions(&self) -> Vec<Version>
Find all sliding sync versions that are available.
Be careful: This method may hit the store and will send new requests for each call. It can be costly to call it repeatedly.
If .well-known
or /versions
is unreachable, it will simply move
potential sliding sync versions aside. No error will be reported.
sourcepub fn sliding_sync(&self, id: impl Into<String>) -> Result<SlidingSyncBuilder>
pub fn sliding_sync(&self, id: impl Into<String>) -> Result<SlidingSyncBuilder>
Create a SlidingSyncBuilder
tied to this client, with the given
identifier.
Note: the identifier must not be more than 16 chars long!
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Client
impl !RefUnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl !UnwindSafe for Client
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more