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

source

pub async fn new(homeserver_url: Url) -> Result<Self, ClientBuildError>

Create a new Client that will use the given homeserver.

§Arguments
  • homeserver_url - The homeserver that the client should connect to.
source

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.

source

pub fn builder() -> ClientBuilder

Create a new ClientBuilder.

source

pub fn http_client(&self) -> &Client

The underlying HTTP client.

source

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.

source

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
}
source

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().

source

pub fn logged_in(&self) -> bool

Is the client logged in.

source

pub fn server(&self) -> Option<&Url>

The server used by the client.

See Self::server to learn more.

source

pub fn homeserver(&self) -> Url

The homeserver of the client.

source

pub fn sliding_sync_version(&self) -> SlidingSyncVersion

Available on crate feature experimental-sliding-sync only.

Get the sliding sync version.

source

pub fn set_sliding_sync_version(&self, version: SlidingSyncVersion)

Available on crate feature experimental-sliding-sync only.

Override the sliding sync version.

source

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.

source

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.

source

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 search
  • limit - The maximum number of results to return. Defaults to 10.
source

pub fn user_id(&self) -> Option<&UserId>

Get the user id of the current owner of the client.

source

pub fn device_id(&self) -> Option<&DeviceId>

Get the device ID that identifies the current session.

source

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.

source

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.

source

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.

source

pub fn store(&self) -> &DynStateStore

Get a reference to the state store.

source

pub fn matrix_auth(&self) -> MatrixAuth

Access the native Matrix authentication API with this client.

source

pub fn account(&self) -> Account

Get the account of the current owner of the client.

source

pub fn encryption(&self) -> Encryption

Available on crate feature e2e-encryption only.

Get the encryption manager of the client.

source

pub fn media(&self) -> Media

Get the media manager of the client.

source

pub fn pusher(&self) -> Pusher

Get the pusher manager of the client.

source

pub fn oidc(&self) -> Oidc

Available on crate feature experimental-oidc only.

Access the OpenID Connect API of the client.

source

pub fn add_event_handler<Ev, Ctx, H>(&self, handler: H) -> EventHandlerHandle
where Ev: SyncEvent + DeserializeOwned + SendOutsideWasm + 'static, H: EventHandler<Ev, Ctx>,

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}");
});
source

pub fn add_room_event_handler<Ev, Ctx, H>( &self, room_id: &RoomId, handler: H, ) -> EventHandlerHandle
where Ev: SyncEvent + DeserializeOwned + SendOutsideWasm + 'static, H: EventHandler<Ev, Ctx>,

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.

source

pub fn observe_events<Ev, Ctx>(&self) -> ObservableEventHandler<(Ev, Ctx)>

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, ()>();
source

pub fn observe_room_events<Ev, Ctx>( &self, room_id: &RoomId, ) -> ObservableEventHandler<(Ev, Ctx)>

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.

source

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);
    },
);
source

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.

source

pub fn add_event_handler_context<T>(&self, ctx: T)
where T: Clone + Send + Sync + 'static,

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 });
        }
    },
);
source

pub async fn register_notification_handler<H, Fut>(&self, handler: H) -> &Self
where 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.

source

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.

source

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.

source

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.

source

pub fn rooms_filtered(&self, filter: RoomStateFilter) -> Vec<Room>

Get all the rooms the client knows about, filtered by room state.

source

pub fn rooms_stream( &self, ) -> (Vector<Room>, impl Stream<Item = Vec<VectorDiff<Room>>> + '_)

Available on non-WebAssembly only.

Get a stream of all the rooms, in addition to the existing rooms.

source

pub fn joined_rooms(&self) -> Vec<Room>

Returns the joined rooms this client knows about.

source

pub fn invited_rooms(&self) -> Vec<Room>

Returns the invited rooms this client knows about.

source

pub fn left_rooms(&self) -> Vec<Room>

Returns the left rooms this client knows about.

source

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.

source

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.

source

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.

source

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 a 404 status code).
  • An Err otherwise.
source

pub async fn create_room_alias( &self, alias: &RoomAliasId, room_id: &RoomId, ) -> HttpResult<()>

Creates a new room alias associated with a room.

source

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.

source

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.

source

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();
source

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 - The RoomId of the room to be joined.
source

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 - The RoomId or RoomAliasId of the room to be joined. An alias looks like #name:example.com.
source

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 of PublicRoomsChunks in each response.

  • since - Pagination token from a previous request.

  • server - The name of the server, if None 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;
source

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());
source

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.
source

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 the get_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:?}");
}
source

pub fn send<Request>( &self, request: Request, config: Option<RequestConfig>, ) -> SendRequest<Request>

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
source

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);
source

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.

