ruma_client_api/authenticated_media/get_content_thumbnail.rs
1//! `GET /_matrix/client/*/media/thumbnail/{serverName}/{mediaId}`
2//!
3//! Get a thumbnail of content from the media store.
4
5pub mod v1 {
6 //! `/v1/` ([spec])
7 //!
8 //! [spec]: https://spec.matrix.org/latest/client-server-api/#get_matrixclientv1mediathumbnailservernamemediaid
9
10 use std::time::Duration;
11
12 use http::header::{CONTENT_DISPOSITION, CONTENT_TYPE};
13 use js_int::UInt;
14 use ruma_common::{
15 IdParseError, MxcUri, OwnedServerName,
16 api::{auth_scheme::AccessToken, request, response},
17 http_headers::ContentDisposition,
18 media::Method,
19 metadata,
20 };
21
22 metadata! {
23 method: GET,
24 rate_limited: true,
25 authentication: AccessToken,
26 history: {
27 unstable("org.matrix.msc3916") => "/_matrix/client/unstable/org.matrix.msc3916/media/thumbnail/{server_name}/{media_id}",
28 1.11 | stable("org.matrix.msc3916.stable") => "/_matrix/client/v1/media/thumbnail/{server_name}/{media_id}",
29 }
30 }
31
32 /// Request type for the `get_content_thumbnail` endpoint.
33 #[request(error = crate::Error)]
34 pub struct Request {
35 /// The server name from the mxc:// URI (the authoritory component).
36 #[ruma_api(path)]
37 pub server_name: OwnedServerName,
38
39 /// The media ID from the mxc:// URI (the path component).
40 #[ruma_api(path)]
41 pub media_id: String,
42
43 /// The desired resizing method.
44 #[ruma_api(query)]
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub method: Option<Method>,
47
48 /// The *desired* width of the thumbnail.
49 ///
50 /// The actual thumbnail may not match the size specified.
51 #[ruma_api(query)]
52 pub width: UInt,
53
54 /// The *desired* height of the thumbnail.
55 ///
56 /// The actual thumbnail may not match the size specified.
57 #[ruma_api(query)]
58 pub height: UInt,
59
60 /// The maximum duration that the client is willing to wait to start receiving data, in the
61 /// case that the content has not yet been uploaded.
62 ///
63 /// The default value is 20 seconds.
64 #[ruma_api(query)]
65 #[serde(
66 with = "ruma_common::serde::duration::ms",
67 default = "ruma_common::media::default_download_timeout",
68 skip_serializing_if = "ruma_common::media::is_default_download_timeout"
69 )]
70 pub timeout_ms: Duration,
71
72 /// Whether the server should return an animated thumbnail.
73 ///
74 /// When `Some(true)`, the server should return an animated thumbnail if possible and
75 /// supported. When `Some(false)`, the server must not return an animated
76 /// thumbnail. When `None`, the server should not return an animated thumbnail.
77 #[ruma_api(query)]
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub animated: Option<bool>,
80 }
81
82 /// Response type for the `get_content_thumbnail` endpoint.
83 #[response(error = crate::Error)]
84 pub struct Response {
85 /// A thumbnail of the requested content.
86 #[ruma_api(raw_body)]
87 pub file: Vec<u8>,
88
89 /// The content type of the thumbnail.
90 #[ruma_api(header = CONTENT_TYPE)]
91 pub content_type: Option<String>,
92
93 /// The value of the `Content-Disposition` HTTP header, possibly containing the name of the
94 /// file that was previously uploaded.
95 ///
96 /// See [MDN] for the syntax.
97 ///
98 /// [MDN]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#Syntax
99 #[ruma_api(header = CONTENT_DISPOSITION)]
100 pub content_disposition: Option<ContentDisposition>,
101 }
102
103 impl Request {
104 /// Creates a new `Request` with the given media ID, server name, desired thumbnail width
105 /// and desired thumbnail height.
106 pub fn new(
107 media_id: String,
108 server_name: OwnedServerName,
109 width: UInt,
110 height: UInt,
111 ) -> Self {
112 Self {
113 media_id,
114 server_name,
115 method: None,
116 width,
117 height,
118 timeout_ms: ruma_common::media::default_download_timeout(),
119 animated: None,
120 }
121 }
122
123 /// Creates a new `Request` with the given URI, desired thumbnail width and
124 /// desired thumbnail height.
125 pub fn from_uri(uri: &MxcUri, width: UInt, height: UInt) -> Result<Self, IdParseError> {
126 let (server_name, media_id) = uri.parts()?;
127
128 Ok(Self::new(media_id.to_owned(), server_name.to_owned(), width, height))
129 }
130 }
131
132 impl Response {
133 /// Creates a new `Response` with the given thumbnail.
134 pub fn new(
135 file: Vec<u8>,
136 content_type: String,
137 content_disposition: ContentDisposition,
138 ) -> Self {
139 Self {
140 file,
141 content_type: Some(content_type),
142 content_disposition: Some(content_disposition),
143 }
144 }
145 }
146}