1use chrono::NaiveDateTime;
2use serde::{Deserialize, Serialize};
3use solana_sdk::pubkey::Pubkey;
4
5#[cfg(feature = "redis")]
6use redis_derive::{FromRedisValue, ToRedisArgs};
7
8#[derive(Serialize, Deserialize, Debug, Clone)]
10pub struct AuthResponse {
11 pub token: String,
12}
13
14#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
16pub struct SupplyResponse {
17 pub result: String,
18}
19
20#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
22pub struct ChatSendMessageResponse {
23 pub status: String,
24 pub message: String,
25}
26
27#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
28pub struct User {
29 pub authority: String,
30 pub username: String,
31 pub profile_photo_url: Option<String>,
32 pub discord_user: Option<DiscordUser>,
33 pub updated_at: NaiveDateTime,
34 pub risk_score: i64,
35 pub is_banned: bool,
36 pub role: Option<String>,
37}
38
39#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
41#[cfg_attr(feature = "redis", derive(FromRedisValue, ToRedisArgs))]
42pub struct ChatNotification {
43 pub authority: String,
44 pub username: String,
45 pub text: String,
46 pub id: u64,
47 pub ts: i64,
48 pub profile_photo_url: Option<String>,
49 pub role: Option<String>,
50 pub discord_user_id: Option<String>,
51 #[serde(default, skip_serializing_if = "Option::is_none")]
53 pub reply_to_id: Option<u64>,
54 #[serde(default, skip_serializing_if = "Option::is_none")]
55 pub reply_to_text: Option<String>,
56 #[serde(default, skip_serializing_if = "Option::is_none")]
57 pub reply_to_username: Option<String>,
58 #[serde(default, skip_serializing_if = "Option::is_none")]
60 pub reactions: Option<ChatReactions>,
61}
62
63#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
66#[cfg_attr(feature = "redis", derive(FromRedisValue, ToRedisArgs))]
67pub struct ChatReactions {
68 #[serde(default, skip_serializing_if = "is_zero")]
69 pub thumbs_up: u32, #[serde(default, skip_serializing_if = "is_zero")]
71 pub heart: u32, #[serde(default, skip_serializing_if = "is_zero")]
73 pub laughing: u32, #[serde(default, skip_serializing_if = "is_zero")]
75 pub surprised: u32, #[serde(default, skip_serializing_if = "is_zero")]
77 pub sad: u32, #[serde(default, skip_serializing_if = "is_zero")]
79 pub fire: u32, }
81
82fn is_zero(n: &u32) -> bool {
83 *n == 0
84}
85
86impl ChatReactions {
87 pub fn is_empty(&self) -> bool {
89 self.thumbs_up == 0
90 && self.heart == 0
91 && self.laughing == 0
92 && self.surprised == 0
93 && self.sad == 0
94 && self.fire == 0
95 }
96
97 pub fn get(&self, emoji: &str) -> u32 {
99 match emoji {
100 "👍" => self.thumbs_up,
101 "❤️" | "❤" => self.heart,
102 "😂" => self.laughing,
103 "😮" => self.surprised,
104 "😢" => self.sad,
105 "🔥" => self.fire,
106 _ => 0,
107 }
108 }
109
110 pub fn set(&mut self, emoji: &str, count: u32) {
112 match emoji {
113 "👍" => self.thumbs_up = count,
114 "❤️" | "❤" => self.heart = count,
115 "😂" => self.laughing = count,
116 "😮" => self.surprised = count,
117 "😢" => self.sad = count,
118 "🔥" => self.fire = count,
119 _ => {}
120 }
121 }
122}
123
124pub const ALLOWED_REACTION_EMOJI: [&str; 6] = ["👍", "❤️", "😂", "😮", "😢", "🔥"];
126
127pub fn is_valid_reaction_emoji(emoji: &str) -> bool {
129 if emoji == "❤" {
131 return true;
132 }
133 ALLOWED_REACTION_EMOJI.contains(&emoji)
134}
135
136#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
137pub struct ResetNotification {
138 pub block_id: u64,
139}
140
141#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
143#[cfg_attr(feature = "redis", derive(FromRedisValue, ToRedisArgs))]
144pub struct DeployNotification {
145 pub authority: String,
147 pub amount: u64,
149 pub mask: u64,
151 pub round_id: u64,
153 pub signer: String,
155 pub strategy: u64,
157 pub total_squares: u64,
159 pub ts: i64,
161 pub sig: String,
163}
164
165#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
167pub struct ReactionNotification {
168 pub message_id: u64,
169 pub emoji: String,
170 pub count: u32,
171 pub action: String, }
173
174#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
176pub struct TypingUser {
177 pub authority: String,
178 pub username: String,
179}
180
181#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
183pub struct TypingNotification {
184 pub users: Vec<TypingUser>,
185}
186
187#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
188pub enum Notification {
189 Chat(ChatNotification),
190 ChatBatch(Vec<ChatNotification>),
191 Reset(ResetNotification),
192 Deploy(DeployNotification),
193 Reaction(ReactionNotification),
194 Typing(TypingNotification),
195}
196
197impl Notification {
198 pub fn id(&self) -> String {
199 match self {
200 Notification::Chat(chat) => chat.id.to_string(),
201 Notification::ChatBatch(_) => "chat_batch".to_string(),
202 Notification::Reset(reset) => reset.block_id.to_string(),
203 Notification::Deploy(deploy) => deploy.sig.clone(),
204 Notification::Reaction(reaction) => {
205 format!("{}:{}", reaction.message_id, reaction.emoji)
206 }
207 Notification::Typing(_) => "typing".to_string(),
208 }
209 }
210}
211
212#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
214pub struct ChatReactResponse {
215 pub status: String,
216 pub action: String, pub message_id: u64,
218 pub emoji: String,
219 pub count: u32, }
221
222#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
224pub struct ChatTypingResponse {
225 pub status: String,
226}
227
228#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
230pub struct ChatHistoryResponse {
231 pub messages: Vec<ChatNotification>,
232 pub has_more: bool,
233 pub oldest_id: Option<u64>,
234}
235
236#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
237pub struct DailyRevenue {
238 pub day: String,
239 pub revenue: i64,
240}
241
242#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
245pub struct UsernameValidationResponse {
246 pub valid: bool,
247 pub error: Option<String>,
248}
249
250impl UsernameValidationResponse {
251 pub fn valid() -> Self {
252 Self {
253 valid: true,
254 error: None,
255 }
256 }
257
258 pub fn invalid(error: String) -> Self {
259 Self {
260 valid: false,
261 error: Some(error),
262 }
263 }
264}
265
266#[derive(Serialize, Deserialize, Debug, Clone)]
268pub struct DiscordAuthResponse {
269 pub access_token: String,
270}
271
272#[derive(Serialize, Deserialize, Debug, Clone)]
274pub struct GoogleUser {
275 pub email: String,
276 pub name: String,
277 pub picture: Option<String>,
278}
279
280#[derive(Serialize, Deserialize, Debug, Clone)]
282pub struct GoogleAuthResponse {
283 pub jwt: String,
284 pub user: GoogleUser,
285}
286
287#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
288pub struct DiscordUser {
289 pub id: String,
290 pub username: String,
291 pub discriminator: String,
292 #[serde(default, skip_serializing_if = "Option::is_none")]
293 pub global_name: Option<String>,
294 #[serde(default, skip_serializing_if = "Option::is_none")]
295 pub avatar: Option<String>,
296 #[serde(default, skip_serializing_if = "Option::is_none")]
297 pub verified: Option<bool>,
298 #[serde(default, skip_serializing_if = "Option::is_none")]
299 pub email: Option<String>,
300}
301
302#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
303pub struct OreBalance {
304 pub wallet: u64,
305 pub staked: u64,
306 pub unrefined: u64,
307 pub refined: u64,
308 pub lifetime_deployed_sol: u64,
309}
310
311#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
312pub struct LeaderboardEntry {
313 pub authority: String,
314 pub amount: u64,
315 pub username: Option<String>,
316 pub profile_picture_url: Option<String>,
317}
318
319#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
322pub struct ResetEventResponse {
323 pub disc: u8,
324 pub round_id: u64,
325 pub start_slot: u64,
326 pub end_slot: u64,
327 pub winning_square: u64,
328 pub top_miner: Pubkey,
329 pub num_winners: u64,
330 pub motherlode: u64,
331 pub total_deployed: u64,
332 pub total_vaulted: u64,
333 pub total_winnings: u64,
334 pub total_minted: u64,
335 pub ts: i64,
336 pub rng: u64,
337 pub deployed_winning_square: u64,
338 pub top_miner_username: Option<String>,
339 pub top_miner_profile_photo: Option<String>,
340}
341
342#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
344pub struct DeployHistoryEvent {
345 pub sig: String,
346 pub authority: String,
347 pub signer: String,
348 pub amount: u64,
349 pub mask: i64,
350 pub round_id: i64,
351 pub total_squares: i64,
352 pub ts: i64,
353 pub winning_square: i64,
354 pub top_miner: String,
355 pub rewards_sol: u64,
356 pub rewards_ore: u64,
357 pub total_winnings_sol: u64,
358 pub deployed_winning_square: u64,
359 pub motherlode: u64,
360}
361
362#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
364pub struct RoundWinner {
365 pub authority: String,
367 pub username: Option<String>,
369 pub profile_photo_url: Option<String>,
371 pub deployed_on_winning: u64,
373 pub combined_mask: u64,
375}
376
377#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
379pub struct RoundWinnersResponse {
380 pub round_id: u64,
382 pub winning_square: u64,
384 pub total_on_winning: u64,
386 pub total_winnings: u64,
388 pub winners: Vec<RoundWinner>,
390}