matrix_sdk/room/messages.rs
1// Copyright 2023 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt;
16
17use matrix_sdk_common::{debug::DebugStructExt as _, deserialized_responses::TimelineEvent};
18use ruma::{
19 api::{
20 client::{filter::RoomEventFilter, message::get_message_events},
21 Direction,
22 },
23 assign,
24 events::AnyStateEvent,
25 serde::Raw,
26 uint, RoomId, UInt,
27};
28
29/// Options for [`messages`][super::Room::messages].
30///
31/// See that method and
32/// <https://spec.matrix.org/v1.3/client-server-api/#get_matrixclientv3roomsroomidmessages>
33/// for details.
34#[non_exhaustive]
35pub struct MessagesOptions {
36 /// The token to start returning events from.
37 ///
38 /// This token can be obtained from a `prev_batch` token returned for each
39 /// room from the sync API, or from a start or end token returned by a
40 /// previous `messages` call.
41 ///
42 /// If `from` isn't provided the homeserver shall return a list of messages
43 /// from the first or last (per the value of the dir parameter) visible
44 /// event in the room history for the requesting user.
45 pub from: Option<String>,
46
47 /// The token to stop returning events at.
48 ///
49 /// This token can be obtained from a `prev_batch` token returned for each
50 /// room by the sync API, or from a start or end token returned by a
51 /// previous `messages` call.
52 pub to: Option<String>,
53
54 /// The direction to return events in.
55 pub dir: Direction,
56
57 /// The maximum number of events to return.
58 ///
59 /// Default: 10.
60 pub limit: UInt,
61
62 /// A [`RoomEventFilter`] to filter returned events with.
63 pub filter: RoomEventFilter,
64}
65
66impl MessagesOptions {
67 /// Creates `MessagesOptions` with the given direction.
68 ///
69 /// All other parameters will be defaulted.
70 pub fn new(dir: Direction) -> Self {
71 Self { from: None, to: None, dir, limit: uint!(10), filter: RoomEventFilter::default() }
72 }
73
74 /// Creates `MessagesOptions` with `dir` set to `Backward`.
75 ///
76 /// If no `from` token is set afterwards, pagination will start at the
77 /// end of (the accessible part of) the room timeline.
78 pub fn backward() -> Self {
79 Self::new(Direction::Backward)
80 }
81
82 /// Creates `MessagesOptions` with `dir` set to `Forward`.
83 ///
84 /// If no `from` token is set afterwards, pagination will start at the
85 /// beginning of (the accessible part of) the room timeline.
86 pub fn forward() -> Self {
87 Self::new(Direction::Forward)
88 }
89
90 /// Creates a new `MessagesOptions` from `self` with the `from` field set to
91 /// the given value.
92 ///
93 /// Since the field is public, you can also assign to it directly. This
94 /// method merely acts as a shorthand for that, because it is very
95 /// common to set this field.
96 pub fn from<'a>(self, from: impl Into<Option<&'a str>>) -> Self {
97 Self { from: from.into().map(ToOwned::to_owned), ..self }
98 }
99
100 pub(super) fn into_request(self, room_id: &RoomId) -> get_message_events::v3::Request {
101 assign!(get_message_events::v3::Request::new(room_id.to_owned(), self.dir), {
102 from: self.from,
103 to: self.to,
104 limit: self.limit,
105 filter: self.filter,
106 })
107 }
108}
109
110#[cfg(not(tarpaulin_include))]
111impl fmt::Debug for MessagesOptions {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 let Self { from, to, dir, limit, filter } = self;
114
115 let mut s = f.debug_struct("MessagesOptions");
116 s.maybe_field("from", from).maybe_field("to", to).field("dir", dir).field("limit", limit);
117 if !filter.is_empty() {
118 s.field("filter", filter);
119 }
120 s.finish()
121 }
122}
123
124/// The result of a [`super::Room::messages`] call.
125///
126/// In short, this is a possibly decrypted version of the response of a
127/// `room/messages` api call.
128#[derive(Debug, Default)]
129pub struct Messages {
130 /// The token the pagination starts from.
131 pub start: String,
132
133 /// The token the pagination ends at.
134 pub end: Option<String>,
135
136 /// A list of room events.
137 pub chunk: Vec<TimelineEvent>,
138
139 /// A list of state events relevant to showing the `chunk`.
140 pub state: Vec<Raw<AnyStateEvent>>,
141}
142
143/// The result of a [`super::Room::event_with_context`] query.
144///
145/// This is a wrapper around
146/// [`ruma::api::client::context::get_context::v3::Response`], with events
147/// decrypted if needs be.
148#[derive(Debug, Default)]
149pub struct EventWithContextResponse {
150 /// The event targeted by the /context query.
151 pub event: Option<TimelineEvent>,
152
153 /// Events before the target event, if a non-zero context size was
154 /// requested.
155 ///
156 /// Like the corresponding Ruma response, these are in reverse chronological
157 /// order.
158 pub events_before: Vec<TimelineEvent>,
159
160 /// Events after the target event, if a non-zero context size was requested.
161 ///
162 /// Like the corresponding Ruma response, these are in chronological order.
163 pub events_after: Vec<TimelineEvent>,
164
165 /// Token to paginate backwards, aka "start" token.
166 pub prev_batch_token: Option<String>,
167
168 /// Token to paginate forwards, aka "end" token.
169 pub next_batch_token: Option<String>,
170
171 /// State events related to the request.
172 ///
173 /// If lazy-loading of members was requested, this may contain room
174 /// membership events.
175 pub state: Vec<Raw<AnyStateEvent>>,
176}