filthy_rich/types/
payloads.rs1use serde::{Deserialize, Serialize, ser::SerializeStruct};
5
6use crate::{
7 ds,
8 errors::InnerParsingError,
9 types::{ActivitySpec, ActivityType, StatusDisplayType},
10 utils::get_current_timestamp,
11};
12
13#[derive(Debug, Deserialize, Clone)]
16pub struct AssetsPayload {
17 pub(crate) large_image: Option<String>,
18 pub(crate) large_url: Option<String>,
19 pub(crate) large_text: Option<String>,
20 pub(crate) small_image: Option<String>,
21 pub(crate) small_text: Option<String>,
22 pub(crate) small_url: Option<String>,
23}
24
25impl AssetsPayload {
26 ds!(large_image, "The key for the large image.");
27 ds!(large_url, "The URL for the large image.");
28 ds!(large_text, "The hover text for the large image.");
29 ds!(small_image, "The key for the small image.");
30 ds!(small_url, "The URL for the small image.");
31 ds!(small_text, "The hover text for the small image.");
32}
33
34impl Serialize for AssetsPayload {
36 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
37 where
38 S: serde::Serializer,
39 {
40 let mut state = serializer.serialize_struct("AssetsPayload", 6)?;
41
42 if let Some(v) = &self.large_image {
43 state.serialize_field("large_image", v)?;
44
45 if let Some(v) = &self.large_text {
46 state.serialize_field("large_text", v)?;
47 }
48 if let Some(v) = &self.large_url {
49 state.serialize_field("large_url", v)?;
50 }
51 }
52
53 if let Some(v) = &self.small_image {
54 state.serialize_field("small_image", v)?;
55
56 if let Some(v) = &self.small_text {
57 state.serialize_field("small_text", v)?;
58 }
59 if let Some(v) = &self.small_url {
60 state.serialize_field("small_url", v)?;
61 }
62 }
63
64 state.end()
65 }
66}
67
68#[derive(Debug, Serialize, Deserialize, Clone)]
70pub struct ButtonPayload {
71 pub(crate) label: String,
72 pub(crate) url: String,
73}
74
75impl ButtonPayload {
76 #[must_use]
78 pub fn label(&self) -> &str {
79 self.label.as_ref()
80 }
81 #[must_use]
83 pub fn url(&self) -> &str {
84 self.url.as_str()
85 }
86}
87
88#[derive(Debug, Serialize, Deserialize, Clone)]
90pub struct TimestampPayload {
91 start: u64,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 end: Option<u64>,
94}
95
96impl TimestampPayload {
97 #[must_use]
99 pub fn start(&self) -> u64 {
100 self.start
101 }
102 #[must_use]
104 pub fn end(&self) -> Option<u64> {
105 self.end
106 }
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct ActivityPayload {
112 #[serde(skip_serializing_if = "Option::is_none")]
113 name: Option<String>,
114 #[serde(skip_serializing_if = "Option::is_none")]
115 r#type: Option<ActivityType>,
116 created_at: u64,
117 #[serde(skip_serializing_if = "Option::is_none")]
118 instance: Option<bool>,
119 #[serde(skip_serializing_if = "Option::is_none")]
120 status_display_type: Option<StatusDisplayType>,
121 #[serde(skip_serializing_if = "Option::is_none")]
122 details: Option<String>,
123 #[serde(skip_serializing_if = "Option::is_none")]
124 details_url: Option<String>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 state: Option<String>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 state_url: Option<String>,
129 timestamps: TimestampPayload,
130 #[serde(skip_serializing_if = "Option::is_none")]
131 assets: Option<AssetsPayload>,
132 #[serde(skip_serializing_if = "Option::is_none")]
133 buttons: Option<Vec<ButtonPayload>>,
134}
135
136impl ActivityPayload {
137 ds!(name, "The name for the activity.");
138
139 #[must_use]
141 pub fn activity_type(&self) -> Option<ActivityType> {
142 self.r#type
143 }
144 #[must_use]
146 pub fn created_at(&self) -> u64 {
147 self.created_at
148 }
149 #[must_use]
151 pub fn instance(&self) -> Option<bool> {
152 self.instance
153 }
154 #[must_use]
156 pub fn status_display_type(&self) -> Option<StatusDisplayType> {
157 self.status_display_type
158 }
159
160 ds!(details, "The details (top text) for the activity.");
161 ds!(
162 details_url,
163 "The URL which the details field redirects to when clicked on."
164 );
165 ds!(
166 state,
167 "The state (usually the bottom text but could be on top) for the activity."
168 );
169 ds!(
170 state_url,
171 "The URL which the state redirects to when clicked on."
172 );
173
174 #[must_use]
176 pub fn timestamps(&self) -> &TimestampPayload {
177 &self.timestamps
178 }
179 #[must_use]
182 pub fn assets(&self) -> Option<&AssetsPayload> {
183 self.assets.as_ref()
184 }
185 #[must_use]
188 pub fn buttons(&self) -> Option<&Vec<ButtonPayload>> {
189 self.buttons.as_ref()
190 }
191
192 pub(crate) fn create(
193 value: ActivitySpec,
194 session_start: u64,
195 ) -> Result<Self, InnerParsingError> {
196 let current_t = get_current_timestamp()?;
197 let end_timestamp = value.duration.map(|d| current_t + d.as_secs());
198
199 Ok(Self {
200 name: value.name,
201 r#type: value.r#type,
202 created_at: current_t,
203 instance: value.instance,
204 status_display_type: value.status_display_type,
205 details: value.details,
206 details_url: value.details_url,
207 state: value.state,
208 state_url: value.state_url,
209 timestamps: TimestampPayload {
210 start: session_start,
211 end: end_timestamp,
212 },
213 assets: value.assets,
214 buttons: value.buttons,
215 })
216 }
217}