source

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?;
source

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("")
    );
}
source

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 to None and will always fail with an UiaaResponse. The response will contain information for the interactive auth and the same request needs to be made but this time with some auth_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?;
    }
}
source

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.
source

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 server
    • timeout - 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 configured token.
    • 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;
source

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 for Client::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?;
source

pub async fn sync_with_callback<C>( &self, sync_settings: SyncSettings, callback: impl Fn(SyncResponse) -> C, ) -> Result<(), Error>
where C: Future<Output = LoopCtrl>,

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 for Client::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 returns LoopCtrl::Continue the sync will continue, if the callback returns LoopCtrl::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;
};
source

pub async fn sync_with_result_callback<C>( &self, sync_settings: SyncSettings, callback: impl Fn(Result<SyncResponse, Error>) -> C, ) -> Result<(), Error>
where C: Future<Output = Result<LoopCtrl, 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 for Client::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 a Result<LoopCtrl, Error>, too. When returning Ok(LoopCtrl::Continue) the sync will continue, if the callback returns Ok(LoopCtrl::Break) the sync will be stopped and the function returns Ok(()). In case the callback can’t handle the Error or has a different malfunction, it can return an Err(Error), which results in the sync ending and the Err(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;
};
source

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 for Client::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);
            }
        }
    }
}
source

pub async fn whoami(&self) -> HttpResult<Response>

Gets information about the owner of a given access token.

source

pub fn subscribe_to_session_changes(&self) -> Receiver<SessionChange>

Subscribes a new receiver to client SessionChange broadcasts.

source

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.

source

pub async fn notification_settings(&self) -> NotificationSettings

Get the notification settings of the current owner of the client.

source

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.

source

pub fn event_cache(&self) -> &EventCache

The EventCache instance for this Client.

source

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.

source

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

source

pub fn upload_encrypted_file<'a, R: Read + ?Sized + 'a>( &'a self, content_type: &'a Mime, reader: &'a mut R, ) -> UploadEncryptedFile<'a, R>

Available on crate feature e2e-encryption only.

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?;
source

pub fn get_dm_room(&self, user_id: &UserId) -> Option<Room>

Available on crate feature e2e-encryption only.

Get the existing DM room with the given user, if any.

source§

impl Client

source

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

source

pub async fn available_sliding_sync_versions(&self) -> Vec<Version>

Available on crate feature experimental-sliding-sync only.

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.

source

pub fn sliding_sync(&self, id: impl Into<String>) -> Result<SlidingSyncBuilder>

Available on crate feature experimental-sliding-sync only.

Create a SlidingSyncBuilder tied to this client, with the given identifier.

Note: the identifier must not be more than 16 chars long!

Trait Implementations§

source§

impl Clone for Client

source§

fn clone(&self) -> Client

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Client

Available on non-tarpaulin_include only.
source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
source§

impl EventHandlerContext for Client

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> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where T: Clone,

source§

default unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T> CompatExt for T

§

fn compat(self) -> Compat<T>

Applies the [Compat] adapter by value. Read more
§

fn compat_ref(&self) -> Compat<&T>

Applies the [Compat] adapter by shared reference. Read more
§

fn compat_mut(&mut self) -> Compat<&mut T>

Applies the [Compat] adapter by mutable reference. Read more
source§

impl<T> DynClone for T
where T: Clone,

source§

fn __clone_box(&self, _: Private) -> *mut ()

source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> FromRef<T> for T
where T: Clone,

source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
source§

impl<T> FutureExt for T

source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
source§

impl<T, UT> HandleAlloc<UT> for T
where T: Send + Sync,

source§

fn new_handle(value: Arc<T>) -> Handle

Create a new handle for an Arc value Read more
source§

fn clone_handle(handle: Handle) -> Handle

Clone a handle Read more
source§

fn consume_handle(handle: Handle) -> Arc<T>

Consume a handle, getting back the initial Arc<>
source§

fn get_arc(handle: Handle) -> Arc<Self>

Get a clone of the Arc<> using a “borrowed” handle. Read more
source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

source§

const WITNESS: W = W::MAKE

A constant of the type witness
source§

impl<T> Identity for T
where T: ?Sized,

§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
source§

impl<T> Any for T
where T: Any,

source§

impl<T> AsyncTraitDeps for T

source§

impl<T> CloneAny for T
where T: Any + Clone,

source§

impl<T> CloneAnySend for T
where T: Any + Send + Clone,

source§

impl<T> CloneAnySendSync for T
where T: Any + Send + Sync + Clone,

source§

impl<T> CloneAnySync for T
where T: Any + Sync + Clone,

source§

impl<T> SendOutsideWasm for T
where T: Send,

source§

impl<T> SyncOutsideWasm for T
where T: Sync,