Update existing events for spec r0.5.0 and add m.fully_read and
m.room.message.feedback.
This commit is contained in:
parent
9f43f37f41
commit
ba2538dda9
@ -15,4 +15,29 @@ pub struct HangupEventContent {
|
|||||||
pub call_id: String,
|
pub call_id: String,
|
||||||
/// The version of the VoIP specification this messages adheres to.
|
/// The version of the VoIP specification this messages adheres to.
|
||||||
pub version: u64,
|
pub version: u64,
|
||||||
|
/// Optional error reason for the hangup.
|
||||||
|
pub reason: Option<Reason>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A reason for a hangup.
|
||||||
|
///
|
||||||
|
/// This should not be provided when the user naturally ends or rejects the call. When there was an
|
||||||
|
/// error in the call negotiation, this should be `ice_failed` for when ICE negotiation fails or
|
||||||
|
/// `invite_timeout` for when the other party did not answer in time.
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub enum Reason {
|
||||||
|
/// ICE negotiation failure.
|
||||||
|
#[serde(rename = "ice_failed")]
|
||||||
|
IceFailed,
|
||||||
|
|
||||||
|
/// Party did not answer in time.
|
||||||
|
#[serde(rename = "invite_timeout")]
|
||||||
|
InviteTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_enum! {
|
||||||
|
Reason {
|
||||||
|
IceFailed => "ice_failed",
|
||||||
|
InviteTimeout => "invite_timeout",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,25 @@ use crate::{
|
|||||||
answer::AnswerEvent, candidates::CandidatesEvent, hangup::HangupEvent, invite::InviteEvent,
|
answer::AnswerEvent, candidates::CandidatesEvent, hangup::HangupEvent, invite::InviteEvent,
|
||||||
},
|
},
|
||||||
direct::DirectEvent,
|
direct::DirectEvent,
|
||||||
|
fully_read::FullyReadEvent,
|
||||||
presence::PresenceEvent,
|
presence::PresenceEvent,
|
||||||
receipt::ReceiptEvent,
|
receipt::ReceiptEvent,
|
||||||
room::{
|
room::{
|
||||||
aliases::AliasesEvent, avatar::AvatarEvent, canonical_alias::CanonicalAliasEvent,
|
aliases::AliasesEvent,
|
||||||
create::CreateEvent, guest_access::GuestAccessEvent,
|
avatar::AvatarEvent,
|
||||||
history_visibility::HistoryVisibilityEvent, join_rules::JoinRulesEvent,
|
canonical_alias::CanonicalAliasEvent,
|
||||||
member::MemberEvent, message::MessageEvent, name::NameEvent,
|
create::CreateEvent,
|
||||||
pinned_events::PinnedEventsEvent, power_levels::PowerLevelsEvent,
|
guest_access::GuestAccessEvent,
|
||||||
redaction::RedactionEvent, third_party_invite::ThirdPartyInviteEvent, topic::TopicEvent,
|
history_visibility::HistoryVisibilityEvent,
|
||||||
|
join_rules::JoinRulesEvent,
|
||||||
|
member::MemberEvent,
|
||||||
|
message::{feedback::FeedbackEvent, MessageEvent},
|
||||||
|
name::NameEvent,
|
||||||
|
pinned_events::PinnedEventsEvent,
|
||||||
|
power_levels::PowerLevelsEvent,
|
||||||
|
redaction::RedactionEvent,
|
||||||
|
third_party_invite::ThirdPartyInviteEvent,
|
||||||
|
topic::TopicEvent,
|
||||||
},
|
},
|
||||||
tag::TagEvent,
|
tag::TagEvent,
|
||||||
typing::TypingEvent,
|
typing::TypingEvent,
|
||||||
@ -38,6 +48,8 @@ pub enum Event {
|
|||||||
CallInvite(InviteEvent),
|
CallInvite(InviteEvent),
|
||||||
/// m.direct
|
/// m.direct
|
||||||
Direct(DirectEvent),
|
Direct(DirectEvent),
|
||||||
|
/// m.fully_read
|
||||||
|
FullyRead(FullyReadEvent),
|
||||||
/// m.presence
|
/// m.presence
|
||||||
Presence(PresenceEvent),
|
Presence(PresenceEvent),
|
||||||
/// m.receipt
|
/// m.receipt
|
||||||
@ -60,6 +72,8 @@ pub enum Event {
|
|||||||
RoomMember(MemberEvent),
|
RoomMember(MemberEvent),
|
||||||
/// m.room.message
|
/// m.room.message
|
||||||
RoomMessage(MessageEvent),
|
RoomMessage(MessageEvent),
|
||||||
|
/// m.room.message.feedback
|
||||||
|
RoomMessageFeedback(FeedbackEvent),
|
||||||
/// m.room.name
|
/// m.room.name
|
||||||
RoomName(NameEvent),
|
RoomName(NameEvent),
|
||||||
/// m.room.pinned_events
|
/// m.room.pinned_events
|
||||||
@ -114,6 +128,8 @@ pub enum RoomEvent {
|
|||||||
RoomMember(MemberEvent),
|
RoomMember(MemberEvent),
|
||||||
/// m.room.message
|
/// m.room.message
|
||||||
RoomMessage(MessageEvent),
|
RoomMessage(MessageEvent),
|
||||||
|
/// m.room.message.feedback
|
||||||
|
RoomMessageFeedback(FeedbackEvent),
|
||||||
/// m.room.name
|
/// m.room.name
|
||||||
RoomName(NameEvent),
|
RoomName(NameEvent),
|
||||||
/// m.room.pinned_events
|
/// m.room.pinned_events
|
||||||
@ -177,6 +193,7 @@ impl Serialize for Event {
|
|||||||
Event::CallHangup(ref event) => event.serialize(serializer),
|
Event::CallHangup(ref event) => event.serialize(serializer),
|
||||||
Event::CallInvite(ref event) => event.serialize(serializer),
|
Event::CallInvite(ref event) => event.serialize(serializer),
|
||||||
Event::Direct(ref event) => event.serialize(serializer),
|
Event::Direct(ref event) => event.serialize(serializer),
|
||||||
|
Event::FullyRead(ref event) => event.serialize(serializer),
|
||||||
Event::Presence(ref event) => event.serialize(serializer),
|
Event::Presence(ref event) => event.serialize(serializer),
|
||||||
Event::Receipt(ref event) => event.serialize(serializer),
|
Event::Receipt(ref event) => event.serialize(serializer),
|
||||||
Event::RoomAliases(ref event) => event.serialize(serializer),
|
Event::RoomAliases(ref event) => event.serialize(serializer),
|
||||||
@ -188,6 +205,7 @@ impl Serialize for Event {
|
|||||||
Event::RoomJoinRules(ref event) => event.serialize(serializer),
|
Event::RoomJoinRules(ref event) => event.serialize(serializer),
|
||||||
Event::RoomMember(ref event) => event.serialize(serializer),
|
Event::RoomMember(ref event) => event.serialize(serializer),
|
||||||
Event::RoomMessage(ref event) => event.serialize(serializer),
|
Event::RoomMessage(ref event) => event.serialize(serializer),
|
||||||
|
Event::RoomMessageFeedback(ref event) => event.serialize(serializer),
|
||||||
Event::RoomName(ref event) => event.serialize(serializer),
|
Event::RoomName(ref event) => event.serialize(serializer),
|
||||||
Event::RoomPinnedEvents(ref event) => event.serialize(serializer),
|
Event::RoomPinnedEvents(ref event) => event.serialize(serializer),
|
||||||
Event::RoomPowerLevels(ref event) => event.serialize(serializer),
|
Event::RoomPowerLevels(ref event) => event.serialize(serializer),
|
||||||
@ -261,6 +279,14 @@ impl<'de> Deserialize<'de> for Event {
|
|||||||
|
|
||||||
Ok(Event::Direct(event))
|
Ok(Event::Direct(event))
|
||||||
}
|
}
|
||||||
|
EventType::FullyRead => {
|
||||||
|
let event = match from_value::<FullyReadEvent>(value) {
|
||||||
|
Ok(event) => event,
|
||||||
|
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Event::FullyRead(event))
|
||||||
|
}
|
||||||
EventType::Presence => {
|
EventType::Presence => {
|
||||||
let event = match from_value::<PresenceEvent>(value) {
|
let event = match from_value::<PresenceEvent>(value) {
|
||||||
Ok(event) => event,
|
Ok(event) => event,
|
||||||
@ -349,6 +375,14 @@ impl<'de> Deserialize<'de> for Event {
|
|||||||
|
|
||||||
Ok(Event::RoomMessage(event))
|
Ok(Event::RoomMessage(event))
|
||||||
}
|
}
|
||||||
|
EventType::RoomMessageFeedback => {
|
||||||
|
let event = match from_value::<FeedbackEvent>(value) {
|
||||||
|
Ok(event) => event,
|
||||||
|
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Event::RoomMessageFeedback(event))
|
||||||
|
}
|
||||||
EventType::RoomName => {
|
EventType::RoomName => {
|
||||||
let event = match from_value::<NameEvent>(value) {
|
let event = match from_value::<NameEvent>(value) {
|
||||||
Ok(event) => event,
|
Ok(event) => event,
|
||||||
@ -463,6 +497,7 @@ impl Serialize for RoomEvent {
|
|||||||
RoomEvent::RoomJoinRules(ref event) => event.serialize(serializer),
|
RoomEvent::RoomJoinRules(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::RoomMember(ref event) => event.serialize(serializer),
|
RoomEvent::RoomMember(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::RoomMessage(ref event) => event.serialize(serializer),
|
RoomEvent::RoomMessage(ref event) => event.serialize(serializer),
|
||||||
|
RoomEvent::RoomMessageFeedback(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::RoomName(ref event) => event.serialize(serializer),
|
RoomEvent::RoomName(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::RoomPinnedEvents(ref event) => event.serialize(serializer),
|
RoomEvent::RoomPinnedEvents(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::RoomPowerLevels(ref event) => event.serialize(serializer),
|
RoomEvent::RoomPowerLevels(ref event) => event.serialize(serializer),
|
||||||
@ -597,6 +632,14 @@ impl<'de> Deserialize<'de> for RoomEvent {
|
|||||||
|
|
||||||
Ok(RoomEvent::RoomMessage(event))
|
Ok(RoomEvent::RoomMessage(event))
|
||||||
}
|
}
|
||||||
|
EventType::RoomMessageFeedback => {
|
||||||
|
let event = match from_value::<FeedbackEvent>(value) {
|
||||||
|
Ok(event) => event,
|
||||||
|
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(RoomEvent::RoomMessageFeedback(event))
|
||||||
|
}
|
||||||
EventType::RoomName => {
|
EventType::RoomName => {
|
||||||
let event = match from_value::<NameEvent>(value) {
|
let event = match from_value::<NameEvent>(value) {
|
||||||
Ok(event) => event,
|
Ok(event) => event,
|
||||||
@ -663,6 +706,7 @@ impl<'de> Deserialize<'de> for RoomEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
EventType::Direct
|
EventType::Direct
|
||||||
|
| EventType::FullyRead
|
||||||
| EventType::Presence
|
| EventType::Presence
|
||||||
| EventType::Receipt
|
| EventType::Receipt
|
||||||
| EventType::Tag
|
| EventType::Tag
|
||||||
@ -830,9 +874,11 @@ impl<'de> Deserialize<'de> for StateEvent {
|
|||||||
| EventType::CallHangup
|
| EventType::CallHangup
|
||||||
| EventType::CallInvite
|
| EventType::CallInvite
|
||||||
| EventType::Direct
|
| EventType::Direct
|
||||||
|
| EventType::FullyRead
|
||||||
| EventType::Presence
|
| EventType::Presence
|
||||||
| EventType::Receipt
|
| EventType::Receipt
|
||||||
| EventType::RoomMessage
|
| EventType::RoomMessage
|
||||||
|
| EventType::RoomMessageFeedback
|
||||||
| EventType::RoomRedaction
|
| EventType::RoomRedaction
|
||||||
| EventType::Tag
|
| EventType::Tag
|
||||||
| EventType::Typing => Err(D::Error::custom("not a state event".to_string())),
|
| EventType::Typing => Err(D::Error::custom("not a state event".to_string())),
|
||||||
@ -855,6 +901,7 @@ impl_from_t_for_event!(CandidatesEvent, CallCandidates);
|
|||||||
impl_from_t_for_event!(HangupEvent, CallHangup);
|
impl_from_t_for_event!(HangupEvent, CallHangup);
|
||||||
impl_from_t_for_event!(InviteEvent, CallInvite);
|
impl_from_t_for_event!(InviteEvent, CallInvite);
|
||||||
impl_from_t_for_event!(DirectEvent, Direct);
|
impl_from_t_for_event!(DirectEvent, Direct);
|
||||||
|
impl_from_t_for_event!(FullyReadEvent, FullyRead);
|
||||||
impl_from_t_for_event!(PresenceEvent, Presence);
|
impl_from_t_for_event!(PresenceEvent, Presence);
|
||||||
impl_from_t_for_event!(ReceiptEvent, Receipt);
|
impl_from_t_for_event!(ReceiptEvent, Receipt);
|
||||||
impl_from_t_for_event!(AliasesEvent, RoomAliases);
|
impl_from_t_for_event!(AliasesEvent, RoomAliases);
|
||||||
@ -866,6 +913,7 @@ impl_from_t_for_event!(HistoryVisibilityEvent, RoomHistoryVisibility);
|
|||||||
impl_from_t_for_event!(JoinRulesEvent, RoomJoinRules);
|
impl_from_t_for_event!(JoinRulesEvent, RoomJoinRules);
|
||||||
impl_from_t_for_event!(MemberEvent, RoomMember);
|
impl_from_t_for_event!(MemberEvent, RoomMember);
|
||||||
impl_from_t_for_event!(MessageEvent, RoomMessage);
|
impl_from_t_for_event!(MessageEvent, RoomMessage);
|
||||||
|
impl_from_t_for_event!(FeedbackEvent, RoomMessageFeedback);
|
||||||
impl_from_t_for_event!(NameEvent, RoomName);
|
impl_from_t_for_event!(NameEvent, RoomName);
|
||||||
impl_from_t_for_event!(PinnedEventsEvent, RoomPinnedEvents);
|
impl_from_t_for_event!(PinnedEventsEvent, RoomPinnedEvents);
|
||||||
impl_from_t_for_event!(PowerLevelsEvent, RoomPowerLevels);
|
impl_from_t_for_event!(PowerLevelsEvent, RoomPowerLevels);
|
||||||
@ -901,6 +949,7 @@ impl_from_t_for_room_event!(HistoryVisibilityEvent, RoomHistoryVisibility);
|
|||||||
impl_from_t_for_room_event!(JoinRulesEvent, RoomJoinRules);
|
impl_from_t_for_room_event!(JoinRulesEvent, RoomJoinRules);
|
||||||
impl_from_t_for_room_event!(MemberEvent, RoomMember);
|
impl_from_t_for_room_event!(MemberEvent, RoomMember);
|
||||||
impl_from_t_for_room_event!(MessageEvent, RoomMessage);
|
impl_from_t_for_room_event!(MessageEvent, RoomMessage);
|
||||||
|
impl_from_t_for_room_event!(FeedbackEvent, RoomMessageFeedback);
|
||||||
impl_from_t_for_room_event!(NameEvent, RoomName);
|
impl_from_t_for_room_event!(NameEvent, RoomName);
|
||||||
impl_from_t_for_room_event!(PinnedEventsEvent, RoomPinnedEvents);
|
impl_from_t_for_room_event!(PinnedEventsEvent, RoomPinnedEvents);
|
||||||
impl_from_t_for_room_event!(PowerLevelsEvent, RoomPowerLevels);
|
impl_from_t_for_room_event!(PowerLevelsEvent, RoomPowerLevels);
|
||||||
|
@ -10,9 +10,13 @@ use crate::{
|
|||||||
answer::AnswerEvent, candidates::CandidatesEvent, hangup::HangupEvent, invite::InviteEvent,
|
answer::AnswerEvent, candidates::CandidatesEvent, hangup::HangupEvent, invite::InviteEvent,
|
||||||
},
|
},
|
||||||
direct::DirectEvent,
|
direct::DirectEvent,
|
||||||
|
fully_read::FullyReadEvent,
|
||||||
presence::PresenceEvent,
|
presence::PresenceEvent,
|
||||||
receipt::ReceiptEvent,
|
receipt::ReceiptEvent,
|
||||||
room::{message::MessageEvent, redaction::RedactionEvent},
|
room::{
|
||||||
|
message::{feedback::FeedbackEvent, MessageEvent},
|
||||||
|
redaction::RedactionEvent,
|
||||||
|
},
|
||||||
tag::TagEvent,
|
tag::TagEvent,
|
||||||
typing::TypingEvent,
|
typing::TypingEvent,
|
||||||
CustomEvent, CustomRoomEvent, EventType,
|
CustomEvent, CustomRoomEvent, EventType,
|
||||||
@ -23,6 +27,8 @@ use crate::{
|
|||||||
pub enum Event {
|
pub enum Event {
|
||||||
/// m.direct
|
/// m.direct
|
||||||
Direct(DirectEvent),
|
Direct(DirectEvent),
|
||||||
|
/// m.fully_read
|
||||||
|
FullyRead(FullyReadEvent),
|
||||||
/// m.presence
|
/// m.presence
|
||||||
Presence(PresenceEvent),
|
Presence(PresenceEvent),
|
||||||
/// m.receipt
|
/// m.receipt
|
||||||
@ -49,6 +55,8 @@ pub enum RoomEvent {
|
|||||||
CallInvite(InviteEvent),
|
CallInvite(InviteEvent),
|
||||||
/// m.room.message
|
/// m.room.message
|
||||||
RoomMessage(MessageEvent),
|
RoomMessage(MessageEvent),
|
||||||
|
/// m.room.message.feedback
|
||||||
|
RoomMessageFeedback(FeedbackEvent),
|
||||||
/// m.room.redaction
|
/// m.room.redaction
|
||||||
RoomRedaction(RedactionEvent),
|
RoomRedaction(RedactionEvent),
|
||||||
/// Any room event that is not part of the specification.
|
/// Any room event that is not part of the specification.
|
||||||
@ -62,6 +70,7 @@ impl Serialize for Event {
|
|||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
Event::Direct(ref event) => event.serialize(serializer),
|
Event::Direct(ref event) => event.serialize(serializer),
|
||||||
|
Event::FullyRead(ref event) => event.serialize(serializer),
|
||||||
Event::Presence(ref event) => event.serialize(serializer),
|
Event::Presence(ref event) => event.serialize(serializer),
|
||||||
Event::Receipt(ref event) => event.serialize(serializer),
|
Event::Receipt(ref event) => event.serialize(serializer),
|
||||||
Event::Tag(ref event) => event.serialize(serializer),
|
Event::Tag(ref event) => event.serialize(serializer),
|
||||||
@ -97,6 +106,14 @@ impl<'de> Deserialize<'de> for Event {
|
|||||||
|
|
||||||
Ok(Event::Direct(event))
|
Ok(Event::Direct(event))
|
||||||
}
|
}
|
||||||
|
EventType::FullyRead => {
|
||||||
|
let event = match from_value::<FullyReadEvent>(value) {
|
||||||
|
Ok(event) => event,
|
||||||
|
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Event::FullyRead(event))
|
||||||
|
}
|
||||||
EventType::Presence => {
|
EventType::Presence => {
|
||||||
let event = match from_value::<PresenceEvent>(value) {
|
let event = match from_value::<PresenceEvent>(value) {
|
||||||
Ok(event) => event,
|
Ok(event) => event,
|
||||||
@ -150,6 +167,7 @@ impl<'de> Deserialize<'de> for Event {
|
|||||||
| EventType::RoomJoinRules
|
| EventType::RoomJoinRules
|
||||||
| EventType::RoomMember
|
| EventType::RoomMember
|
||||||
| EventType::RoomMessage
|
| EventType::RoomMessage
|
||||||
|
| EventType::RoomMessageFeedback
|
||||||
| EventType::RoomName
|
| EventType::RoomName
|
||||||
| EventType::RoomPinnedEvents
|
| EventType::RoomPinnedEvents
|
||||||
| EventType::RoomPowerLevels
|
| EventType::RoomPowerLevels
|
||||||
@ -173,6 +191,7 @@ impl Serialize for RoomEvent {
|
|||||||
RoomEvent::CallHangup(ref event) => event.serialize(serializer),
|
RoomEvent::CallHangup(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::CallInvite(ref event) => event.serialize(serializer),
|
RoomEvent::CallInvite(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::RoomMessage(ref event) => event.serialize(serializer),
|
RoomEvent::RoomMessage(ref event) => event.serialize(serializer),
|
||||||
|
RoomEvent::RoomMessageFeedback(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::RoomRedaction(ref event) => event.serialize(serializer),
|
RoomEvent::RoomRedaction(ref event) => event.serialize(serializer),
|
||||||
RoomEvent::CustomRoom(ref event) => event.serialize(serializer),
|
RoomEvent::CustomRoom(ref event) => event.serialize(serializer),
|
||||||
}
|
}
|
||||||
@ -237,6 +256,14 @@ impl<'de> Deserialize<'de> for RoomEvent {
|
|||||||
|
|
||||||
Ok(RoomEvent::RoomMessage(event))
|
Ok(RoomEvent::RoomMessage(event))
|
||||||
}
|
}
|
||||||
|
EventType::RoomMessageFeedback => {
|
||||||
|
let event = match from_value::<FeedbackEvent>(value) {
|
||||||
|
Ok(event) => event,
|
||||||
|
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(RoomEvent::RoomMessageFeedback(event))
|
||||||
|
}
|
||||||
EventType::RoomRedaction => {
|
EventType::RoomRedaction => {
|
||||||
let event = match from_value::<RedactionEvent>(value) {
|
let event = match from_value::<RedactionEvent>(value) {
|
||||||
Ok(event) => event,
|
Ok(event) => event,
|
||||||
@ -254,6 +281,7 @@ impl<'de> Deserialize<'de> for RoomEvent {
|
|||||||
Ok(RoomEvent::CustomRoom(event))
|
Ok(RoomEvent::CustomRoom(event))
|
||||||
}
|
}
|
||||||
EventType::Direct
|
EventType::Direct
|
||||||
|
| EventType::FullyRead
|
||||||
| EventType::Presence
|
| EventType::Presence
|
||||||
| EventType::Receipt
|
| EventType::Receipt
|
||||||
| EventType::RoomAliases
|
| EventType::RoomAliases
|
||||||
@ -287,6 +315,7 @@ macro_rules! impl_from_t_for_event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl_from_t_for_event!(DirectEvent, Direct);
|
impl_from_t_for_event!(DirectEvent, Direct);
|
||||||
|
impl_from_t_for_event!(FullyReadEvent, FullyRead);
|
||||||
impl_from_t_for_event!(PresenceEvent, Presence);
|
impl_from_t_for_event!(PresenceEvent, Presence);
|
||||||
impl_from_t_for_event!(ReceiptEvent, Receipt);
|
impl_from_t_for_event!(ReceiptEvent, Receipt);
|
||||||
impl_from_t_for_event!(TagEvent, Tag);
|
impl_from_t_for_event!(TagEvent, Tag);
|
||||||
@ -308,5 +337,6 @@ impl_from_t_for_room_event!(CandidatesEvent, CallCandidates);
|
|||||||
impl_from_t_for_room_event!(HangupEvent, CallHangup);
|
impl_from_t_for_room_event!(HangupEvent, CallHangup);
|
||||||
impl_from_t_for_room_event!(InviteEvent, CallInvite);
|
impl_from_t_for_room_event!(InviteEvent, CallInvite);
|
||||||
impl_from_t_for_room_event!(MessageEvent, RoomMessage);
|
impl_from_t_for_room_event!(MessageEvent, RoomMessage);
|
||||||
|
impl_from_t_for_room_event!(FeedbackEvent, RoomMessageFeedback);
|
||||||
impl_from_t_for_room_event!(RedactionEvent, RoomRedaction);
|
impl_from_t_for_room_event!(RedactionEvent, RoomRedaction);
|
||||||
impl_from_t_for_room_event!(CustomRoomEvent, CustomRoom);
|
impl_from_t_for_room_event!(CustomRoomEvent, CustomRoom);
|
||||||
|
@ -85,7 +85,7 @@ mod tests {
|
|||||||
assert!(direct_rooms.contains(&rooms[0]));
|
assert!(direct_rooms.contains(&rooms[0]));
|
||||||
assert!(direct_rooms.contains(&rooms[1]));
|
assert!(direct_rooms.contains(&rooms[1]));
|
||||||
}
|
}
|
||||||
_ => assert!(false),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match from_str::<collections::only::Event>(&json_data).unwrap() {
|
match from_str::<collections::only::Event>(&json_data).unwrap() {
|
||||||
@ -96,7 +96,7 @@ mod tests {
|
|||||||
assert!(direct_rooms.contains(&rooms[0]));
|
assert!(direct_rooms.contains(&rooms[0]));
|
||||||
assert!(direct_rooms.contains(&rooms[1]));
|
assert!(direct_rooms.contains(&rooms[1]));
|
||||||
}
|
}
|
||||||
_ => assert!(false),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
src/fully_read.rs
Normal file
22
src/fully_read.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//! Types for the *m.fully_read* event.
|
||||||
|
|
||||||
|
use ruma_identifiers::{EventId, RoomId};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
event! {
|
||||||
|
/// The current location of the user's read marker in a room.
|
||||||
|
///
|
||||||
|
/// This event appears in the user's room account data for the room the marker is applicable
|
||||||
|
/// for.
|
||||||
|
pub struct FullyReadEvent(FullyReadEventContent) {
|
||||||
|
/// The unique identifier for the room associated with this event.
|
||||||
|
pub room_id: RoomId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The payload of a `FullyReadEvent`.
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub struct FullyReadEventContent {
|
||||||
|
/// The event the user's read marker is located at in the room.
|
||||||
|
pub event_id: EventId,
|
||||||
|
}
|
@ -118,6 +118,7 @@ pub mod collections {
|
|||||||
pub mod only;
|
pub mod only;
|
||||||
}
|
}
|
||||||
pub mod direct;
|
pub mod direct;
|
||||||
|
pub mod fully_read;
|
||||||
pub mod presence;
|
pub mod presence;
|
||||||
pub mod receipt;
|
pub mod receipt;
|
||||||
pub mod room;
|
pub mod room;
|
||||||
@ -142,6 +143,8 @@ pub enum EventType {
|
|||||||
CallInvite,
|
CallInvite,
|
||||||
/// m.direct
|
/// m.direct
|
||||||
Direct,
|
Direct,
|
||||||
|
/// m.fully_read
|
||||||
|
FullyRead,
|
||||||
/// m.presence
|
/// m.presence
|
||||||
Presence,
|
Presence,
|
||||||
/// m.receipt
|
/// m.receipt
|
||||||
@ -164,6 +167,8 @@ pub enum EventType {
|
|||||||
RoomMember,
|
RoomMember,
|
||||||
/// m.room.message
|
/// m.room.message
|
||||||
RoomMessage,
|
RoomMessage,
|
||||||
|
/// m.room.message.feedback
|
||||||
|
RoomMessageFeedback,
|
||||||
/// m.room.name
|
/// m.room.name
|
||||||
RoomName,
|
RoomName,
|
||||||
/// m.room.pinned_events
|
/// m.room.pinned_events
|
||||||
@ -253,6 +258,7 @@ impl Display for EventType {
|
|||||||
EventType::CallHangup => "m.call.hangup",
|
EventType::CallHangup => "m.call.hangup",
|
||||||
EventType::CallInvite => "m.call.invite",
|
EventType::CallInvite => "m.call.invite",
|
||||||
EventType::Direct => "m.direct",
|
EventType::Direct => "m.direct",
|
||||||
|
EventType::FullyRead => "m.fully_read",
|
||||||
EventType::Presence => "m.presence",
|
EventType::Presence => "m.presence",
|
||||||
EventType::Receipt => "m.receipt",
|
EventType::Receipt => "m.receipt",
|
||||||
EventType::RoomAliases => "m.room.aliases",
|
EventType::RoomAliases => "m.room.aliases",
|
||||||
@ -264,6 +270,7 @@ impl Display for EventType {
|
|||||||
EventType::RoomJoinRules => "m.room.join_rules",
|
EventType::RoomJoinRules => "m.room.join_rules",
|
||||||
EventType::RoomMember => "m.room.member",
|
EventType::RoomMember => "m.room.member",
|
||||||
EventType::RoomMessage => "m.room.message",
|
EventType::RoomMessage => "m.room.message",
|
||||||
|
EventType::RoomMessageFeedback => "m.room.message.feedback",
|
||||||
EventType::RoomName => "m.room.name",
|
EventType::RoomName => "m.room.name",
|
||||||
EventType::RoomPinnedEvents => "m.room.pinned_events",
|
EventType::RoomPinnedEvents => "m.room.pinned_events",
|
||||||
EventType::RoomPowerLevels => "m.room.power_levels",
|
EventType::RoomPowerLevels => "m.room.power_levels",
|
||||||
@ -287,6 +294,7 @@ impl<'a> From<&'a str> for EventType {
|
|||||||
"m.call.hangup" => EventType::CallHangup,
|
"m.call.hangup" => EventType::CallHangup,
|
||||||
"m.call.invite" => EventType::CallInvite,
|
"m.call.invite" => EventType::CallInvite,
|
||||||
"m.direct" => EventType::Direct,
|
"m.direct" => EventType::Direct,
|
||||||
|
"m.fully_read" => EventType::FullyRead,
|
||||||
"m.presence" => EventType::Presence,
|
"m.presence" => EventType::Presence,
|
||||||
"m.receipt" => EventType::Receipt,
|
"m.receipt" => EventType::Receipt,
|
||||||
"m.room.aliases" => EventType::RoomAliases,
|
"m.room.aliases" => EventType::RoomAliases,
|
||||||
@ -298,6 +306,7 @@ impl<'a> From<&'a str> for EventType {
|
|||||||
"m.room.join_rules" => EventType::RoomJoinRules,
|
"m.room.join_rules" => EventType::RoomJoinRules,
|
||||||
"m.room.member" => EventType::RoomMember,
|
"m.room.member" => EventType::RoomMember,
|
||||||
"m.room.message" => EventType::RoomMessage,
|
"m.room.message" => EventType::RoomMessage,
|
||||||
|
"m.room.message.feedback" => EventType::RoomMessageFeedback,
|
||||||
"m.room.name" => EventType::RoomName,
|
"m.room.name" => EventType::RoomName,
|
||||||
"m.room.pinned_events" => EventType::RoomPinnedEvents,
|
"m.room.pinned_events" => EventType::RoomPinnedEvents,
|
||||||
"m.room.power_levels" => EventType::RoomPowerLevels,
|
"m.room.power_levels" => EventType::RoomPowerLevels,
|
||||||
|
@ -78,7 +78,7 @@ mod tests {
|
|||||||
avatar_url: Some("mxc://localhost:wefuiwegh8742w".to_string()),
|
avatar_url: Some("mxc://localhost:wefuiwegh8742w".to_string()),
|
||||||
currently_active: Some(false),
|
currently_active: Some(false),
|
||||||
displayname: None,
|
displayname: None,
|
||||||
last_active_ago: Some(2478593),
|
last_active_ago: Some(2_478_593),
|
||||||
presence: PresenceState::Online,
|
presence: PresenceState::Online,
|
||||||
},
|
},
|
||||||
event_type: EventType::Presence,
|
event_type: EventType::Presence,
|
||||||
|
@ -9,11 +9,7 @@ event! {
|
|||||||
/// Informs the client of new receipts.
|
/// Informs the client of new receipts.
|
||||||
pub struct ReceiptEvent(ReceiptEventContent) {
|
pub struct ReceiptEvent(ReceiptEventContent) {
|
||||||
/// The unique identifier for the room associated with this event.
|
/// The unique identifier for the room associated with this event.
|
||||||
///
|
pub room_id: RoomId
|
||||||
/// This can be `None` if the event came from a context where there is
|
|
||||||
/// no ambiguity which room it belongs to, like a `/sync` response for example.
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
pub room_id: Option<RoomId>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +25,7 @@ pub struct Receipts {
|
|||||||
/// A collection of users who have sent *m.read* receipts for this event.
|
/// A collection of users who have sent *m.read* receipts for this event.
|
||||||
#[serde(rename = "m.read")]
|
#[serde(rename = "m.read")]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub m_read: UserReceipts,
|
pub read: UserReceipts,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mapping of user ID to receipt.
|
/// A mapping of user ID to receipt.
|
||||||
@ -40,6 +36,6 @@ pub type UserReceipts = HashMap<UserId, Receipt>;
|
|||||||
/// An acknowledgement of an event.
|
/// An acknowledgement of an event.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct Receipt {
|
pub struct Receipt {
|
||||||
/// The timestamp the receipt was sent at.
|
/// The timestamp (milliseconds since the Unix epoch) when the receipt was sent.
|
||||||
pub ts: u64,
|
pub ts: u64,
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,6 @@ pub struct AvatarEventContent {
|
|||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub info: Option<ImageInfo>,
|
pub info: Option<ImageInfo>,
|
||||||
/// Information about the avatar thumbnail image.
|
/// Information about the avatar thumbnail image.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub thumbnail_info: Option<ImageInfo>,
|
|
||||||
/// URL of the avatar thumbnail image.
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub thumbnail_url: Option<String>,
|
|
||||||
/// URL of the avatar image.
|
/// URL of the avatar image.
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Types for the *m.room.create* event.
|
//! Types for the *m.room.create* event.
|
||||||
|
|
||||||
use ruma_identifiers::UserId;
|
use ruma_identifiers::{EventId, RoomId, RoomVersionId, UserId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
state_event! {
|
state_event! {
|
||||||
@ -10,11 +10,24 @@ state_event! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of a `CreateEvent`.
|
/// The payload of a `CreateEvent`.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
pub struct CreateEventContent {
|
pub struct CreateEventContent {
|
||||||
/// The `user_id` of the room creator. This is set by the homeserver.
|
/// The `user_id` of the room creator. This is set by the homeserver.
|
||||||
pub creator: UserId,
|
pub creator: UserId,
|
||||||
/// Whether or not this room's data should be transferred to other homeservers.
|
/// Whether or not this room's data should be transferred to other homeservers.
|
||||||
#[serde(rename = "m.federate")]
|
#[serde(rename = "m.federate")]
|
||||||
pub federate: Option<bool>,
|
pub federate: Option<bool>,
|
||||||
|
/// The version of the room. Defaults to "1" if the key does not exist.
|
||||||
|
pub room_version: RoomVersionId,
|
||||||
|
/// A reference to the room this room replaces, if the previous room was upgraded.
|
||||||
|
pub predecessor: PreviousRoom,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A reference to an old room replaced during a room version upgrade.
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub struct PreviousRoom {
|
||||||
|
/// The ID of the old room.
|
||||||
|
pub room_id: RoomId,
|
||||||
|
/// The event ID of the last known event in the old room.
|
||||||
|
pub event_id: EventId,
|
||||||
}
|
}
|
||||||
|
@ -4,38 +4,40 @@ use ruma_identifiers::UserId;
|
|||||||
use ruma_signatures::Signatures;
|
use ruma_signatures::Signatures;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::stripped::StrippedState;
|
|
||||||
|
|
||||||
state_event! {
|
state_event! {
|
||||||
/// The current membership state of a user in the room.
|
/// The current membership state of a user in the room.
|
||||||
///
|
///
|
||||||
/// Adjusts the membership state for a user in a room. It is preferable to use the membership
|
/// Adjusts the membership state for a user in a room. It is preferable to use the membership
|
||||||
/// APIs (``/rooms/<room id>/invite`` etc) when performing membership actions rather than
|
/// APIs (`/rooms/<room id>/invite` etc) when performing membership actions rather than
|
||||||
/// adjusting the state directly as there are a restricted set of valid transformations. For
|
/// adjusting the state directly as there are a restricted set of valid transformations. For
|
||||||
/// example, user A cannot force user B to join a room, and trying to force this state change
|
/// example, user A cannot force user B to join a room, and trying to force this state change
|
||||||
/// directly will fail.
|
/// directly will fail.
|
||||||
///
|
///
|
||||||
/// The *third_party_invite* property will be set if this invite is an *invite* event and is the
|
/// The `third_party_invite` property will be set if this invite is an *invite* event and is the
|
||||||
/// successor of an *m.room.third_party_invite* event, and absent otherwise.
|
/// successor of an *m.room.third_party_invite* event, and absent otherwise.
|
||||||
///
|
///
|
||||||
/// This event may also include an *invite_room_state* key outside the *content* key. If
|
/// This event may also include an `invite_room_state` key inside the event's unsigned data. If
|
||||||
/// present, this contains an array of `StrippedState` events. These events provide information
|
/// present, this contains an array of `StrippedState` events. These events provide information
|
||||||
/// on a few select state events such as the room name.
|
/// on a subset of state events such as the room name.
|
||||||
pub struct MemberEvent(MemberEventContent) {
|
///
|
||||||
/// A subset of the state of the room at the time of the invite.
|
/// The user for which a membership applies is represented by the `state_key`. Under some
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
/// conditions, the `sender` and `state_key` may not match - this may be interpreted as the
|
||||||
pub invite_room_state: Option<Vec<StrippedState>>
|
/// `sender` affecting the membership state of the `state_key` user.
|
||||||
}
|
///
|
||||||
|
/// The membership for a given user can change over time. Previous membership can be retrieved
|
||||||
|
/// from the `prev_content` object on an event. If not present, the user's previous membership
|
||||||
|
/// must be assumed as leave.
|
||||||
|
pub struct MemberEvent(MemberEventContent) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of a `MemberEvent`.
|
/// The payload of a `MemberEvent`.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct MemberEventContent {
|
pub struct MemberEventContent {
|
||||||
/// The avatar URL for this user.
|
/// The avatar URL for this user, if any. This is added by the homeserver.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub avatar_url: Option<String>,
|
pub avatar_url: Option<String>,
|
||||||
|
|
||||||
/// The display name for this user.
|
/// The display name for this user, if any. This is added by the homeserver.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub displayname: Option<String>,
|
pub displayname: Option<String>,
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
//! Types for the *m.room.message* event.
|
//! Types for the *m.room.message* event.
|
||||||
|
|
||||||
|
use ruma_identifiers::EventId;
|
||||||
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use serde_json::{from_value, Value};
|
use serde_json::{from_value, Value};
|
||||||
|
|
||||||
use super::{ImageInfo, ThumbnailInfo};
|
use super::{EncryptedFile, ImageInfo, ThumbnailInfo};
|
||||||
|
|
||||||
|
pub mod feedback;
|
||||||
|
|
||||||
room_event! {
|
room_event! {
|
||||||
/// A message sent to a room.
|
/// A message sent to a room.
|
||||||
@ -47,6 +50,7 @@ pub enum MessageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of a message event.
|
/// The payload of a message event.
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum MessageEventContent {
|
pub enum MessageEventContent {
|
||||||
/// An audio message.
|
/// An audio message.
|
||||||
@ -84,8 +88,13 @@ pub struct AudioMessageEventContent {
|
|||||||
pub info: Option<AudioInfo>,
|
pub info: Option<AudioInfo>,
|
||||||
/// The message type. Always *m.audio*.
|
/// The message type. Always *m.audio*.
|
||||||
pub msgtype: MessageType,
|
pub msgtype: MessageType,
|
||||||
/// The URL to the audio clip.
|
/// The URL to the audio clip. Required if the file is unencrypted. The URL (typically
|
||||||
pub url: String,
|
/// [MXC URI](https://matrix.org/docs/spec/client_server/r0.5.0#mxc-uri)) to the audio clip.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub url: Option<String>,
|
||||||
|
/// Required if the audio clip is encrypted. Information on the encrypted audio clip.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub file: Option<EncryptedFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about an audio clip.
|
/// Metadata about an audio clip.
|
||||||
@ -109,6 +118,13 @@ pub struct EmoteMessageEventContent {
|
|||||||
pub body: String,
|
pub body: String,
|
||||||
/// The message type. Always *m.emote*.
|
/// The message type. Always *m.emote*.
|
||||||
pub msgtype: MessageType,
|
pub msgtype: MessageType,
|
||||||
|
/// The format used in the `formatted_body`. Currently only `org.matrix.custom.html` is
|
||||||
|
/// supported.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub format: Option<String>,
|
||||||
|
/// The formatted version of the `body`. This is required if `format` is specified.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub formatted_body: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of a file message.
|
/// The payload of a file message.
|
||||||
@ -118,14 +134,20 @@ pub struct FileMessageEventContent {
|
|||||||
/// original upload.
|
/// original upload.
|
||||||
pub body: String,
|
pub body: String,
|
||||||
/// The original filename of the uploaded file.
|
/// The original filename of the uploaded file.
|
||||||
pub filename: String,
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub filename: Option<String>,
|
||||||
/// Metadata about the file referred to in `url`.
|
/// Metadata about the file referred to in `url`.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub info: Option<FileInfo>,
|
pub info: Option<FileInfo>,
|
||||||
/// The message type. Always *m.file*.
|
/// The message type. Always *m.file*.
|
||||||
pub msgtype: MessageType,
|
pub msgtype: MessageType,
|
||||||
/// The URL to the file.
|
/// The URL to the file. Required if the file is unencrypted. The URL (typically
|
||||||
pub url: String,
|
/// [MXC URI](https://matrix.org/docs/spec/client_server/r0.5.0#mxc-uri)) to the file.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub url: Option<String>,
|
||||||
|
/// Required if file is encrypted. Information on the encrypted file.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub file: Option<EncryptedFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about a file.
|
/// Metadata about a file.
|
||||||
@ -138,9 +160,12 @@ pub struct FileInfo {
|
|||||||
/// Metadata about the image referred to in `thumbnail_url`.
|
/// Metadata about the image referred to in `thumbnail_url`.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumbnail_info: Option<ThumbnailInfo>,
|
pub thumbnail_info: Option<ThumbnailInfo>,
|
||||||
/// The URL to the thumbnail of the file.
|
/// The URL to the thumbnail of the file. Only present if the thumbnail is unencrypted.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumbnail_url: Option<String>,
|
pub thumbnail_url: Option<String>,
|
||||||
|
/// Information on the encrypted thumbnail file. Only present if the thumbnail is encrypted.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub thumbnail_file: Option<EncryptedFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of an image message.
|
/// The payload of an image message.
|
||||||
@ -154,8 +179,12 @@ pub struct ImageMessageEventContent {
|
|||||||
pub info: Option<ImageInfo>,
|
pub info: Option<ImageInfo>,
|
||||||
/// The message type. Always *m.image*.
|
/// The message type. Always *m.image*.
|
||||||
pub msgtype: MessageType,
|
pub msgtype: MessageType,
|
||||||
/// The URL to the image.
|
/// The URL to the image. Required if the file is unencrypted. The URL (typically
|
||||||
pub url: String,
|
/// [MXC URI](https://matrix.org/docs/spec/client_server/r0.5.0#mxc-uri)) to the image.
|
||||||
|
pub url: Option<String>,
|
||||||
|
/// Required if image is encrypted. Information on the encrypted image.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub file: Option<EncryptedFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of a location message.
|
/// The payload of a location message.
|
||||||
@ -176,12 +205,17 @@ pub struct LocationMessageEventContent {
|
|||||||
/// Thumbnail info associated with a location.
|
/// Thumbnail info associated with a location.
|
||||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
pub struct LocationInfo {
|
pub struct LocationInfo {
|
||||||
/// Metadata about the image referred to in `thumbnail_url`.
|
/// Metadata about the image referred to in `thumbnail_url` or `thumbnail_file`.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumbnail_info: Option<ThumbnailInfo>,
|
pub thumbnail_info: Option<ThumbnailInfo>,
|
||||||
/// The URL to a thumbnail of the location being represented.
|
/// The URL to a thumbnail of the location being represented. Only present if the thumbnail is
|
||||||
|
/// unencrypted.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumbnail_url: Option<String>,
|
pub thumbnail_url: Option<String>,
|
||||||
|
/// Information on an encrypted thumbnail of the location being represented. Only present if the
|
||||||
|
/// thumbnail is encrypted.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub thumbnail_file: Option<EncryptedFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of a notice message.
|
/// The payload of a notice message.
|
||||||
@ -191,6 +225,11 @@ pub struct NoticeMessageEventContent {
|
|||||||
pub body: String,
|
pub body: String,
|
||||||
/// The message type. Always *m.notice*.
|
/// The message type. Always *m.notice*.
|
||||||
pub msgtype: MessageType,
|
pub msgtype: MessageType,
|
||||||
|
/// Information about related messages for
|
||||||
|
/// [rich replies](https://matrix.org/docs/spec/client_server/r0.5.0#rich-replies).
|
||||||
|
#[serde(rename = "m.relates_to")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub relates_to: Option<RelatesTo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of a text message.
|
/// The payload of a text message.
|
||||||
@ -200,6 +239,18 @@ pub struct TextMessageEventContent {
|
|||||||
pub body: String,
|
pub body: String,
|
||||||
/// The message type. Always *m.text*.
|
/// The message type. Always *m.text*.
|
||||||
pub msgtype: MessageType,
|
pub msgtype: MessageType,
|
||||||
|
/// The format used in the `formatted_body`. Currently only `org.matrix.custom.html` is
|
||||||
|
/// supported.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub format: Option<String>,
|
||||||
|
/// The formatted version of the `body`. This is required if `format` is specified.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub formatted_body: Option<String>,
|
||||||
|
/// Information about related messages for
|
||||||
|
/// [rich replies](https://matrix.org/docs/spec/client_server/r0.5.0#rich-replies).
|
||||||
|
#[serde(rename = "m.relates_to")]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub relates_to: Option<RelatesTo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The payload of a video message.
|
/// The payload of a video message.
|
||||||
@ -213,8 +264,12 @@ pub struct VideoMessageEventContent {
|
|||||||
pub info: Option<VideoInfo>,
|
pub info: Option<VideoInfo>,
|
||||||
/// The message type. Always *m.video*.
|
/// The message type. Always *m.video*.
|
||||||
pub msgtype: MessageType,
|
pub msgtype: MessageType,
|
||||||
/// The URL to the video clip.
|
/// The URL to the video clip. Required if the file is unencrypted. The URL (typically
|
||||||
pub url: String,
|
/// [MXC URI](https://matrix.org/docs/spec/client_server/r0.5.0#mxc-uri)) to the video clip.
|
||||||
|
pub url: Option<String>,
|
||||||
|
/// Required if video clip is encrypted. Information on the encrypted video clip.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub file: Option<EncryptedFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about a video.
|
/// Metadata about a video.
|
||||||
@ -236,15 +291,35 @@ pub struct VideoInfo {
|
|||||||
/// Metadata about an image.
|
/// Metadata about an image.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumbnail_info: Option<ThumbnailInfo>,
|
pub thumbnail_info: Option<ThumbnailInfo>,
|
||||||
/// The URL to a thumbnail of the video clip.
|
/// The URL (typically [MXC URI](https://matrix.org/docs/spec/client_server/r0.5.0#mxc-uri)) to
|
||||||
|
/// an image thumbnail of the video clip. Only present if the thumbnail is unencrypted.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumbnail_url: Option<String>,
|
pub thumbnail_url: Option<String>,
|
||||||
|
/// Information on the encrypted thumbnail file. Only present if the thumbnail is encrypted.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub thumbnail_file: Option<EncryptedFile>,
|
||||||
/// The width of the video in pixels.
|
/// The width of the video in pixels.
|
||||||
#[serde(rename = "w")]
|
#[serde(rename = "w")]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub width: Option<u64>,
|
pub width: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information about related messages for
|
||||||
|
/// [rich replies](https://matrix.org/docs/spec/client_server/r0.5.0#rich-replies).
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub struct RelatesTo {
|
||||||
|
/// Information about another message being replied to.
|
||||||
|
#[serde(rename = "m.in_reply_to")]
|
||||||
|
pub in_reply_to: InReplyTo,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Information about the event a "rich reply" is replying to.
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub struct InReplyTo {
|
||||||
|
/// The event being replied to.
|
||||||
|
pub event_id: EventId,
|
||||||
|
}
|
||||||
|
|
||||||
impl_enum! {
|
impl_enum! {
|
||||||
MessageType {
|
MessageType {
|
||||||
Audio => "m.audio",
|
Audio => "m.audio",
|
||||||
@ -374,7 +449,8 @@ mod tests {
|
|||||||
body: "test".to_string(),
|
body: "test".to_string(),
|
||||||
info: None,
|
info: None,
|
||||||
msgtype: MessageType::Audio,
|
msgtype: MessageType::Audio,
|
||||||
url: "http://example.com/audio.mp3".to_string(),
|
url: Some("http://example.com/audio.mp3".to_string()),
|
||||||
|
file: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -389,7 +465,8 @@ mod tests {
|
|||||||
body: "test".to_string(),
|
body: "test".to_string(),
|
||||||
info: None,
|
info: None,
|
||||||
msgtype: MessageType::Audio,
|
msgtype: MessageType::Audio,
|
||||||
url: "http://example.com/audio.mp3".to_string(),
|
url: Some("http://example.com/audio.mp3".to_string()),
|
||||||
|
file: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
41
src/room/message/feedback.rs
Normal file
41
src/room/message/feedback.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//! Types for the *m.room.message.feedback* event.
|
||||||
|
|
||||||
|
use ruma_identifiers::EventId;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
room_event! {
|
||||||
|
/// An acknowledgement of a message.
|
||||||
|
///
|
||||||
|
/// N.B.: Usage of this event is discouraged in favor of the receipts module. Most clients will
|
||||||
|
/// not recognise this event.
|
||||||
|
pub struct FeedbackEvent(FeedbackEventContent) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The payload of an *m.room.message.feedback* event.
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub struct FeedbackEventContent {
|
||||||
|
/// The event that this feedback is related to.
|
||||||
|
pub target_event_id: EventId,
|
||||||
|
/// The type of feedback.
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub feedback_type: FeedbackType,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type of feedback.
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub enum FeedbackType {
|
||||||
|
/// Sent when a message is received.
|
||||||
|
#[serde(rename = "delivered")]
|
||||||
|
Delivered,
|
||||||
|
|
||||||
|
/// Sent when a message has been observed by the end user.
|
||||||
|
#[serde(rename = "read")]
|
||||||
|
Read,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_enum! {
|
||||||
|
FeedbackType {
|
||||||
|
Delivered => "delivered",
|
||||||
|
Read => "read",
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,8 @@
|
|||||||
//!
|
//!
|
||||||
//! This module also contains types shared by events in its child namespaces.
|
//! This module also contains types shared by events in its child namespaces.
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub mod aliases;
|
pub mod aliases;
|
||||||
@ -33,9 +35,12 @@ pub struct ImageInfo {
|
|||||||
/// Metadata about the image referred to in `thumbnail_url`.
|
/// Metadata about the image referred to in `thumbnail_url`.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumbnail_info: Option<ThumbnailInfo>,
|
pub thumbnail_info: Option<ThumbnailInfo>,
|
||||||
/// The URL to the thumbnail of the image.
|
/// The URL to the thumbnail of the image. Only present if the thumbnail is unencrypted.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub thumbnail_url: Option<String>,
|
pub thumbnail_url: Option<String>,
|
||||||
|
/// Information on the encrypted thumbnail image. Only present if the thumbnail is encrypted.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub thumbnail_file: Option<EncryptedFile>,
|
||||||
/// The width of the image in pixels.
|
/// The width of the image in pixels.
|
||||||
#[serde(rename = "w")]
|
#[serde(rename = "w")]
|
||||||
pub width: u64,
|
pub width: u64,
|
||||||
@ -55,3 +60,35 @@ pub struct ThumbnailInfo {
|
|||||||
#[serde(rename = "w")]
|
#[serde(rename = "w")]
|
||||||
pub width: u64,
|
pub width: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A file sent to a room with end-to-end encryption enabled.
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub struct EncryptedFile {
|
||||||
|
/// The URL to the file.
|
||||||
|
pub url: String,
|
||||||
|
/// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
|
||||||
|
pub key: JsonWebKey,
|
||||||
|
/// The initialization vector used by AES-CTR, encoded as unpadded base64.
|
||||||
|
pub iv: String,
|
||||||
|
/// A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64.
|
||||||
|
/// Clients should support the SHA-256 hash, which uses the key sha256.
|
||||||
|
pub hashes: HashMap<String, String>,
|
||||||
|
/// Version of the encrypted attachments protocol. Must be `v2`.
|
||||||
|
pub v: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
|
||||||
|
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||||
|
pub struct JsonWebKey {
|
||||||
|
/// Key type. Must be `oct`.
|
||||||
|
pub kty: String,
|
||||||
|
/// Key operations. Must at least contain `encrypt` and `decrypt`.
|
||||||
|
pub key_ops: Vec<String>,
|
||||||
|
/// Required. Algorithm. Must be `A256CTR`.
|
||||||
|
pub alg: String,
|
||||||
|
/// The key, encoded as urlsafe unpadded base64.
|
||||||
|
pub k: String,
|
||||||
|
/// Extractable. Must be `true`. This is a
|
||||||
|
/// [W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk).
|
||||||
|
pub ext: bool,
|
||||||
|
}
|
||||||
|
@ -12,7 +12,6 @@ state_event! {
|
|||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct NameEventContent {
|
pub struct NameEventContent {
|
||||||
/// The name of the room. This MUST NOT exceed 255 bytes.
|
/// The name of the room. This MUST NOT exceed 255 bytes.
|
||||||
/// Rooms with `name: None` should be treated the same as a room with no name.
|
|
||||||
// The spec says “A room with an m.room.name event with an absent, null, or empty name field
|
// The spec says “A room with an m.room.name event with an absent, null, or empty name field
|
||||||
// should be treated the same as a room with no m.room.name event.”.
|
// should be treated the same as a room with no m.room.name event.”.
|
||||||
// Serde maps null fields to None by default, serde(default) maps an absent field to None,
|
// Serde maps null fields to None by default, serde(default) maps an absent field to None,
|
||||||
|
@ -36,7 +36,7 @@ mod tests {
|
|||||||
content: content.clone(),
|
content: content.clone(),
|
||||||
event_id: EventId::new("example.com").unwrap(),
|
event_id: EventId::new("example.com").unwrap(),
|
||||||
event_type: EventType::RoomPinnedEvents,
|
event_type: EventType::RoomPinnedEvents,
|
||||||
origin_server_ts: 1432804485886,
|
origin_server_ts: 1_432_804_485_886,
|
||||||
prev_content: None,
|
prev_content: None,
|
||||||
room_id: Some(RoomId::new("example.com").unwrap()),
|
room_id: Some(RoomId::new("example.com").unwrap()),
|
||||||
sender: UserId::new("example.com").unwrap(),
|
sender: UserId::new("example.com").unwrap(),
|
||||||
|
@ -52,6 +52,19 @@ pub struct PowerLevelsEventContent {
|
|||||||
/// The default power level for every user in the room.
|
/// The default power level for every user in the room.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub users_default: u64,
|
pub users_default: u64,
|
||||||
|
|
||||||
|
/// The power level requirements for specific notification types.
|
||||||
|
///
|
||||||
|
/// This is a mapping from `key` to power level for that notifications key.
|
||||||
|
pub notifications: NotificationPowerLevels,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The power level requirements for specific notification types.
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct NotificationPowerLevels {
|
||||||
|
/// The level required to trigger an `@room` notification.
|
||||||
|
#[serde(default = "default_power_level")]
|
||||||
|
pub room: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_power_level() -> u64 {
|
fn default_power_level() -> u64 {
|
||||||
|
@ -338,7 +338,7 @@ mod tests {
|
|||||||
assert_eq!(event.sender.to_string(), "@example:localhost");
|
assert_eq!(event.sender.to_string(), "@example:localhost");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
assert!(false);
|
unreachable!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -350,7 +350,7 @@ mod tests {
|
|||||||
assert_eq!(event.sender.to_string(), "@example:localhost");
|
assert_eq!(event.sender.to_string(), "@example:localhost");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
assert!(false);
|
unreachable!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -362,14 +362,14 @@ mod tests {
|
|||||||
assert_eq!(image_info.width, 128);
|
assert_eq!(image_info.width, 128);
|
||||||
assert_eq!(image_info.mimetype, "image/jpeg");
|
assert_eq!(image_info.mimetype, "image/jpeg");
|
||||||
assert_eq!(image_info.size, 1024);
|
assert_eq!(image_info.size, 1024);
|
||||||
assert_eq!(event.content.thumbnail_info.unwrap().size, 32);
|
assert_eq!(image_info.thumbnail_info.unwrap().size, 32);
|
||||||
assert_eq!(event.content.url, "https://domain.com/image.jpg");
|
assert_eq!(event.content.url, "https://domain.com/image.jpg");
|
||||||
assert_eq!(event.event_type, EventType::RoomAvatar);
|
assert_eq!(event.event_type, EventType::RoomAvatar);
|
||||||
assert_eq!(event.state_key, "");
|
assert_eq!(event.state_key, "");
|
||||||
assert_eq!(event.sender.to_string(), "@example:localhost");
|
assert_eq!(event.sender.to_string(), "@example:localhost");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
assert!(false);
|
unreachable!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -21,5 +21,5 @@ pub struct TagEventContent {
|
|||||||
pub struct TagInfo {
|
pub struct TagInfo {
|
||||||
/// Value to use for lexicographically ordering rooms with this tag.
|
/// Value to use for lexicographically ordering rooms with this tag.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub order: Option<String>,
|
pub order: Option<f64>,
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,7 @@ event! {
|
|||||||
/// Informs the client of the list of users currently typing.
|
/// Informs the client of the list of users currently typing.
|
||||||
pub struct TypingEvent(TypingEventContent) {
|
pub struct TypingEvent(TypingEventContent) {
|
||||||
/// The unique identifier for the room associated with this event.
|
/// The unique identifier for the room associated with this event.
|
||||||
///
|
pub room_id: RoomId
|
||||||
/// This can be `None` if the event came from a context where there is
|
|
||||||
/// no ambiguity which room it belongs to, like a `/sync` response for example.
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
pub room_id: Option<RoomId>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user