Fetch and thumbnail original media if fetching thumbnail fails

E.g. because the remote server's thumbnail endpoint is broken in
hilarious ways: https://github.com/element-hq/synapse/issues/17518
This commit is contained in:
Lambda 2024-08-04 20:35:25 +00:00
parent 82aacdc153
commit a06c8db996
2 changed files with 56 additions and 24 deletions

View file

@ -125,6 +125,9 @@ This will be the first release of Grapevine since it was forked from Conduit
10. **BREAKING:** Reorganize config into sections.
([!49](https://gitlab.computer.surgery/matrix/grapevine-fork/-/merge_requests/49))
* Details on how to migrate can be found in the merge request's description.
11. Try to generate thumbnails for remote media ourselves if the federation
thumbnail request fails.
([!58](https://gitlab.computer.surgery/matrix/grapevine-fork/-/merge_requests/58))
### Fixed

View file

@ -804,6 +804,13 @@ async fn get_content_thumbnail_route_ruma(
Error::BadRequest(ErrorKind::InvalidParam, "Height is invalid.")
})?;
let make_response = |file, content_type| {
authenticated_media_client::get_content_thumbnail::v1::Response {
file,
content_type,
}
};
if let Some(FileMeta {
content_type,
file,
@ -811,13 +818,10 @@ async fn get_content_thumbnail_route_ruma(
}) =
services().media.get_thumbnail(mxc.to_string(), width, height).await?
{
Ok(authenticated_media_client::get_content_thumbnail::v1::Response {
file,
content_type,
})
} else if &*body.server_name != services().globals.server_name()
&& allow_remote
{
return Ok(make_response(file, content_type));
}
if &*body.server_name != services().globals.server_name() && allow_remote {
let get_thumbnail_response = get_remote_thumbnail(
&body.server_name,
authenticated_media_fed::get_content_thumbnail::v1::Request {
@ -832,25 +836,50 @@ async fn get_content_thumbnail_route_ruma(
animated: Some(false),
},
)
.await?;
.await;
services()
match get_thumbnail_response {
Ok(resp) => {
services()
.media
.upload_thumbnail(
mxc.to_string(),
None,
resp.content.content_type.as_deref(),
width,
height,
&resp.content.file,
)
.await?;
return Ok(make_response(
resp.content.file,
resp.content.content_type,
));
}
Err(error) => warn!(
%error,
"Failed to fetch thumbnail via federation, trying to fetch \
original media and create thumbnail ourselves"
),
}
get_remote_content(&mxc).await?;
if let Some(FileMeta {
content_type,
file,
..
}) = services()
.media
.upload_thumbnail(
mxc.to_string(),
None,
get_thumbnail_response.content.content_type.as_deref(),
width,
height,
&get_thumbnail_response.content.file,
)
.await?;
.get_thumbnail(mxc.to_string(), width, height)
.await?
{
return Ok(make_response(file, content_type));
}
Ok(authenticated_media_client::get_content_thumbnail::v1::Response {
file: get_thumbnail_response.content.file,
content_type: get_thumbnail_response.content.content_type,
})
} else {
Err(Error::BadRequest(ErrorKind::NotYetUploaded, "Media not found."))
error!("Source media doesn't exist even after fetching it from remote");
}
Err(Error::BadRequest(ErrorKind::NotYetUploaded, "Media not found."))
}