mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
Toward abstracting Pdu into trait Event.
Co-authored-by: Jade Ellis <jade@ellis.link> Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
use serde::Deserialize;
|
||||
use serde_json::value::Value as JsonValue;
|
||||
|
||||
use super::Event;
|
||||
use crate::{Result, err};
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(super) fn as_value<E: Event>(event: &E) -> JsonValue {
|
||||
get(event).expect("Failed to represent Event content as JsonValue")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn get<T, E>(event: &E) -> Result<T>
|
||||
where
|
||||
T: for<'de> Deserialize<'de>,
|
||||
E: Event,
|
||||
{
|
||||
serde_json::from_str(event.content().get())
|
||||
.map_err(|e| err!(Request(BadJson("Failed to deserialize content into type: {e}"))))
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
use ruma::{
|
||||
events::{
|
||||
AnyMessageLikeEvent, AnyStateEvent, AnyStrippedStateEvent, AnySyncStateEvent,
|
||||
AnySyncTimelineEvent, AnyTimelineEvent, StateEvent, room::member::RoomMemberEventContent,
|
||||
space::child::HierarchySpaceChildEvent,
|
||||
},
|
||||
serde::Raw,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use super::{Event, redact};
|
||||
|
||||
pub struct Owned<E: Event>(pub(super) E);
|
||||
|
||||
pub struct Ref<'a, E: Event>(pub(super) &'a E);
|
||||
|
||||
impl<E: Event> From<Owned<E>> for Raw<AnySyncTimelineEvent> {
|
||||
fn from(event: Owned<E>) -> Self { Ref(&event.0).into() }
|
||||
}
|
||||
|
||||
impl<'a, E: Event> From<Ref<'a, E>> for Raw<AnySyncTimelineEvent> {
|
||||
fn from(event: Ref<'a, E>) -> Self {
|
||||
let event = event.0;
|
||||
let (redacts, content) = redact::copy(event);
|
||||
let mut json = json!({
|
||||
"content": content,
|
||||
"event_id": event.event_id(),
|
||||
"origin_server_ts": event.origin_server_ts(),
|
||||
"sender": event.sender(),
|
||||
"type": event.event_type(),
|
||||
});
|
||||
|
||||
if let Some(redacts) = redacts {
|
||||
json["redacts"] = json!(redacts);
|
||||
}
|
||||
if let Some(state_key) = event.state_key() {
|
||||
json["state_key"] = json!(state_key);
|
||||
}
|
||||
if let Some(unsigned) = event.unsigned() {
|
||||
json["unsigned"] = json!(unsigned);
|
||||
}
|
||||
|
||||
serde_json::from_value(json).expect("Failed to serialize Event value")
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event> From<Owned<E>> for Raw<AnyTimelineEvent> {
|
||||
fn from(event: Owned<E>) -> Self { Ref(&event.0).into() }
|
||||
}
|
||||
|
||||
impl<'a, E: Event> From<Ref<'a, E>> for Raw<AnyTimelineEvent> {
|
||||
fn from(event: Ref<'a, E>) -> Self {
|
||||
let event = event.0;
|
||||
let (redacts, content) = redact::copy(event);
|
||||
let mut json = json!({
|
||||
"content": content,
|
||||
"event_id": event.event_id(),
|
||||
"origin_server_ts": event.origin_server_ts(),
|
||||
"room_id": event.room_id(),
|
||||
"sender": event.sender(),
|
||||
"type": event.kind(),
|
||||
});
|
||||
|
||||
if let Some(redacts) = redacts {
|
||||
json["redacts"] = json!(redacts);
|
||||
}
|
||||
if let Some(state_key) = event.state_key() {
|
||||
json["state_key"] = json!(state_key);
|
||||
}
|
||||
if let Some(unsigned) = event.unsigned() {
|
||||
json["unsigned"] = json!(unsigned);
|
||||
}
|
||||
|
||||
serde_json::from_value(json).expect("Failed to serialize Event value")
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event> From<Owned<E>> for Raw<AnyMessageLikeEvent> {
|
||||
fn from(event: Owned<E>) -> Self { Ref(&event.0).into() }
|
||||
}
|
||||
|
||||
impl<'a, E: Event> From<Ref<'a, E>> for Raw<AnyMessageLikeEvent> {
|
||||
fn from(event: Ref<'a, E>) -> Self {
|
||||
let event = event.0;
|
||||
let (redacts, content) = redact::copy(event);
|
||||
let mut json = json!({
|
||||
"content": content,
|
||||
"event_id": event.event_id(),
|
||||
"origin_server_ts": event.origin_server_ts(),
|
||||
"room_id": event.room_id(),
|
||||
"sender": event.sender(),
|
||||
"type": event.kind(),
|
||||
});
|
||||
|
||||
if let Some(redacts) = &redacts {
|
||||
json["redacts"] = json!(redacts);
|
||||
}
|
||||
if let Some(state_key) = event.state_key() {
|
||||
json["state_key"] = json!(state_key);
|
||||
}
|
||||
if let Some(unsigned) = event.unsigned() {
|
||||
json["unsigned"] = json!(unsigned);
|
||||
}
|
||||
|
||||
serde_json::from_value(json).expect("Failed to serialize Event value")
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event> From<Owned<E>> for Raw<AnyStateEvent> {
|
||||
fn from(event: Owned<E>) -> Self { Ref(&event.0).into() }
|
||||
}
|
||||
|
||||
impl<'a, E: Event> From<Ref<'a, E>> for Raw<AnyStateEvent> {
|
||||
fn from(event: Ref<'a, E>) -> Self {
|
||||
let event = event.0;
|
||||
let mut json = json!({
|
||||
"content": event.content(),
|
||||
"event_id": event.event_id(),
|
||||
"origin_server_ts": event.origin_server_ts(),
|
||||
"room_id": event.room_id(),
|
||||
"sender": event.sender(),
|
||||
"state_key": event.state_key(),
|
||||
"type": event.kind(),
|
||||
});
|
||||
|
||||
if let Some(unsigned) = event.unsigned() {
|
||||
json["unsigned"] = json!(unsigned);
|
||||
}
|
||||
|
||||
serde_json::from_value(json).expect("Failed to serialize Event value")
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event> From<Owned<E>> for Raw<AnySyncStateEvent> {
|
||||
fn from(event: Owned<E>) -> Self { Ref(&event.0).into() }
|
||||
}
|
||||
|
||||
impl<'a, E: Event> From<Ref<'a, E>> for Raw<AnySyncStateEvent> {
|
||||
fn from(event: Ref<'a, E>) -> Self {
|
||||
let event = event.0;
|
||||
let mut json = json!({
|
||||
"content": event.content(),
|
||||
"event_id": event.event_id(),
|
||||
"origin_server_ts": event.origin_server_ts(),
|
||||
"sender": event.sender(),
|
||||
"state_key": event.state_key(),
|
||||
"type": event.kind(),
|
||||
});
|
||||
|
||||
if let Some(unsigned) = event.unsigned() {
|
||||
json["unsigned"] = json!(unsigned);
|
||||
}
|
||||
|
||||
serde_json::from_value(json).expect("Failed to serialize Event value")
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event> From<Owned<E>> for Raw<AnyStrippedStateEvent> {
|
||||
fn from(event: Owned<E>) -> Self { Ref(&event.0).into() }
|
||||
}
|
||||
|
||||
impl<'a, E: Event> From<Ref<'a, E>> for Raw<AnyStrippedStateEvent> {
|
||||
fn from(event: Ref<'a, E>) -> Self {
|
||||
let event = event.0;
|
||||
let json = json!({
|
||||
"content": event.content(),
|
||||
"sender": event.sender(),
|
||||
"state_key": event.state_key(),
|
||||
"type": event.kind(),
|
||||
});
|
||||
|
||||
serde_json::from_value(json).expect("Failed to serialize Event value")
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event> From<Owned<E>> for Raw<HierarchySpaceChildEvent> {
|
||||
fn from(event: Owned<E>) -> Self { Ref(&event.0).into() }
|
||||
}
|
||||
|
||||
impl<'a, E: Event> From<Ref<'a, E>> for Raw<HierarchySpaceChildEvent> {
|
||||
fn from(event: Ref<'a, E>) -> Self {
|
||||
let event = event.0;
|
||||
let json = json!({
|
||||
"content": event.content(),
|
||||
"origin_server_ts": event.origin_server_ts(),
|
||||
"sender": event.sender(),
|
||||
"state_key": event.state_key(),
|
||||
"type": event.kind(),
|
||||
});
|
||||
|
||||
serde_json::from_value(json).expect("Failed to serialize Event value")
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Event> From<Owned<E>> for Raw<StateEvent<RoomMemberEventContent>> {
|
||||
fn from(event: Owned<E>) -> Self { Ref(&event.0).into() }
|
||||
}
|
||||
|
||||
impl<'a, E: Event> From<Ref<'a, E>> for Raw<StateEvent<RoomMemberEventContent>> {
|
||||
fn from(event: Ref<'a, E>) -> Self {
|
||||
let event = event.0;
|
||||
let mut json = json!({
|
||||
"content": event.content(),
|
||||
"event_id": event.event_id(),
|
||||
"origin_server_ts": event.origin_server_ts(),
|
||||
"redacts": event.redacts(),
|
||||
"room_id": event.room_id(),
|
||||
"sender": event.sender(),
|
||||
"state_key": event.state_key(),
|
||||
"type": event.kind(),
|
||||
});
|
||||
|
||||
if let Some(unsigned) = event.unsigned() {
|
||||
json["unsigned"] = json!(unsigned);
|
||||
}
|
||||
|
||||
serde_json::from_value(json).expect("Failed to serialize Event value")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
use ruma::{
|
||||
OwnedEventId, RoomVersionId,
|
||||
events::{TimelineEventType, room::redaction::RoomRedactionEventContent},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::value::{RawValue as RawJsonValue, to_raw_value};
|
||||
|
||||
use super::Event;
|
||||
|
||||
/// Copies the `redacts` property of the event to the `content` dict and
|
||||
/// vice-versa.
|
||||
///
|
||||
/// This follows the specification's
|
||||
/// [recommendation](https://spec.matrix.org/v1.10/rooms/v11/#moving-the-redacts-property-of-mroomredaction-events-to-a-content-property):
|
||||
///
|
||||
/// > For backwards-compatibility with older clients, servers should add a
|
||||
/// > redacts property to the top level of m.room.redaction events in when
|
||||
/// > serving such events over the Client-Server API.
|
||||
///
|
||||
/// > For improved compatibility with newer clients, servers should add a
|
||||
/// > redacts property to the content of m.room.redaction events in older
|
||||
/// > room versions when serving such events over the Client-Server API.
|
||||
#[must_use]
|
||||
pub(super) fn copy<E: Event>(event: &E) -> (Option<OwnedEventId>, Box<RawJsonValue>) {
|
||||
if *event.event_type() != TimelineEventType::RoomRedaction {
|
||||
return (event.redacts().map(ToOwned::to_owned), event.content().to_owned());
|
||||
}
|
||||
|
||||
let Ok(mut content) = event.get_content::<RoomRedactionEventContent>() else {
|
||||
return (event.redacts().map(ToOwned::to_owned), event.content().to_owned());
|
||||
};
|
||||
|
||||
if let Some(redacts) = content.redacts {
|
||||
return (Some(redacts), event.content().to_owned());
|
||||
}
|
||||
|
||||
if let Some(redacts) = event.redacts().map(ToOwned::to_owned) {
|
||||
content.redacts = Some(redacts);
|
||||
return (
|
||||
event.redacts().map(ToOwned::to_owned),
|
||||
to_raw_value(&content).expect("Must be valid, we only added redacts field"),
|
||||
);
|
||||
}
|
||||
|
||||
(event.redacts().map(ToOwned::to_owned), event.content().to_owned())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub(super) fn is_redacted<E: Event>(event: &E) -> bool {
|
||||
let Some(unsigned) = event.unsigned() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Ok(unsigned) = ExtractRedactedBecause::deserialize(unsigned) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
unsigned.redacted_because.is_some()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub(super) fn redacts_id<E: Event>(
|
||||
event: &E,
|
||||
room_version: &RoomVersionId,
|
||||
) -> Option<OwnedEventId> {
|
||||
use RoomVersionId::*;
|
||||
|
||||
if *event.kind() != TimelineEventType::RoomRedaction {
|
||||
return None;
|
||||
}
|
||||
|
||||
match *room_version {
|
||||
| V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 =>
|
||||
event.redacts().map(ToOwned::to_owned),
|
||||
| _ =>
|
||||
event
|
||||
.get_content::<RoomRedactionEventContent>()
|
||||
.ok()?
|
||||
.redacts,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ExtractRedactedBecause {
|
||||
redacted_because: Option<serde::de::IgnoredAny>,
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
use ruma::events::{StateEventType, TimelineEventType};
|
||||
|
||||
use super::StateKey;
|
||||
|
||||
/// Convenience trait for adding event type plus state key to state maps.
|
||||
pub trait TypeExt {
|
||||
fn with_state_key(self, state_key: impl Into<StateKey>) -> (StateEventType, StateKey);
|
||||
}
|
||||
|
||||
impl TypeExt for StateEventType {
|
||||
fn with_state_key(self, state_key: impl Into<StateKey>) -> (StateEventType, StateKey) {
|
||||
(self, state_key.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeExt for &StateEventType {
|
||||
fn with_state_key(self, state_key: impl Into<StateKey>) -> (StateEventType, StateKey) {
|
||||
(self.clone(), state_key.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeExt for TimelineEventType {
|
||||
fn with_state_key(self, state_key: impl Into<StateKey>) -> (StateEventType, StateKey) {
|
||||
(self.into(), state_key.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeExt for &TimelineEventType {
|
||||
fn with_state_key(self, state_key: impl Into<StateKey>) -> (StateEventType, StateKey) {
|
||||
(self.clone().into(), state_key.into())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user