add MSC3266 room summary API support

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-07-03 12:40:08 -04:00
parent 82acc7c0b0
commit b0eec60724
5 changed files with 174 additions and 21 deletions

32
Cargo.lock generated
View file

@ -2903,7 +2903,7 @@ dependencies = [
[[package]]
name = "ruma"
version = "0.10.1"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"assign",
"js_int",
@ -2924,7 +2924,7 @@ dependencies = [
[[package]]
name = "ruma-appservice-api"
version = "0.10.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"js_int",
"ruma-common",
@ -2936,7 +2936,7 @@ dependencies = [
[[package]]
name = "ruma-client-api"
version = "0.18.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"as_variant",
"assign",
@ -2959,7 +2959,7 @@ dependencies = [
[[package]]
name = "ruma-common"
version = "0.13.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"as_variant",
"base64 0.22.1",
@ -2972,7 +2972,7 @@ dependencies = [
"percent-encoding",
"rand",
"regex",
"ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0)",
"ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5)",
"ruma-macros",
"serde",
"serde_html_form",
@ -2989,7 +2989,7 @@ dependencies = [
[[package]]
name = "ruma-events"
version = "0.28.1"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"as_variant",
"indexmap 2.2.6",
@ -2999,7 +2999,7 @@ dependencies = [
"pulldown-cmark",
"regex",
"ruma-common",
"ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0)",
"ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5)",
"ruma-macros",
"serde",
"serde_json",
@ -3012,7 +3012,7 @@ dependencies = [
[[package]]
name = "ruma-federation-api"
version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"js_int",
"ruma-common",
@ -3024,7 +3024,7 @@ dependencies = [
[[package]]
name = "ruma-identifiers-validation"
version = "0.9.5"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"js_int",
"thiserror",
@ -3042,7 +3042,7 @@ dependencies = [
[[package]]
name = "ruma-identity-service-api"
version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"js_int",
"ruma-common",
@ -3052,13 +3052,13 @@ dependencies = [
[[package]]
name = "ruma-macros"
version = "0.13.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"once_cell",
"proc-macro-crate",
"proc-macro2",
"quote",
"ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0)",
"ruma-identifiers-validation 0.9.5 (git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5)",
"serde",
"syn 2.0.68",
"toml",
@ -3067,7 +3067,7 @@ dependencies = [
[[package]]
name = "ruma-push-gateway-api"
version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"js_int",
"ruma-common",
@ -3079,7 +3079,7 @@ dependencies = [
[[package]]
name = "ruma-server-util"
version = "0.3.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"headers",
"http 1.1.0",
@ -3092,7 +3092,7 @@ dependencies = [
[[package]]
name = "ruma-signatures"
version = "0.15.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"base64 0.22.1",
"ed25519-dalek",
@ -3108,7 +3108,7 @@ dependencies = [
[[package]]
name = "ruma-state-res"
version = "0.11.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c51ccb2c68d2e3557eb12b1a49036531711ec0e5#c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
dependencies = [
"itertools 0.12.1",
"js_int",

View file

@ -274,7 +274,7 @@ version = "0.1.2"
[workspace.dependencies.ruma]
git = "https://github.com/girlbossceo/ruwuma"
#branch = "conduwuit-changes"
rev = "9a5bfad8494b7a4e6c40421c3d0675db4b434ec0"
rev = "c51ccb2c68d2e3557eb12b1a49036531711ec0e5"
features = [
"compat",
"rand",
@ -294,6 +294,7 @@ features = [
"unstable-msc2870",
"unstable-msc3026",
"unstable-msc3061",
"unstable-msc3266",
"unstable-msc3575",
"unstable-msc4121",
"unstable-msc4125",

View file

@ -1,5 +1,8 @@
use axum_client_ip::InsecureClientIp;
use conduit::{warn, RumaResponse};
use ruma::{
api::client::{error::ErrorKind, membership::mutual_rooms},
api::client::{error::ErrorKind, membership::mutual_rooms, room::get_summary},
events::room::member::MembershipState,
OwnedRoomId,
};
@ -12,8 +15,9 @@ use crate::{services, Error, Result, Ruma};
/// TODO: Implement pagination, currently this just returns everything
///
/// An implementation of [MSC2666](https://github.com/matrix-org/matrix-spec-proposals/pull/2666)
#[tracing::instrument(skip_all, fields(%client), name = "mutual_rooms")]
pub(crate) async fn get_mutual_rooms_route(
body: Ruma<mutual_rooms::unstable::Request>,
InsecureClientIp(client): InsecureClientIp, body: Ruma<mutual_rooms::unstable::Request>,
) -> Result<mutual_rooms::unstable::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
@ -43,3 +47,116 @@ pub(crate) async fn get_mutual_rooms_route(
next_batch_token: None,
})
}
/// # `GET /_matrix/client/unstable/im.nheko.summary/rooms/{roomIdOrAlias}/summary`
///
/// Returns a short description of the state of a room.
///
/// This is the "wrong" endpoint that some implementations/clients may use
/// according to the MSC. Request and response bodies are the same as
/// `get_room_summary`.
///
/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266)
pub(crate) async fn get_room_summary_legacy(
InsecureClientIp(client): InsecureClientIp, body: Ruma<get_summary::msc3266::Request>,
) -> Result<RumaResponse<get_summary::msc3266::Response>> {
get_room_summary(InsecureClientIp(client), body)
.await
.map(RumaResponse)
}
/// # `GET /_matrix/client/unstable/im.nheko.summary/summary/{roomIdOrAlias}`
///
/// Returns a short description of the state of a room.
///
/// TODO: support fetching remote room info if we don't know the room
///
/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266)
#[tracing::instrument(skip_all, fields(%client), name = "room_summary")]
pub(crate) async fn get_room_summary(
InsecureClientIp(client): InsecureClientIp, body: Ruma<get_summary::msc3266::Request>,
) -> Result<get_summary::msc3266::Response> {
let sender_user = body.sender_user.as_ref();
let room_id = services()
.rooms
.alias
.resolve(&body.room_id_or_alias)
.await?;
if !services().rooms.metadata.exists(&room_id)? {
return Err(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server"));
}
if sender_user.is_none()
&& !services()
.rooms
.state_accessor
.is_world_readable(&room_id)
.unwrap_or(false)
{
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"Room is not world readable, authentication is required",
));
}
Ok(get_summary::msc3266::Response {
room_id: room_id.clone(),
canonical_alias: services()
.rooms
.state_accessor
.get_canonical_alias(&room_id)?,
avatar_url: services()
.rooms
.state_accessor
.get_avatar(&room_id)?
.into_option()
.unwrap_or_default()
.url,
guest_can_join: services().rooms.state_accessor.guest_can_join(&room_id)?,
name: services()
.rooms
.state_accessor
.get_name(&room_id)
.unwrap_or(None),
num_joined_members: services()
.rooms
.state_cache
.room_joined_count(&room_id)
.unwrap_or_default()
.unwrap_or_else(|| {
warn!("Room {room_id} has no member count");
0
})
.try_into()
.expect("user count should not be that big"),
topic: services()
.rooms
.state_accessor
.get_room_topic(&room_id)
.unwrap_or(None),
world_readable: services()
.rooms
.state_accessor
.is_world_readable(&room_id)
.unwrap_or(false),
join_rule: services().rooms.state_accessor.get_join_rule(&room_id)?.0,
room_type: services().rooms.state_accessor.get_room_type(&room_id)?,
room_version: Some(services().rooms.state.get_room_version(&room_id)?),
membership: if let Some(sender_user) = sender_user {
services()
.rooms
.state_accessor
.get_member(&room_id, sender_user)?
.map_or_else(|| Some(MembershipState::Leave), |content| Some(content.membership))
} else {
None
},
encryption: services()
.rooms
.state_accessor
.get_room_encryption(&room_id)
.unwrap_or_else(|_e| None),
})
}

View file

@ -172,7 +172,6 @@ pub fn build(router: Router, server: &Server) -> Router {
.ruma_route(client::get_key_changes_route)
.ruma_route(client::get_pushers_route)
.ruma_route(client::set_pushers_route)
// .ruma_route(client::third_party_route)
.ruma_route(client::upgrade_room_route)
.ruma_route(client::get_threads_route)
.ruma_route(client::get_relating_events_with_rel_type_and_event_type_route)
@ -180,6 +179,11 @@ pub fn build(router: Router, server: &Server) -> Router {
.ruma_route(client::get_relating_events_route)
.ruma_route(client::get_hierarchy_route)
.ruma_route(client::get_mutual_rooms_route)
.ruma_route(client::get_room_summary)
.route(
"/_matrix/client/unstable/im.nheko.summary/rooms/:room_id_or_alias/summary",
get(client::get_room_summary_legacy)
)
.ruma_route(client::well_known_support)
.ruma_route(client::well_known_client)
.route("/_conduwuit/server_version", get(client::conduwuit_server_version))

View file

@ -14,6 +14,8 @@ use ruma::{
room::{
avatar::RoomAvatarEventContent,
canonical_alias::RoomCanonicalAliasEventContent,
create::RoomCreateEventContent,
encryption::RoomEncryptionEventContent,
guest_access::{GuestAccess, RoomGuestAccessEventContent},
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
join_rules::{AllowRule, JoinRule, RoomJoinRulesEventContent, RoomMembership},
@ -24,8 +26,10 @@ use ruma::{
},
StateEventType,
},
room::RoomType,
space::SpaceRoomJoinRule,
EventId, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId,
EventEncryptionAlgorithm, EventId, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, ServerName,
UserId,
};
use serde_json::value::to_raw_value;
@ -451,4 +455,31 @@ impl Service {
}
room_ids
}
pub fn get_room_type(&self, room_id: &RoomId) -> Result<Option<RoomType>> {
Ok(self
.room_state_get(room_id, &StateEventType::RoomCreate, "")?
.map(|s| {
serde_json::from_str::<RoomCreateEventContent>(s.content.get()).map_err(|e| {
error!("Invalid room create event in database: {e}");
Error::BadDatabase("Invalid room create event in database.")
})
})
.transpose()?
.and_then(|e| e.room_type))
}
/// Gets the room's encryption algorithm if `m.room.encryption` state event
/// is found
pub fn get_room_encryption(&self, room_id: &RoomId) -> Result<Option<EventEncryptionAlgorithm>> {
self.room_state_get(room_id, &StateEventType::RoomEncryption, "")?
.map_or(Ok(None), |s| {
serde_json::from_str::<RoomEncryptionEventContent>(s.content.get())
.map(|content| Some(content.algorithm))
.map_err(|e| {
error!("Invalid room encryption event in database: {e}");
Error::BadDatabase("Invalid room encryption event in database.")
})
})
}
}