refactor: Ruma upstreaming, half-baked edition

Co-authored-by: Jade Ellis <jade@ellis.link>
This commit is contained in:
Ginger
2026-03-29 12:25:42 -04:00
parent 1cc9dbf2a4
commit 204bc1367e
141 changed files with 2715 additions and 2279 deletions
+5 -3
View File
@@ -6,7 +6,9 @@ use conduwuit::{
};
use database::{Database, Interfix, Map};
use futures::StreamExt;
use ruma::{Mxc, OwnedMxcUri, UserId, http_headers::ContentDisposition};
use ruma::{OwnedMxcUri, OwnedUserId, UserId, http_headers::ContentDisposition};
use crate::media::mxc::Mxc;
use super::{preview::UrlPreviewData, thumbnail::Dim};
@@ -41,7 +43,7 @@ impl Data {
content_type: Option<&str>,
) -> Result<Vec<u8>> {
let dim: &[u32] = &[dim.width, dim.height];
let key = (mxc, dim, content_disposition, content_type);
let key = (mxc, dim, content_disposition.map(ToString::to_string), content_type);
let key = database::serialize_key(key)?;
self.mediaid_file.insert(&key, []);
if let Some(user) = user {
@@ -146,7 +148,7 @@ impl Data {
self.mediaid_user
.stream()
.ignore_err()
.ready_filter_map(|(key, user): (&str, &UserId)| {
.ready_filter_map(|(key, user): (&str, OwnedUserId)| {
(user == user_id).then(|| key.into())
})
.collect()
+3 -2
View File
@@ -1,4 +1,5 @@
pub mod blurhash;
pub mod mxc;
mod data;
pub(super) mod migrations;
mod preview;
@@ -17,7 +18,7 @@ use conduwuit::{
},
warn,
};
use ruma::{Mxc, OwnedMxcUri, UserId, http_headers::ContentDisposition};
use ruma::{OwnedMxcUri, UserId, http_headers::ContentDisposition};
use tokio::{
fs,
io::{AsyncReadExt, AsyncWriteExt, BufReader},
@@ -25,7 +26,7 @@ use tokio::{
use self::data::{Data, Metadata};
pub use self::thumbnail::Dim;
use crate::{Dep, client, globals, moderation, sending};
use crate::{Dep, client, globals, media::mxc::Mxc, moderation, sending};
#[derive(Debug)]
pub struct FileMeta {
+54
View File
@@ -0,0 +1,54 @@
use std::fmt;
use ruma::{MxcUri, MxcUriError, OwnedMxcUri, ServerName};
use serde::{Serialize, Serializer};
/// A structured, valid MXC URI
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Mxc<'a> {
/// ServerName part of the MXC URI
pub server_name: &'a ServerName,
/// MediaId part of the MXC URI
pub media_id: &'a str,
}
impl fmt::Display for Mxc<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "mxc://{}/{}", self.server_name, self.media_id)
}
}
impl<'a> TryFrom<&'a MxcUri> for Mxc<'a> {
type Error = MxcUriError;
fn try_from(s: &'a MxcUri) -> Result<Self, Self::Error> {
let (server_name, media_id) = s.parts()?;
Ok(Self { server_name, media_id })
}
}
impl<'a> TryFrom<&'a str> for Mxc<'a> {
type Error = MxcUriError;
fn try_from(s: &'a str) -> Result<Self, Self::Error> {
let s: &MxcUri = s.into();
s.try_into()
}
}
impl<'a> TryFrom<&'a OwnedMxcUri> for Mxc<'a> {
type Error = MxcUriError;
fn try_from(s: &'a OwnedMxcUri) -> Result<Self, Self::Error> {
let s: &MxcUri = s.as_ref();
s.try_into()
}
}
impl Serialize for Mxc<'_> {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.to_string().as_str())
}
}
+2 -1
View File
@@ -130,7 +130,8 @@ pub async fn download_image(
) -> Result<UrlPreviewData> {
use conduwuit::utils::random_string;
use image::ImageReader;
use ruma::Mxc;
use crate::media::mxc::Mxc;
let mut preview_data = preview_data.unwrap_or_default();
+60 -62
View File
@@ -6,18 +6,16 @@ use conduwuit::{
};
use http::header::{CONTENT_DISPOSITION, CONTENT_TYPE, HeaderValue};
use ruma::{
Mxc, ServerName, UserId,
api::{
OutgoingRequest,
client::{
ServerName, UserId, api::{
Metadata, OutgoingRequest, auth_scheme::NoAuthentication, client::{
error::ErrorKind::{NotFound, Unrecognized},
media,
},
federation,
federation::authenticated_media::{Content, FileOrLocation},
},
}, federation::{self, authenticated_media::{Content, FileOrLocation}, authentication::ServerSignatures}, path_builder::PathBuilder
}
};
use crate::{federation::FederationPathBuilderInput, media::mxc::Mxc};
use super::{Dim, FileMeta};
#[implement(super::Service)]
@@ -87,14 +85,10 @@ async fn fetch_thumbnail_authenticated(
) -> Result<FileMeta> {
use federation::authenticated_media::get_content_thumbnail::v1::{Request, Response};
let request = Request {
media_id: mxc.media_id.into(),
method: dim.method.clone().into(),
width: dim.width.into(),
height: dim.height.into(),
animated: true.into(),
timeout_ms,
};
let mut request = Request::new(mxc.media_id.into(), dim.width.into(), dim.height.into());
request.method = Some(dim.method.clone());
request.animated = Some(true);
request.timeout_ms = timeout_ms;
let Response { content, .. } = self.federation_request(mxc, server, request).await?;
@@ -102,6 +96,7 @@ async fn fetch_thumbnail_authenticated(
| FileOrLocation::File(content) =>
self.handle_thumbnail_file(mxc, user, dim, content).await,
| FileOrLocation::Location(location) => self.handle_location(mxc, user, &location).await,
| _ => Err!("Unknown content in response"),
}
}
@@ -115,16 +110,15 @@ async fn fetch_content_authenticated(
) -> Result<FileMeta> {
use federation::authenticated_media::get_content::v1::{Request, Response};
let request = Request {
media_id: mxc.media_id.into(),
timeout_ms,
};
let mut request = Request::new(mxc.media_id.into());
request.timeout_ms = timeout_ms;
let Response { content, .. } = self.federation_request(mxc, server, request).await?;
match content {
| FileOrLocation::File(content) => self.handle_content_file(mxc, user, content).await,
| FileOrLocation::Location(location) => self.handle_location(mxc, user, &location).await,
| _ => Err!("Unknown content in response"),
}
}
@@ -140,23 +134,18 @@ async fn fetch_thumbnail_unauthenticated(
) -> Result<FileMeta> {
use media::get_content_thumbnail::v3::{Request, Response};
let request = Request {
allow_remote: true,
allow_redirect: true,
animated: true.into(),
method: dim.method.clone().into(),
width: dim.width.into(),
height: dim.height.into(),
server_name: mxc.server_name.into(),
media_id: mxc.media_id.into(),
timeout_ms,
};
let mut request = Request::new(mxc.media_id.into(), mxc.server_name.into(), dim.width.into(), dim.height.into());
request.allow_redirect = true;
request.allow_remote = true;
request.animated = Some(true);
request.method = Some(dim.method.clone());
request.timeout_ms = timeout_ms;
let Response {
file, content_type, content_disposition, ..
} = self.federation_request(mxc, server, request).await?;
} = self.federation_request_unauthenticated(mxc, server, request).await?;
let content = Content { file, content_type, content_disposition };
let content = Content::new(file, content_type.unwrap(), content_disposition.unwrap());
self.handle_thumbnail_file(mxc, user, dim, content).await
}
@@ -172,19 +161,16 @@ async fn fetch_content_unauthenticated(
) -> Result<FileMeta> {
use media::get_content::v3::{Request, Response};
let request = Request {
allow_remote: true,
allow_redirect: true,
server_name: mxc.server_name.into(),
media_id: mxc.media_id.into(),
timeout_ms,
};
let mut request = Request::new(mxc.media_id.into(), mxc.server_name.into());
request.allow_remote = true;
request.allow_redirect = true;
request.timeout_ms = timeout_ms;
let Response {
file, content_type, content_disposition, ..
} = self.federation_request(mxc, server, request).await?;
} = self.federation_request_unauthenticated(mxc, server, request).await?;
let content = Content { file, content_type, content_disposition };
let content = Content::new(file, content_type.unwrap(), content_disposition.unwrap());
self.handle_content_file(mxc, user, content).await
}
@@ -307,14 +293,14 @@ async fn location_request(&self, location: &str) -> Result<FileMeta> {
}
#[implement(super::Service)]
async fn federation_request<Request>(
async fn federation_request<'i, Request>(
&self,
mxc: &Mxc<'_>,
server: Option<&ServerName>,
request: Request,
) -> Result<Request::IncomingResponse>
where
Request: OutgoingRequest + Send + Debug,
Request: OutgoingRequest::<Authentication = ServerSignatures, PathBuilder: PathBuilder<Input<'i>: FederationPathBuilderInput>> + Debug + Send,
{
self.services
.sending
@@ -322,6 +308,22 @@ where
.await
}
#[implement(super::Service)]
async fn federation_request_unauthenticated<'i, Request>(
&self,
mxc: &Mxc<'_>,
server: Option<&ServerName>,
request: Request,
) -> Result<Request::IncomingResponse>
where
Request: OutgoingRequest::<Authentication = NoAuthentication, PathBuilder: PathBuilder<Input<'i>: FederationPathBuilderInput>> + Debug + Send,
{
self.services
.sending
.send_unauthenticated_request(server.unwrap_or(mxc.server_name), request)
.await
}
#[implement(super::Service)]
#[allow(deprecated)]
pub async fn fetch_remote_thumbnail_legacy(
@@ -333,22 +335,19 @@ pub async fn fetch_remote_thumbnail_legacy(
media_id: &body.media_id,
};
let mut request = media::get_content_thumbnail::v3::Request::new(body.media_id.clone(), body.server_name.clone(), body.width, body.height);
request.method = body.method.clone();
request.allow_remote = body.allow_remote;
request.allow_redirect = body.allow_redirect;
request.animated = body.animated;
request.timeout_ms = body.timeout_ms;
self.check_legacy_freeze()?;
self.check_fetch_authorized(&mxc)?;
let response = self
.services
.sending
.send_federation_request(mxc.server_name, media::get_content_thumbnail::v3::Request {
allow_remote: body.allow_remote,
height: body.height,
width: body.width,
method: body.method.clone(),
server_name: body.server_name.clone(),
media_id: body.media_id.clone(),
timeout_ms: body.timeout_ms,
allow_redirect: body.allow_redirect,
animated: body.animated,
})
.send_unauthenticated_request(mxc.server_name, request)
.await?;
let dim = Dim::from_ruma(body.width, body.height, body.method.clone())?;
@@ -373,18 +372,17 @@ pub async fn fetch_remote_content_legacy(
allow_redirect: bool,
timeout_ms: Duration,
) -> Result<media::get_content::v3::Response, Error> {
let mut request = media::get_content::v3::Request::new(mxc.media_id.into(), mxc.server_name.into());
request.allow_remote = true;
request.allow_redirect = allow_redirect;
request.timeout_ms = timeout_ms;
self.check_legacy_freeze()?;
self.check_fetch_authorized(mxc)?;
let response = self
.services
.sending
.send_federation_request(mxc.server_name, media::get_content::v3::Request {
allow_remote: true,
server_name: mxc.server_name.into(),
media_id: mxc.media_id.into(),
timeout_ms,
allow_redirect,
})
.send_unauthenticated_request(mxc.server_name, request)
.await?;
let content_disposition = make_content_disposition(
+3 -1
View File
@@ -8,12 +8,14 @@
use std::{cmp, num::Saturating as Sat};
use conduwuit::{Result, checked, err, implement};
use ruma::{Mxc, UInt, UserId, http_headers::ContentDisposition, media::Method};
use ruma::{UInt, UserId, http_headers::ContentDisposition, media::Method};
use tokio::{
fs,
io::{AsyncReadExt, AsyncWriteExt},
};
use crate::media::mxc::Mxc;
use super::{FileMeta, data::Metadata};
/// Dimension specification for a thumbnail.