//! `GET /_matrix/client/*/rooms/{roomId}/messages` pub mod v3 { //! `/v3/` ([spec]) //! //! [spec]: https://spec.matrix.org/v1.2/client-server-api/#get_matrixclientv3roomsroomidmessages use js_int::{uint, UInt}; use ruma_common::{ api::ruma_api, events::{AnyRoomEvent, AnyStateEvent}, }; use ruma_identifiers::RoomId; use ruma_serde::Raw; use serde::{Deserialize, Serialize}; use crate::filter::{IncomingRoomEventFilter, RoomEventFilter}; ruma_api! { metadata: { description: "Get message events for a room.", method: GET, name: "get_message_events", r0_path: "/_matrix/client/r0/rooms/:room_id/messages", stable_path: "/_matrix/client/v3/rooms/:room_id/messages", rate_limited: false, authentication: AccessToken, added: 1.0, } request: { /// The room to get events from. #[ruma_api(path)] pub room_id: &'a RoomId, /// The token to start returning events from. /// /// This token can be obtained from a /// prev_batch token returned for each room by the sync API, or from a start or end token /// returned by a previous request to this endpoint. #[ruma_api(query)] pub from: &'a str, /// The token to stop returning events at. /// /// This token can be obtained from a prev_batch /// token returned for each room by the sync endpoint, or from a start or end token returned /// by a previous request to this endpoint. #[serde(skip_serializing_if = "Option::is_none")] #[ruma_api(query)] pub to: Option<&'a str>, /// The direction to return events from. #[ruma_api(query)] pub dir: Direction, /// The maximum number of events to return. /// /// Default: 10. #[ruma_api(query)] #[serde(default = "default_limit", skip_serializing_if = "is_default_limit")] pub limit: UInt, /// A RoomEventFilter to filter returned events with. #[ruma_api(query)] #[serde( with = "ruma_serde::json_string", default, skip_serializing_if = "RoomEventFilter::is_empty" )] pub filter: RoomEventFilter<'a>, } #[derive(Default)] response: { /// The token the pagination starts from. pub start: String, /// The token the pagination ends at. #[serde(skip_serializing_if = "Option::is_none")] pub end: Option, /// A list of room events. #[serde(default)] pub chunk: Vec>, /// A list of state events relevant to showing the `chunk`. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub state: Vec>, } error: crate::Error } impl<'a> Request<'a> { /// Creates a new `Request` with the given parameters. /// /// All other parameters will be defaulted. pub fn new(room_id: &'a RoomId, from: &'a str, dir: Direction) -> Self { Self { room_id, from, to: None, dir, limit: default_limit(), filter: RoomEventFilter::default(), } } /// Creates a new `Request` with the given room ID and from token, and `dir` set to /// `Backward`. pub fn backward(room_id: &'a RoomId, from: &'a str) -> Self { Self::new(room_id, from, Direction::Backward) } /// Creates a new `Request` with the given room ID and from token, and `dir` set to /// `Forward`. pub fn forward(room_id: &'a RoomId, from: &'a str) -> Self { Self::new(room_id, from, Direction::Forward) } } impl Response { /// Creates an empty `Response`. pub fn new() -> Self { Default::default() } } fn default_limit() -> UInt { uint!(10) } #[allow(clippy::trivially_copy_pass_by_ref)] fn is_default_limit(val: &UInt) -> bool { *val == default_limit() } /// The direction to return events from. #[derive(Clone, Debug, Deserialize, Serialize)] #[allow(clippy::exhaustive_enums)] pub enum Direction { /// Return events backwards in time from the requested `from` token. #[serde(rename = "b")] Backward, /// Return events forwards in time from the requested `from` token. #[serde(rename = "f")] Forward, } #[cfg(all(test, feature = "client"))] mod tests { use js_int::uint; use ruma_common::api::{MatrixVersion, OutgoingRequest, SendAccessToken}; use ruma_identifiers::room_id; use super::{Direction, Request}; use crate::filter::{LazyLoadOptions, RoomEventFilter}; #[test] fn serialize_some_room_event_filter() { let room_id = room_id!("!roomid:example.org"); let rooms = &[room_id.to_owned()]; let filter = RoomEventFilter { lazy_load_options: LazyLoadOptions::Enabled { include_redundant_members: true }, rooms: Some(rooms), not_rooms: &[ room_id!("!room:example.org").to_owned(), room_id!("!room2:example.org").to_owned(), room_id!("!room3:example.org").to_owned(), ], not_types: &["type".into()], ..Default::default() }; let req = Request { room_id, from: "token", to: Some("token2"), dir: Direction::Backward, limit: uint!(0), filter, }; let request: http::Request> = req .try_into_http_request( "https://homeserver.tld", SendAccessToken::IfRequired("auth_tok"), &[MatrixVersion::V1_1], ) .unwrap(); assert_eq!( "from=token\ &to=token2\ &dir=b\ &limit=0\ &filter=%7B%22not_types%22%3A%5B%22type%22%5D%2C%22not_rooms%22%3A%5B%22%21room%3Aexample.org%22%2C%22%21room2%3Aexample.org%22%2C%22%21room3%3Aexample.org%22%5D%2C%22rooms%22%3A%5B%22%21roomid%3Aexample.org%22%5D%2C%22lazy_load_members%22%3Atrue%2C%22include_redundant_members%22%3Atrue%7D", request.uri().query().unwrap() ); } #[test] fn serialize_default_room_event_filter() { let room_id = room_id!("!roomid:example.org"); let req = Request { room_id, from: "token", to: Some("token2"), dir: Direction::Backward, limit: uint!(0), filter: RoomEventFilter::default(), }; let request = req .try_into_http_request::>( "https://homeserver.tld", SendAccessToken::IfRequired("auth_tok"), &[MatrixVersion::V1_1], ) .unwrap(); assert_eq!("from=token&to=token2&dir=b&limit=0", request.uri().query().unwrap(),); } } }