mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
feat: Add support for MSC4466
This commit is contained in:
Generated
+11
-11
@@ -4151,7 +4151,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma"
|
name = "ruma"
|
||||||
version = "0.15.1"
|
version = "0.15.1"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -4170,7 +4170,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-appservice-api"
|
name = "ruma-appservice-api"
|
||||||
version = "0.15.0"
|
version = "0.15.0"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -4182,7 +4182,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-client-api"
|
name = "ruma-client-api"
|
||||||
version = "0.23.1"
|
version = "0.23.1"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"assign",
|
"assign",
|
||||||
@@ -4204,7 +4204,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-common"
|
name = "ruma-common"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
@@ -4237,7 +4237,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events"
|
name = "ruma-events"
|
||||||
version = "0.33.0"
|
version = "0.33.0"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@@ -4258,7 +4258,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-federation-api"
|
name = "ruma-federation-api"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"headers",
|
"headers",
|
||||||
@@ -4281,7 +4281,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers-validation"
|
name = "ruma-identifiers-validation"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
@@ -4290,7 +4290,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-macros"
|
name = "ruma-macros"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -4306,7 +4306,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-push-gateway-api"
|
name = "ruma-push-gateway-api"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -4318,7 +4318,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-signatures"
|
name = "ruma-signatures"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
@@ -4334,7 +4334,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-state-res"
|
name = "ruma-state-res"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
source = "git+https://github.com/ruma/ruma.git?rev=9c9dccc93f054bbd28f23f630223fffa6289ecbc#9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
source = "git+https://github.com/ruma/ruma.git?rev=3ecd80b92794d2d93f657a7b3db62d4be237526b#3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
|
|||||||
+2
-1
@@ -344,7 +344,7 @@ version = "1.1.1"
|
|||||||
[workspace.dependencies.ruma]
|
[workspace.dependencies.ruma]
|
||||||
# version = "0.14.1"
|
# version = "0.14.1"
|
||||||
git = "https://github.com/ruma/ruma.git"
|
git = "https://github.com/ruma/ruma.git"
|
||||||
rev = "9c9dccc93f054bbd28f23f630223fffa6289ecbc"
|
rev = "3ecd80b92794d2d93f657a7b3db62d4be237526b"
|
||||||
features = [
|
features = [
|
||||||
"appservice-api-c",
|
"appservice-api-c",
|
||||||
"client-api",
|
"client-api",
|
||||||
@@ -379,6 +379,7 @@ features = [
|
|||||||
"unstable-msc4293",
|
"unstable-msc4293",
|
||||||
"unstable-msc4406",
|
"unstable-msc4406",
|
||||||
"unstable-msc4439",
|
"unstable-msc4439",
|
||||||
|
"unstable-msc4466",
|
||||||
"unstable-extensible-events",
|
"unstable-extensible-events",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
+123
-47
@@ -8,12 +8,12 @@ use ruma::{
|
|||||||
UserId,
|
UserId,
|
||||||
api::{
|
api::{
|
||||||
client::profile::{
|
client::profile::{
|
||||||
delete_profile_field, get_profile, get_profile_field, set_profile_field,
|
PropagateTo, delete_profile_field, get_profile, get_profile_field, set_profile_field,
|
||||||
},
|
},
|
||||||
federation,
|
federation,
|
||||||
},
|
},
|
||||||
assign,
|
assign,
|
||||||
events::room::member::{MembershipState, RoomMemberEventContent},
|
events::room::member::MembershipState,
|
||||||
presence::PresenceState,
|
presence::PresenceState,
|
||||||
profile::{ProfileFieldName, ProfileFieldValue},
|
profile::{ProfileFieldName, ProfileFieldValue},
|
||||||
};
|
};
|
||||||
@@ -62,8 +62,13 @@ pub(crate) async fn set_profile_field_route(
|
|||||||
return Err!(Request(InvalidParam("You may not change a remote user's profile data.")));
|
return Err!(Request(InvalidParam("You may not change a remote user's profile data.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
set_profile_field(&services, &body.user_id, ProfileFieldChange::Set(body.value.clone()))
|
set_profile_field(
|
||||||
.await?;
|
&services,
|
||||||
|
&body.user_id,
|
||||||
|
ProfileFieldChange::Set(body.value.clone()),
|
||||||
|
body.propagate_to.clone(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(set_profile_field::v3::Response::new())
|
Ok(set_profile_field::v3::Response::new())
|
||||||
}
|
}
|
||||||
@@ -83,8 +88,13 @@ pub(crate) async fn delete_profile_field_route(
|
|||||||
return Err!(Request(InvalidParam("You may not change a remote user's profile data.")));
|
return Err!(Request(InvalidParam("You may not change a remote user's profile data.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
set_profile_field(&services, &body.user_id, ProfileFieldChange::Delete(body.field.clone()))
|
set_profile_field(
|
||||||
.await?;
|
&services,
|
||||||
|
&body.user_id,
|
||||||
|
ProfileFieldChange::Delete(body.field.clone()),
|
||||||
|
body.propagate_to.clone(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(delete_profile_field::v3::Response::new())
|
Ok(delete_profile_field::v3::Response::new())
|
||||||
}
|
}
|
||||||
@@ -119,7 +129,13 @@ async fn fetch_full_profile(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = set_profile_field(services, user_id, ProfileFieldChange::Set(value)).await;
|
let _ = set_profile_field(
|
||||||
|
services,
|
||||||
|
user_id,
|
||||||
|
ProfileFieldChange::Set(value),
|
||||||
|
PropagateTo::None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(BTreeMap::from_iter(response))
|
Some(BTreeMap::from_iter(response))
|
||||||
@@ -153,8 +169,13 @@ async fn fetch_profile_field(
|
|||||||
|
|
||||||
if let Some(value) = response.get(field.as_str()).map(ToOwned::to_owned) {
|
if let Some(value) = response.get(field.as_str()).map(ToOwned::to_owned) {
|
||||||
if let Ok(value) = ProfileFieldValue::new(field.as_str(), value) {
|
if let Ok(value) = ProfileFieldValue::new(field.as_str(), value) {
|
||||||
let _ = set_profile_field(services, user_id, ProfileFieldChange::Set(value.clone()))
|
let _ = set_profile_field(
|
||||||
.await;
|
services,
|
||||||
|
user_id,
|
||||||
|
ProfileFieldChange::Set(value.clone()),
|
||||||
|
PropagateTo::None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
Ok(Some(value))
|
Ok(Some(value))
|
||||||
} else {
|
} else {
|
||||||
@@ -163,7 +184,13 @@ async fn fetch_profile_field(
|
|||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let _ = set_profile_field(services, user_id, ProfileFieldChange::Delete(field)).await;
|
let _ = set_profile_field(
|
||||||
|
services,
|
||||||
|
user_id,
|
||||||
|
ProfileFieldChange::Delete(field),
|
||||||
|
PropagateTo::None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@@ -256,6 +283,7 @@ async fn set_profile_field(
|
|||||||
services: &Services,
|
services: &Services,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
change: ProfileFieldChange,
|
change: ProfileFieldChange,
|
||||||
|
propagate_to: PropagateTo,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
const MAX_KEY_LENGTH_BYTES: usize = 255;
|
const MAX_KEY_LENGTH_BYTES: usize = 255;
|
||||||
const MAX_PROFILE_LENGTH_BYTES: usize = 65536;
|
const MAX_PROFILE_LENGTH_BYTES: usize = 65536;
|
||||||
@@ -303,6 +331,91 @@ async fn set_profile_field(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the user is local and changed their displayname or avatar_url, update it
|
||||||
|
// in all their joined rooms. This is done before updating their profile data
|
||||||
|
// so we can check the old value of the field if `propagate_to` is `unchanged`.
|
||||||
|
if matches!(field_name, ProfileFieldName::AvatarUrl | ProfileFieldName::DisplayName)
|
||||||
|
&& matches!(propagate_to, PropagateTo::All | PropagateTo::Unchanged)
|
||||||
|
&& services.globals.user_is_local(user_id)
|
||||||
|
{
|
||||||
|
let current_displayname = services.users.displayname(user_id).await.ok();
|
||||||
|
let current_avatar_url = services.users.avatar_url(user_id).await.ok();
|
||||||
|
|
||||||
|
let mut all_joined_rooms = services.rooms.state_cache.rooms_joined(user_id);
|
||||||
|
|
||||||
|
while let Some(room_id) = all_joined_rooms.next().await {
|
||||||
|
// TODO: this clobbers any custom fields on the event content
|
||||||
|
let mut current_membership = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_member(&room_id, user_id)
|
||||||
|
.await
|
||||||
|
.expect("should be able to fetch membership event for joined room");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
current_membership.membership,
|
||||||
|
MembershipState::Join,
|
||||||
|
"user should be joined"
|
||||||
|
);
|
||||||
|
|
||||||
|
// If `propagate_to` is `unchanged`, and the current value of the field we're
|
||||||
|
// updating was changed from its global value in this room, skip it.
|
||||||
|
if matches!(propagate_to, PropagateTo::Unchanged) {
|
||||||
|
let field_changed_from_global = match field_name {
|
||||||
|
| ProfileFieldName::AvatarUrl =>
|
||||||
|
current_membership.avatar_url.as_ref() != current_avatar_url.as_ref(),
|
||||||
|
| ProfileFieldName::DisplayName =>
|
||||||
|
current_membership.displayname.as_ref() != current_displayname.as_ref(),
|
||||||
|
| _ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if field_changed_from_global {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let state_lock = services.rooms.state.mutex.lock(room_id.as_str()).await;
|
||||||
|
|
||||||
|
// Preserve keys in accordance with the key copying rules
|
||||||
|
current_membership.reason = None;
|
||||||
|
current_membership.join_authorized_via_users_server = None;
|
||||||
|
match &change {
|
||||||
|
| ProfileFieldChange::Set(ProfileFieldValue::AvatarUrl(avatar_url)) => {
|
||||||
|
current_membership.avatar_url = Some(avatar_url.clone());
|
||||||
|
},
|
||||||
|
| ProfileFieldChange::Set(ProfileFieldValue::DisplayName(displayname)) => {
|
||||||
|
current_membership.displayname = Some(displayname.clone());
|
||||||
|
},
|
||||||
|
| ProfileFieldChange::Delete(ProfileFieldName::AvatarUrl) => {
|
||||||
|
current_membership.avatar_url = None;
|
||||||
|
},
|
||||||
|
| ProfileFieldChange::Delete(ProfileFieldName::DisplayName) => {
|
||||||
|
current_membership.displayname = None;
|
||||||
|
},
|
||||||
|
| _ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.build_and_append_pdu(
|
||||||
|
PartialPdu::state(user_id.to_string(), ¤t_membership),
|
||||||
|
user_id,
|
||||||
|
Some(&room_id),
|
||||||
|
&state_lock,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
if services.config.allow_local_presence {
|
||||||
|
// Send a presence EDU to indicate the profile changed
|
||||||
|
let _ = services
|
||||||
|
.presence
|
||||||
|
.ping_presence(user_id, &PresenceState::Online)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match change {
|
match change {
|
||||||
| ProfileFieldChange::Set(ProfileFieldValue::DisplayName(displayname)) => {
|
| ProfileFieldChange::Set(ProfileFieldValue::DisplayName(displayname)) => {
|
||||||
services
|
services
|
||||||
@@ -326,42 +439,5 @@ async fn set_profile_field(
|
|||||||
.set_profile_key(user_id, other.field_name().as_str(), other.value()),
|
.set_profile_key(user_id, other.field_name().as_str(), other.value()),
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user is local and changed their displayname or avatar_url, update it
|
|
||||||
// in all their joined rooms
|
|
||||||
if matches!(field_name, ProfileFieldName::AvatarUrl | ProfileFieldName::DisplayName)
|
|
||||||
&& services.globals.user_is_local(user_id)
|
|
||||||
{
|
|
||||||
let displayname = services.users.displayname(user_id).await.ok();
|
|
||||||
let avatar_url = services.users.avatar_url(user_id).await.ok();
|
|
||||||
let membership_content = assign!(
|
|
||||||
RoomMemberEventContent::new(MembershipState::Join), { displayname, avatar_url }
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut all_joined_rooms = services.rooms.state_cache.rooms_joined(user_id);
|
|
||||||
|
|
||||||
while let Some(room_id) = all_joined_rooms.next().await {
|
|
||||||
let state_lock = services.rooms.state.mutex.lock(room_id.as_str()).await;
|
|
||||||
|
|
||||||
let _ = services
|
|
||||||
.rooms
|
|
||||||
.timeline
|
|
||||||
.build_and_append_pdu(
|
|
||||||
PartialPdu::state(user_id.to_string(), &membership_content),
|
|
||||||
user_id,
|
|
||||||
Some(&room_id),
|
|
||||||
&state_lock,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
||||||
if services.config.allow_local_presence {
|
|
||||||
// Send a presence EDU to indicate the profile changed
|
|
||||||
let _ = services
|
|
||||||
.presence
|
|
||||||
.ping_presence(user_id, &PresenceState::Online)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user