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