ruma_federation_api/authenticated_media/
get_content_thumbnail.rs

1//! `GET /_matrix/federation/*/media/thumbnail/{mediaId}`
2//!
3//! Get a thumbnail of content from the media repository.
4
5pub mod v1 {
6    //! `/v1/` ([spec])
7    //!
8    //! [spec]: https://spec.matrix.org/latest/server-server-api/#get_matrixfederationv1mediathumbnailmediaid
9
10    use std::time::Duration;
11
12    use js_int::UInt;
13    use ruma_common::{api::request, media::Method, metadata};
14
15    use crate::authenticated_media::{ContentMetadata, FileOrLocation};
16
17    metadata! {
18        method: GET,
19        rate_limited: true,
20        authentication: ServerSignatures,
21        history: {
22            unstable => "/_matrix/federation/unstable/org.matrix.msc3916.v2/media/thumbnail/{media_id}",
23            1.11 => "/_matrix/federation/v1/media/thumbnail/{media_id}",
24        }
25    }
26
27    /// Request type for the `get_content_thumbnail` endpoint.
28    #[request]
29    pub struct Request {
30        /// The media ID from the `mxc://` URI (the path component).
31        #[ruma_api(path)]
32        pub media_id: String,
33
34        /// The desired resizing method.
35        #[ruma_api(query)]
36        #[serde(skip_serializing_if = "Option::is_none")]
37        pub method: Option<Method>,
38
39        /// The *desired* width of the thumbnail.
40        ///
41        /// The actual thumbnail may not match the size specified.
42        #[ruma_api(query)]
43        pub width: UInt,
44
45        /// The *desired* height of the thumbnail.
46        ///
47        /// The actual thumbnail may not match the size specified.
48        #[ruma_api(query)]
49        pub height: UInt,
50
51        /// The maximum duration that the client is willing to wait to start receiving data, in the
52        /// case that the content has not yet been uploaded.
53        ///
54        /// The default value is 20 seconds.
55        #[ruma_api(query)]
56        #[serde(
57            with = "ruma_common::serde::duration::ms",
58            default = "ruma_common::media::default_download_timeout",
59            skip_serializing_if = "ruma_common::media::is_default_download_timeout"
60        )]
61        pub timeout_ms: Duration,
62
63        /// Whether the server should return an animated thumbnail.
64        ///
65        /// When `Some(true)`, the server should return an animated thumbnail if possible and
66        /// supported. When `Some(false)`, the server must not return an animated
67        /// thumbnail. When `None`, the server should not return an animated thumbnail.
68        #[ruma_api(query)]
69        #[serde(skip_serializing_if = "Option::is_none")]
70        pub animated: Option<bool>,
71    }
72
73    impl Request {
74        /// Creates a new `Request` with the given media ID, desired thumbnail width
75        /// and desired thumbnail height.
76        pub fn new(media_id: String, width: UInt, height: UInt) -> Self {
77            Self {
78                media_id,
79                method: None,
80                width,
81                height,
82                timeout_ms: ruma_common::media::default_download_timeout(),
83                animated: None,
84            }
85        }
86    }
87
88    /// Response type for the `get_content_thumbnail` endpoint.
89    #[derive(Debug, Clone)]
90    #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
91    pub struct Response {
92        /// The metadata of the thumbnail.
93        pub metadata: ContentMetadata,
94
95        /// The content of the thumbnail.
96        pub content: FileOrLocation,
97    }
98
99    impl Response {
100        /// Creates a new `Response` with the given metadata and content.
101        pub fn new(metadata: ContentMetadata, content: FileOrLocation) -> Self {
102            Self { metadata, content }
103        }
104    }
105
106    #[cfg(feature = "client")]
107    impl ruma_common::api::IncomingResponse for Response {
108        type EndpointError = ruma_common::api::error::MatrixError;
109
110        fn try_from_http_response<T: AsRef<[u8]>>(
111            http_response: http::Response<T>,
112        ) -> Result<Self, ruma_common::api::error::FromHttpResponseError<Self::EndpointError>>
113        {
114            use ruma_common::api::EndpointError;
115
116            if http_response.status().as_u16() < 400 {
117                let (metadata, content) =
118                    crate::authenticated_media::try_from_multipart_mixed_response(http_response)?;
119                Ok(Self { metadata, content })
120            } else {
121                Err(ruma_common::api::error::FromHttpResponseError::Server(
122                    ruma_common::api::error::MatrixError::from_http_response(http_response),
123                ))
124            }
125        }
126    }
127
128    #[cfg(feature = "server")]
129    impl ruma_common::api::OutgoingResponse for Response {
130        fn try_into_http_response<T: Default + bytes::BufMut>(
131            self,
132        ) -> Result<http::Response<T>, ruma_common::api::error::IntoHttpError> {
133            crate::authenticated_media::try_into_multipart_mixed_response(
134                &self.metadata,
135                &self.content,
136            )
137        }
138    }
139}