1use std::{
4 collections::{btree_map, BTreeMap},
5 ops::Deref,
6};
7
8use js_int::UInt;
9use ruma_common::OwnedEventId;
10use ruma_macros::EventContent;
11use serde::{Deserialize, Serialize};
12
13use crate::{message::TextContentBlock, relation::Reference};
14
15#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
29#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
30#[ruma_event(type = "m.poll.end", kind = MessageLike)]
31pub struct PollEndEventContent {
32 #[serde(rename = "m.text")]
34 pub text: TextContentBlock,
35
36 #[serde(rename = "m.poll.results", skip_serializing_if = "Option::is_none")]
38 pub poll_results: Option<PollResultsContentBlock>,
39
40 #[cfg(feature = "unstable-msc3955")]
42 #[serde(
43 default,
44 skip_serializing_if = "ruma_common::serde::is_default",
45 rename = "org.matrix.msc1767.automated"
46 )]
47 pub automated: bool,
48
49 #[serde(rename = "m.relates_to")]
51 pub relates_to: Reference,
52}
53
54impl PollEndEventContent {
55 pub fn new(text: TextContentBlock, poll_start_id: OwnedEventId) -> Self {
58 Self {
59 text,
60 poll_results: None,
61 #[cfg(feature = "unstable-msc3955")]
62 automated: false,
63 relates_to: Reference::new(poll_start_id),
64 }
65 }
66
67 pub fn with_plain_text(plain_text: impl Into<String>, poll_start_id: OwnedEventId) -> Self {
70 Self {
71 text: TextContentBlock::plain(plain_text),
72 poll_results: None,
73 #[cfg(feature = "unstable-msc3955")]
74 automated: false,
75 relates_to: Reference::new(poll_start_id),
76 }
77 }
78}
79
80#[derive(Clone, Debug, Default, Serialize, Deserialize)]
84#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
85pub struct PollResultsContentBlock(BTreeMap<String, UInt>);
86
87impl PollResultsContentBlock {
88 pub fn sorted(&self) -> Vec<(&str, UInt)> {
92 let mut sorted = self.0.iter().map(|(id, count)| (id.as_str(), *count)).collect::<Vec<_>>();
93 sorted.sort_by(|(_, a), (_, b)| b.cmp(a));
94 sorted
95 }
96}
97
98impl From<BTreeMap<String, UInt>> for PollResultsContentBlock {
99 fn from(value: BTreeMap<String, UInt>) -> Self {
100 Self(value)
101 }
102}
103
104impl IntoIterator for PollResultsContentBlock {
105 type Item = (String, UInt);
106 type IntoIter = btree_map::IntoIter<String, UInt>;
107
108 fn into_iter(self) -> Self::IntoIter {
109 self.0.into_iter()
110 }
111}
112
113impl FromIterator<(String, UInt)> for PollResultsContentBlock {
114 fn from_iter<T: IntoIterator<Item = (String, UInt)>>(iter: T) -> Self {
115 Self(BTreeMap::from_iter(iter))
116 }
117}
118
119impl Deref for PollResultsContentBlock {
120 type Target = BTreeMap<String, UInt>;
121
122 fn deref(&self) -> &Self::Target {
123 &self.0
124 }
125}