events: Support m.html shortcut for MessageContent
This commit is contained in:
		
							parent
							
								
									ed8990c3fd
								
							
						
					
					
						commit
						6f3d9fd327
					
				| @ -14,6 +14,14 @@ pub(crate) struct MessageContentSerDeHelper { | ||||
|     #[serde(rename = "org.matrix.msc1767.text")] | ||||
|     text_unstable: Option<String>, | ||||
| 
 | ||||
|     /// HTML short form, stable name.
 | ||||
|     #[serde(rename = "m.html")] | ||||
|     html_stable: Option<String>, | ||||
| 
 | ||||
|     /// HTML short form, unstable name.
 | ||||
|     #[serde(rename = "org.matrix.msc1767.html")] | ||||
|     html_unstable: Option<String>, | ||||
| 
 | ||||
|     /// Long form, stable name.
 | ||||
|     #[serde(rename = "m.message")] | ||||
|     message_stable: Option<Vec<Text>>, | ||||
| @ -30,16 +38,26 @@ impl TryFrom<MessageContentSerDeHelper> for MessageContent { | ||||
|         let MessageContentSerDeHelper { | ||||
|             text_stable, | ||||
|             text_unstable, | ||||
|             html_stable, | ||||
|             html_unstable, | ||||
|             message_stable, | ||||
|             message_unstable, | ||||
|         } = helper; | ||||
| 
 | ||||
|         if let Some(message) = message_stable.or(message_unstable) { | ||||
|             Ok(Self(message)) | ||||
|         } else if let Some(text) = text_stable.or(text_unstable) { | ||||
|             Ok(Self::plain(text)) | ||||
|         } else { | ||||
|             Err(TryFromExtensibleError::MissingField("m.message or m.text".to_owned())) | ||||
|             let message: Vec<_> = html_stable | ||||
|                 .or(html_unstable) | ||||
|                 .map(Text::html) | ||||
|                 .into_iter() | ||||
|                 .chain(text_stable.or(text_unstable).map(Text::plain)) | ||||
|                 .collect(); | ||||
|             if !message.is_empty() { | ||||
|                 Ok(Self(message)) | ||||
|             } else { | ||||
|                 Err(TryFromExtensibleError::MissingField("m.message, m.text or m.html".to_owned())) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -49,13 +67,30 @@ impl Serialize for MessageContent { | ||||
|     where | ||||
|         S: serde::Serializer, | ||||
|     { | ||||
|         let mut st = serializer.serialize_struct("MessageContent", 1)?; | ||||
|         if self.len() == 1 && self[0].mimetype == "text/plain" { | ||||
|             st.serialize_field("org.matrix.msc1767.text", &self[0].body)?; | ||||
|         #[cfg(feature = "unstable-msc3554")] | ||||
|         let has_shortcut = |message: &Text| { | ||||
|             matches!(&*message.mimetype, "text/plain" | "text/html") && message.lang.is_none() | ||||
|         }; | ||||
| 
 | ||||
|         #[cfg(not(feature = "unstable-msc3554"))] | ||||
|         let has_shortcut = | ||||
|             |message: &Text| matches!(&*message.mimetype, "text/plain" | "text/html"); | ||||
| 
 | ||||
|         if self.iter().all(has_shortcut) { | ||||
|             let mut st = serializer.serialize_struct("MessageContent", self.len())?; | ||||
|             for message in self.iter() { | ||||
|                 if message.mimetype == "text/plain" { | ||||
|                     st.serialize_field("org.matrix.msc1767.text", &message.body)?; | ||||
|                 } else if message.mimetype == "text/html" { | ||||
|                     st.serialize_field("org.matrix.msc1767.html", &message.body)?; | ||||
|                 } | ||||
|             } | ||||
|             st.end() | ||||
|         } else { | ||||
|             let mut st = serializer.serialize_struct("MessageContent", 1)?; | ||||
|             st.serialize_field("org.matrix.msc1767.message", &self.0)?; | ||||
|             st.end() | ||||
|         } | ||||
|         st.end() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -172,10 +172,8 @@ fn event_serialization() { | ||||
|         to_json_value(&event).unwrap(), | ||||
|         json!({ | ||||
|             "content": { | ||||
|                 "org.matrix.msc1767.message": [ | ||||
|                     { "body": "Upload: <strong>my_mix.mp3</strong>", "mimetype": "text/html"}, | ||||
|                     { "body": "Upload: my_mix.mp3", "mimetype": "text/plain"}, | ||||
|                 ], | ||||
|                 "org.matrix.msc1767.html": "Upload: <strong>my_mix.mp3</strong>", | ||||
|                 "org.matrix.msc1767.text": "Upload: my_mix.mp3", | ||||
|                 "m.file": { | ||||
|                     "url": "mxc://notareal.hs/abcdef", | ||||
|                     "name": "my_mix.mp3", | ||||
|  | ||||
| @ -126,10 +126,8 @@ fn file_event_serialization() { | ||||
|         to_json_value(&event).unwrap(), | ||||
|         json!({ | ||||
|             "content": { | ||||
|                 "org.matrix.msc1767.message": [ | ||||
|                     { "body": "Upload: <strong>my_file.txt</strong>", "mimetype": "text/html"}, | ||||
|                     { "body": "Upload: my_file.txt", "mimetype": "text/plain"}, | ||||
|                 ], | ||||
|                 "org.matrix.msc1767.html": "Upload: <strong>my_file.txt</strong>", | ||||
|                 "org.matrix.msc1767.text": "Upload: my_file.txt", | ||||
|                 "m.file": { | ||||
|                     "url": "mxc://notareal.hs/abcdef", | ||||
|                     "name": "my_file.txt", | ||||
|  | ||||
| @ -147,10 +147,8 @@ fn image_event_serialization() { | ||||
|         to_json_value(&event).unwrap(), | ||||
|         json!({ | ||||
|             "content": { | ||||
|                 "org.matrix.msc1767.message": [ | ||||
|                     { "body": "Upload: <strong>my_house.jpg</strong>", "mimetype": "text/html"}, | ||||
|                     { "body": "Upload: my_house.jpg", "mimetype": "text/plain"}, | ||||
|                 ], | ||||
|                 "org.matrix.msc1767.html": "Upload: <strong>my_house.jpg</strong>", | ||||
|                 "org.matrix.msc1767.text": "Upload: my_house.jpg", | ||||
|                 "m.file": { | ||||
|                     "url": "mxc://notareal.hs/abcdef", | ||||
|                     "name": "my_house.jpg", | ||||
|  | ||||
| @ -70,16 +70,8 @@ fn event_serialization() { | ||||
|         to_json_value(&event).unwrap(), | ||||
|         json!({ | ||||
|             "content": { | ||||
|                 "org.matrix.msc1767.message": [ | ||||
|                     { | ||||
|                         "body": "Alice was at <strong>geo:51.5008,0.1247;u=35</strong> as of <em>Sat Nov 13 18:50:58 2021</em>", | ||||
|                         "mimetype": "text/html", | ||||
|                     }, | ||||
|                     { | ||||
|                         "body": "Alice was at geo:51.5008,0.1247;u=35 as of Sat Nov 13 18:50:58 2021", | ||||
|                         "mimetype": "text/plain", | ||||
|                     }, | ||||
|                 ], | ||||
|                 "org.matrix.msc1767.html": "Alice was at <strong>geo:51.5008,0.1247;u=35</strong> as of <em>Sat Nov 13 18:50:58 2021</em>", | ||||
|                 "org.matrix.msc1767.text": "Alice was at geo:51.5008,0.1247;u=35 as of Sat Nov 13 18:50:58 2021", | ||||
|                 "m.location": { | ||||
|                     "uri": "geo:51.5008,0.1247;u=35", | ||||
|                     "description": "Alice's whereabouts", | ||||
|  | ||||
| @ -37,10 +37,8 @@ fn html_content_serialization() { | ||||
|     assert_eq!( | ||||
|         to_json_value(&message_event_content).unwrap(), | ||||
|         json!({ | ||||
|             "org.matrix.msc1767.message": [ | ||||
|                 { "body": "Hello, <em>World</em>!", "mimetype": "text/html"}, | ||||
|                 { "body": "Hello, World!", "mimetype": "text/plain"}, | ||||
|             ] | ||||
|             "org.matrix.msc1767.html": "Hello, <em>World</em>!", | ||||
|             "org.matrix.msc1767.text": "Hello, World!", | ||||
|         }) | ||||
|     ); | ||||
| } | ||||
| @ -96,10 +94,8 @@ fn markdown_content_serialization() { | ||||
|     assert_eq!( | ||||
|         to_json_value(&formatted_message).unwrap(), | ||||
|         json!({ | ||||
|             "org.matrix.msc1767.message": [ | ||||
|                 { "body": "<p>Testing <strong>bold</strong> and <em>italic</em>!</p>\n", "mimetype": "text/html"}, | ||||
|                 { "body": "Testing **bold** and _italic_!", "mimetype": "text/plain"}, | ||||
|             ] | ||||
|             "org.matrix.msc1767.html": "<p>Testing <strong>bold</strong> and <em>italic</em>!</p>\n", | ||||
|             "org.matrix.msc1767.text": "Testing **bold** and _italic_!", | ||||
|         }) | ||||
|     ); | ||||
| 
 | ||||
| @ -118,10 +114,8 @@ fn markdown_content_serialization() { | ||||
|     assert_eq!( | ||||
|         to_json_value(&plain_message_paragraphs).unwrap(), | ||||
|         json!({ | ||||
|             "org.matrix.msc1767.message": [ | ||||
|                 { "body": "<p>Testing</p>\n<p>Several</p>\n<p>Paragraphs.</p>\n", "mimetype": "text/html"}, | ||||
|                 { "body": "Testing\n\nSeveral\n\nParagraphs.", "mimetype": "text/plain"}, | ||||
|             ] | ||||
|             "org.matrix.msc1767.html": "<p>Testing</p>\n<p>Several</p>\n<p>Paragraphs.</p>\n", | ||||
|             "org.matrix.msc1767.text": "Testing\n\nSeveral\n\nParagraphs.", | ||||
|         }) | ||||
|     ); | ||||
| } | ||||
| @ -198,7 +192,53 @@ fn plain_text_content_stable_deserialization() { | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn html_text_content_unstable_deserialization() { | ||||
| fn html_content_unstable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "org.matrix.msc1767.html": "Hello, <em>New World</em>!", | ||||
|     }); | ||||
| 
 | ||||
|     let content = from_json_value::<MessageEventContent>(json_data).unwrap(); | ||||
|     assert_eq!(content.message.find_plain(), None); | ||||
|     assert_eq!(content.message.find_html(), Some("Hello, <em>New World</em>!")); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn html_content_stable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "m.html": "Hello, <em>New World</em>!", | ||||
|     }); | ||||
| 
 | ||||
|     let content = from_json_value::<MessageEventContent>(json_data).unwrap(); | ||||
|     assert_eq!(content.message.find_plain(), None); | ||||
|     assert_eq!(content.message.find_html(), Some("Hello, <em>New World</em>!")); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn html_and_text_content_unstable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "org.matrix.msc1767.html": "Hello, <em>New World</em>!", | ||||
|         "org.matrix.msc1767.text": "Hello, New World!", | ||||
|     }); | ||||
| 
 | ||||
|     let content = from_json_value::<MessageEventContent>(json_data).unwrap(); | ||||
|     assert_eq!(content.message.find_plain(), Some("Hello, New World!")); | ||||
|     assert_eq!(content.message.find_html(), Some("Hello, <em>New World</em>!")); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn html_and_text_content_stable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "m.html": "Hello, <em>New World</em>!", | ||||
|         "m.text": "Hello, New World!", | ||||
|     }); | ||||
| 
 | ||||
|     let content = from_json_value::<MessageEventContent>(json_data).unwrap(); | ||||
|     assert_eq!(content.message.find_plain(), Some("Hello, New World!")); | ||||
|     assert_eq!(content.message.find_html(), Some("Hello, <em>New World</em>!")); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn message_content_unstable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "org.matrix.msc1767.message": [ | ||||
|             { "body": "Hello, <em>New World</em>!", "mimetype": "text/html"}, | ||||
| @ -212,7 +252,7 @@ fn html_text_content_unstable_deserialization() { | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn html_text_content_stable_deserialization() { | ||||
| fn message_content_stable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "m.message": [ | ||||
|             { "body": "Hello, <em>New World</em>!", "mimetype": "text/html"}, | ||||
| @ -315,7 +355,61 @@ fn room_message_plain_text_unstable_deserialization() { | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn room_message_html_text_stable_deserialization() { | ||||
| fn room_message_html_and_text_stable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "body": "test", | ||||
|         "formatted_body": "<h1>test</h1>", | ||||
|         "format": "org.matrix.custom.html", | ||||
|         "msgtype": "m.text", | ||||
|         "m.html": "<h1>test</h1>", | ||||
|         "m.text": "test", | ||||
|     }); | ||||
| 
 | ||||
|     let content = assert_matches!( | ||||
|         from_json_value::<RoomMessageEventContent>(json_data), | ||||
|         Ok(RoomMessageEventContent { | ||||
|             msgtype: MessageType::Text(content), | ||||
|             .. | ||||
|         }) => content | ||||
|     ); | ||||
|     assert_eq!(content.body, "test"); | ||||
|     let formatted = content.formatted.unwrap(); | ||||
|     assert_eq!(formatted.body, "<h1>test</h1>"); | ||||
|     let message = content.message.unwrap(); | ||||
|     assert_eq!(message.len(), 2); | ||||
|     assert_eq!(message[0].body, "<h1>test</h1>"); | ||||
|     assert_eq!(message[1].body, "test"); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn room_message_html_and_text_unstable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "body": "test", | ||||
|         "formatted_body": "<h1>test</h1>", | ||||
|         "format": "org.matrix.custom.html", | ||||
|         "msgtype": "m.text", | ||||
|         "org.matrix.msc1767.html": "<h1>test</h1>", | ||||
|         "org.matrix.msc1767.text": "test", | ||||
|     }); | ||||
| 
 | ||||
|     let content = assert_matches!( | ||||
|         from_json_value::<RoomMessageEventContent>(json_data), | ||||
|         Ok(RoomMessageEventContent { | ||||
|             msgtype: MessageType::Text(content), | ||||
|             .. | ||||
|         }) => content | ||||
|     ); | ||||
|     assert_eq!(content.body, "test"); | ||||
|     let formatted = content.formatted.unwrap(); | ||||
|     assert_eq!(formatted.body, "<h1>test</h1>"); | ||||
|     let message = content.message.unwrap(); | ||||
|     assert_eq!(message.len(), 2); | ||||
|     assert_eq!(message[0].body, "<h1>test</h1>"); | ||||
|     assert_eq!(message[1].body, "test"); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn room_message_message_stable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "body": "test", | ||||
|         "formatted_body": "<h1>test</h1>", | ||||
| @ -344,7 +438,7 @@ fn room_message_html_text_stable_deserialization() { | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn room_message_html_text_unstable_deserialization() { | ||||
| fn room_message_message_unstable_deserialization() { | ||||
|     let json_data = json!({ | ||||
|         "body": "test", | ||||
|         "formatted_body": "<h1>test</h1>", | ||||
| @ -537,10 +631,8 @@ fn emote_event_serialization() { | ||||
|         to_json_value(&event).unwrap(), | ||||
|         json!({ | ||||
|             "content": { | ||||
|                 "org.matrix.msc1767.message": [ | ||||
|                     { "body": "is testing some <code>code</code>…", "mimetype": "text/html" }, | ||||
|                     { "body": "is testing some code…", "mimetype": "text/plain" }, | ||||
|                 ] | ||||
|                 "org.matrix.msc1767.html": "is testing some <code>code</code>…", | ||||
|                 "org.matrix.msc1767.text": "is testing some code…", | ||||
|             }, | ||||
|             "event_id": "$event:notareal.hs", | ||||
|             "origin_server_ts": 134_829_848, | ||||
|  | ||||
| @ -192,10 +192,8 @@ fn formatted_body_serialization() { | ||||
|             "msgtype": "m.text", | ||||
|             "format": "org.matrix.custom.html", | ||||
|             "formatted_body": "Hello, <em>World</em>!", | ||||
|             "org.matrix.msc1767.message": [ | ||||
|                 { "body": "Hello, <em>World</em>!", "mimetype": "text/html" }, | ||||
|                 { "body": "Hello, World!", "mimetype": "text/plain" }, | ||||
|             ], | ||||
|             "org.matrix.msc1767.html": "Hello, <em>World</em>!", | ||||
|             "org.matrix.msc1767.text": "Hello, World!", | ||||
|         }) | ||||
|     ); | ||||
| } | ||||
| @ -253,10 +251,8 @@ fn markdown_content_serialization() { | ||||
|             "formatted_body": "<p>Testing <strong>bold</strong> and <em>italic</em>!</p>\n", | ||||
|             "format": "org.matrix.custom.html", | ||||
|             "msgtype": "m.text", | ||||
|             "org.matrix.msc1767.message": [ | ||||
|                 { "body": "<p>Testing <strong>bold</strong> and <em>italic</em>!</p>\n", "mimetype": "text/html" }, | ||||
|                 { "body": "Testing **bold** and _italic_!", "mimetype": "text/plain" }, | ||||
|             ], | ||||
|             "org.matrix.msc1767.html": "<p>Testing <strong>bold</strong> and <em>italic</em>!</p>\n", | ||||
|             "org.matrix.msc1767.text": "Testing **bold** and _italic_!", | ||||
|         }) | ||||
|     ); | ||||
| 
 | ||||
| @ -306,10 +302,8 @@ fn markdown_content_serialization() { | ||||
|             "formatted_body": "<p>Testing</p>\n<p>Several</p>\n<p>Paragraphs.</p>\n", | ||||
|             "format": "org.matrix.custom.html", | ||||
|             "msgtype": "m.text", | ||||
|             "org.matrix.msc1767.message": [ | ||||
|                 { "body": "<p>Testing</p>\n<p>Several</p>\n<p>Paragraphs.</p>\n", "mimetype": "text/html" }, | ||||
|                 { "body": "Testing\n\nSeveral\n\nParagraphs.", "mimetype": "text/plain" }, | ||||
|             ], | ||||
|             "org.matrix.msc1767.html": "<p>Testing</p>\n<p>Several</p>\n<p>Paragraphs.</p>\n", | ||||
|             "org.matrix.msc1767.text": "Testing\n\nSeveral\n\nParagraphs.", | ||||
|         }) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| @ -154,10 +154,8 @@ fn event_serialization() { | ||||
|         to_json_value(&event).unwrap(), | ||||
|         json!({ | ||||
|             "content": { | ||||
|                 "org.matrix.msc1767.message": [ | ||||
|                     { "body": "Upload: <strong>my_lava_lamp.webm</strong>", "mimetype": "text/html"}, | ||||
|                     { "body": "Upload: my_lava_lamp.webm", "mimetype": "text/plain"}, | ||||
|                 ], | ||||
|                 "org.matrix.msc1767.html": "Upload: <strong>my_lava_lamp.webm</strong>", | ||||
|                 "org.matrix.msc1767.text": "Upload: my_lava_lamp.webm", | ||||
|                 "m.file": { | ||||
|                     "url": "mxc://notareal.hs/abcdef", | ||||
|                     "name": "my_lava_lamp.webm", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user