cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 1 | use ruma::{ |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 2 | OwnedEventId, UserId, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 3 | events::{ |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 4 | poll::{start::PollStartEventContent, unstable_start::UnstablePollStartEventContent}, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 5 | room::message::{ |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 6 | MessageType, Relation, RoomMessageEventContent, RoomMessageEventContentWithoutRelation, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 7 | }, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 8 | sticker::StickerEventContent, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 9 | }, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 10 | }; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 11 | use serde_json::Value; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 12 | |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 13 | use super::{ |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 14 | link_preview::sender_previews, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 15 | media::{ |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 16 | MediaRegistration, media_descriptor_for_sticker, media_registration, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 17 | media_sticker_registration, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 18 | }, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 19 | timeline::formatted_body, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 20 | }; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 21 | use crate::{ |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 22 | Message, MessageMentions, ReplyDetails, ReplyReference, SendState, Sender, TimelineContent, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 23 | TimelineEvent, TimelineItem, TimelineItemId, UtdCause, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 24 | }; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 25 | |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 26 | pub(crate) fn normalise_observed( |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 27 | value: &Value, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 28 | current_user_id: Option<&UserId>, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 29 | identity: &str, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 30 | ) -> Option<(TimelineItem, Vec<MediaRegistration>)> { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 31 | let event_id: OwnedEventId = serde_json::from_value(value.get("event_id")?.clone()).ok()?; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 32 | let sender_id: ruma::OwnedUserId = serde_json::from_value(value.get("sender")?.clone()).ok()?; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 33 | let timestamp_ms = value.get("origin_server_ts")?.as_u64()?; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 34 | let event_type = value.get("type")?.as_str()?.to_owned(); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 35 | let own = current_user_id.is_some_and(|user_id| user_id.as_str() == sender_id.as_str()); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 36 | let redacted = value |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 37 | .get("unsigned") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 38 | .and_then(|unsigned| unsigned.get("redacted_because")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 39 | .is_some(); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 40 | let mut media = Vec::new(); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 41 | let (content, reply_to, thread_root) = if redacted { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 42 | (TimelineContent::Redacted, None, None) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 43 | } else if event_type == "m.room.message" { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 44 | match value |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 45 | .get("content") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 46 | .cloned() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 47 | .and_then(|content| serde_json::from_value::<RoomMessageEventContent>(content).ok()) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 48 | { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 49 | Some(mut message) => { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 50 | let (reply_to, thread_root) = relation_refs(message.relates_to.as_ref()); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 51 | let relation_replacement = match &message.relates_to { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 52 | Some(Relation::Replacement(replacement)) => { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 53 | Some(replacement.new_content.clone()) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 54 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 55 | _ => None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 56 | }; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 57 | let bundled_replacement = value |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 58 | .get("unsigned") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 59 | .and_then(|unsigned| unsigned.get("m.relations")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 60 | .and_then(|relations| relations.get("m.replace")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 61 | .and_then(|edit| { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 62 | let edit_sender = edit.get("sender")?.as_str()?; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 63 | if edit_sender != sender_id.as_str() { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 64 | return None; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 65 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 66 | edit.get("content")?.get("m.new_content").cloned() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 67 | }) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 68 | .and_then(|content| { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 69 | serde_json::from_value::<RoomMessageEventContentWithoutRelation>(content) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 70 | .ok() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 71 | }); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 72 | let edited = relation_replacement.is_some() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 73 | || bundled_replacement.is_some() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 74 | || value |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 75 | .get("unsigned") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 76 | .and_then(|unsigned| unsigned.get("macltok_edited")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 77 | .and_then(Value::as_bool) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 78 | .unwrap_or(false); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 79 | if let Some(replacement) = relation_replacement.or(bundled_replacement) { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 80 | message.apply_replacement(replacement); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 81 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 82 | let message_type = &message.msgtype; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 83 | media.extend(media_registration(identity, message_type)); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 84 | let previews = sender_previews(Some(identity), message_type); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 85 | media.extend( |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 86 | previews |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 87 | .iter() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 88 | .filter_map(|(_, registration)| registration.clone()), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 89 | ); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 90 | ( |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 91 | TimelineContent::Message(Message { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 92 | kind: super::message_kind(message_type), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 93 | body: message.body().to_owned(), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 94 | geo_uri: match message_type { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 95 | MessageType::Location(location) => Some(location.geo_uri.clone()), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 96 | _ => None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 97 | }, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 98 | formatted_body: formatted_body(message_type), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 99 | mentions: message.mentions.as_ref().map(|mentions| MessageMentions { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 100 | user_ids: mentions.user_ids.iter().cloned().collect(), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 101 | room: mentions.room, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 102 | }), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 103 | edited, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 104 | media: super::media::media_from_message(identity, message_type), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 105 | link_previews: previews.into_iter().map(|(preview, _)| preview).collect(), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 106 | }), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 107 | reply_to, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 108 | thread_root, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 109 | ) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 110 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 111 | None => (TimelineContent::Other { event_type }, None, None), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 112 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 113 | } else if event_type == "m.room.encrypted" { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 114 | ( |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 115 | TimelineContent::UnableToDecrypt(UtdCause::Unknown), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 116 | None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 117 | None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 118 | ) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 119 | } else if event_type == "m.sticker" { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 120 | match value |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 121 | .get("content") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 122 | .cloned() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 123 | .and_then(|content| serde_json::from_value::<StickerEventContent>(content).ok()) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 124 | { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 125 | Some(sticker) => { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 126 | let (reply_to, thread_root) = relation_refs(sticker.relates_to.as_ref()); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 127 | media.extend(media_sticker_registration(identity, &sticker)); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 128 | ( |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 129 | TimelineContent::Sticker { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 130 | body: sticker.body.clone(), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 131 | media: media_descriptor_for_sticker(identity, &sticker), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 132 | }, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 133 | reply_to, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 134 | thread_root, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 135 | ) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 136 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 137 | None => (TimelineContent::Other { event_type }, None, None), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 138 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 139 | } else if event_type == "m.poll.start" || event_type == "org.matrix.msc3381.poll.start" { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 140 | let poll_content = value.get("content"); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 141 | let question = poll_content.and_then(|content| poll_question(content, &event_type)); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 142 | match question { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 143 | Some(question) => { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 144 | let (reply_to, thread_root) = |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 145 | poll_content.map(raw_relation_refs).unwrap_or_default(); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 146 | (TimelineContent::Poll { question }, reply_to, thread_root) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 147 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 148 | None => (TimelineContent::Other { event_type }, None, None), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 149 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 150 | } else if let Some(state_key) = value.get("state_key").and_then(Value::as_str) { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 151 | ( |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 152 | TimelineContent::OtherState { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 153 | event_type, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 154 | state_key: state_key.to_owned(), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 155 | }, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 156 | None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 157 | None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 158 | ) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 159 | } else { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 160 | (TimelineContent::Other { event_type }, None, None) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 161 | }; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 162 | let event = TimelineEvent { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 163 | item_id: TimelineItemId::new(identity.to_owned()), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 164 | event_id: Some(event_id), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 165 | transaction_id: None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 166 | sender: Sender { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 167 | user_id: sender_id, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 168 | display_name: None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 169 | avatar: None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 170 | name_ambiguous: false, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 171 | }, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 172 | timestamp_ms, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 173 | own, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 174 | send_state: SendState::Sent, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 175 | content, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 176 | reply_to: reply_to.map(|event_id| ReplyReference { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 177 | event_id, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 178 | details: ReplyDetails::Pending, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 179 | }), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 180 | thread_root, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 181 | thread_summary: None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 182 | reactions: Vec::new(), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 183 | read_by: Vec::new(), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 184 | editable: false, |
913832a327a8 | atagen | 2026-10-25 09:33 UTC | 185 | highlight: false, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 186 | }; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 187 | Some((TimelineItem::Event(Box::new(event)), media)) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 188 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 189 | |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 190 | fn relation_refs<C>( |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 191 | relation: Option<&Relation<C>>, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 192 | ) -> (Option<OwnedEventId>, Option<OwnedEventId>) { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 193 | match relation { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 194 | Some(Relation::Reply(reply)) => (Some(reply.in_reply_to.event_id.clone()), None), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 195 | Some(Relation::Thread(thread)) => ( |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 196 | thread |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 197 | .in_reply_to |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 198 | .as_ref() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 199 | .map(|reply| reply.event_id.clone()), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 200 | Some(thread.event_id.clone()), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 201 | ), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 202 | _ => (None, None), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 203 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 204 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 205 | |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 206 | fn raw_relation_refs(content: &Value) -> (Option<OwnedEventId>, Option<OwnedEventId>) { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 207 | let Some(relation) = content.get("m.relates_to") else { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 208 | return (None, None); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 209 | }; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 210 | let reply_to = relation |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 211 | .get("m.in_reply_to") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 212 | .and_then(|reply| reply.get("event_id")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 213 | .and_then(Value::as_str) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 214 | .and_then(|event_id| event_id.parse().ok()); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 215 | let thread_root = (relation.get("rel_type").and_then(Value::as_str) == Some("m.thread")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 216 | .then(|| relation.get("event_id").and_then(Value::as_str)) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 217 | .flatten() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 218 | .and_then(|event_id| event_id.parse().ok()); |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 219 | (reply_to, thread_root) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 220 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 221 | |
c9effeac326a | atagen | 2026-10-25 10:32 UTC | 222 | pub(crate) fn poll_question(content: &Value, event_type: &str) -> Option<String> { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 223 | let typed_question = match event_type { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 224 | "m.poll.start" => serde_json::from_value::<PollStartEventContent>(content.clone()) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 225 | .ok() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 226 | .and_then(|poll| poll.poll.question.text.find_plain().map(str::to_owned)), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 227 | "org.matrix.msc3381.poll.start" => { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 228 | serde_json::from_value::<UnstablePollStartEventContent>(content.clone()) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 229 | .ok() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 230 | .map(|poll| poll.poll_start().question.text.clone()) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 231 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 232 | _ => None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 233 | }; |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 234 | typed_question |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 235 | .or_else(|| { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 236 | content |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 237 | .get("m.poll") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 238 | .and_then(|poll| poll.get("question")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 239 | .and_then(|question| question.get("m.text")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 240 | .and_then(generic_text) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 241 | }) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 242 | .or_else(|| { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 243 | content |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 244 | .get("org.matrix.msc3381.poll.start") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 245 | .and_then(|poll| poll.get("question")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 246 | .and_then(|question| question.get("org.matrix.msc1767.text")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 247 | .and_then(generic_text) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 248 | }) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 249 | .or_else(|| { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 250 | ["org.matrix.msc1767.text", "m.text", "question", "body"] |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 251 | .iter() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 252 | .find_map(|key| content.get(*key).and_then(generic_text)) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 253 | }) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 254 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 255 | |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 256 | fn generic_text(value: &Value) -> Option<String> { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 257 | match value { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 258 | Value::String(text) => Some(text.clone()), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 259 | Value::Array(representations) => representations |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 260 | .iter() |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 261 | .find(|representation| { |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 262 | representation.get("mimetype").and_then(Value::as_str) == Some("text/plain") |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 263 | }) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 264 | .or_else(|| representations.first()) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 265 | .and_then(|representation| representation.get("body")) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 266 | .and_then(Value::as_str) |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 267 | .map(str::to_owned), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 268 | Value::Object(_) => value.get("body").and_then(Value::as_str).map(str::to_owned), |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 269 | _ => None, |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 270 | } |
cbb715e11963 | atagen | 2026-10-24 23:24 UTC | 271 | } |