ruma_client_api/threads/get_thread_subscriptions_changes.rs
1//! `GET /_matrix/client/*/thread_subscriptions`
2//!
3//! Retrieve a paginated range of thread subscriptions across all rooms.
4
5pub mod unstable {
6 //! `/unstable/` ([spec])
7 //!
8 //! [spec]: https://github.com/matrix-org/matrix-spec-proposals/pull/4308
9
10 use std::collections::BTreeMap;
11
12 use js_int::UInt;
13 use ruma_common::{
14 api::{request, response, Direction, Metadata},
15 metadata, OwnedEventId, OwnedRoomId,
16 };
17 use serde::{Deserialize, Serialize};
18
19 const METADATA: Metadata = metadata! {
20 method: GET,
21 rate_limited: true,
22 authentication: AccessToken,
23 history: {
24 unstable("org.matrix.msc4308") => "/_matrix/client/unstable/io.element.msc4308/thread_subscriptions",
25 }
26 };
27
28 /// Request type for the `get_thread_subscriptions_changes` endpoint.
29 #[request(error = crate::Error)]
30 pub struct Request {
31 /// The direction to use for pagination.
32 ///
33 /// Always `b`ackwards at the time of implementation (2025-08-21).
34 #[ruma_api(query)]
35 dir: Direction,
36
37 /// A token to continue pagination from.
38 ///
39 /// This token can be acquired from a previous `/thread_subscriptions` response, or the
40 /// `prev_batch` in a sliding sync response's `thread_subscriptions` field.
41 ///
42 /// The token is opaque and has no client-discernible meaning.
43 ///
44 /// If not provided, then the pagination starts from the "end".
45 #[ruma_api(query)]
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub from: Option<String>,
48
49 /// A token used to limit the pagination.
50 ///
51 /// The token can be set to the value of a sliding sync `pos` field used in a request that
52 /// returned new thread subscriptions with a `prev_batch` token.
53 #[ruma_api(query)]
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub to: Option<String>,
56
57 /// A maximum number of thread subscriptions to fetch in one response.
58 ///
59 /// Defaults to 100, if not provided. Servers may impose a smaller limit than requested.
60 #[ruma_api(query)]
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub limit: Option<UInt>,
63 }
64
65 /// A thread has been subscribed to at some point.
66 #[derive(Clone, Debug, Serialize, Deserialize)]
67 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
68 pub struct ThreadSubscription {
69 /// Whether the subscription was made automatically by a client, not by manual user choice.
70 pub automatic: bool,
71
72 /// The bump stamp of the thread subscription, to be used to compare with other changes
73 /// related to the same thread.
74 pub bump_stamp: UInt,
75 }
76
77 impl ThreadSubscription {
78 /// Create a new [`ThreadSubscription`] with the given values.
79 pub fn new(automatic: bool, bump_stamp: UInt) -> Self {
80 Self { automatic, bump_stamp }
81 }
82 }
83
84 /// A thread has been unsubscribed to at some point.
85 #[derive(Clone, Debug, Serialize, Deserialize)]
86 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
87 pub struct ThreadUnsubscription {
88 /// The bump stamp of the thread subscription, to be used to compare with other changes
89 /// related to the same thread.
90 pub bump_stamp: UInt,
91 }
92
93 impl ThreadUnsubscription {
94 /// Create a new [`ThreadUnsubscription`] with the given bump stamp.
95 pub fn new(bump_stamp: UInt) -> Self {
96 Self { bump_stamp }
97 }
98 }
99
100 /// Response type for the `get_thread_subscriptions_changes` endpoint.
101 #[response(error = crate::Error)]
102 pub struct Response {
103 /// New thread subscriptions.
104 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
105 pub subscribed: BTreeMap<OwnedRoomId, BTreeMap<OwnedEventId, ThreadSubscription>>,
106
107 /// New thread unsubscriptions.
108 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
109 pub unsubscribed: BTreeMap<OwnedRoomId, BTreeMap<OwnedEventId, ThreadUnsubscription>>,
110
111 /// If there are still more results to fetch, this is the token to use as the next `from`
112 /// value.
113 #[serde(skip_serializing_if = "Option::is_none")]
114 pub end: Option<String>,
115 }
116
117 impl Request {
118 /// Creates a new empty `Request`.
119 pub fn new() -> Self {
120 Self { dir: Direction::Backward, from: None, to: None, limit: None }
121 }
122 }
123
124 impl Response {
125 /// Creates a new empty `Response`.
126 pub fn new() -> Self {
127 Self { subscribed: BTreeMap::new(), unsubscribed: BTreeMap::new(), end: None }
128 }
129 }
130}