use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::models::OrderListing;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum WsEvent {
Connected,
Disconnected { reason: String },
Authenticated,
AuthenticationFailed { error: String },
OnlineCount {
connections: u64,
authorized: u64,
},
StatusUpdate {
status: UserStatus,
status_until: Option<DateTime<Utc>>,
activity: Option<Activity>,
},
SessionRevoked,
VerificationUpdate { ingame_name: String, verified: bool },
Banned {
until: DateTime<Utc>,
message: String,
},
Warned { message: String },
BanLifted,
WarningLifted,
OrderCreated { order: OrderListing },
OrderUpdated { order: OrderListing },
OrderRemoved { order_id: String },
Unknown {
route: String,
payload: serde_json::Value,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum UserStatus {
#[default]
Offline,
Online,
Ingame,
Invisible,
}
impl UserStatus {
pub fn is_available(&self) -> bool {
matches!(self, UserStatus::Online | UserStatus::Ingame)
}
}
impl std::fmt::Display for UserStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UserStatus::Offline => write!(f, "Offline"),
UserStatus::Online => write!(f, "Online"),
UserStatus::Ingame => write!(f, "In Game"),
UserStatus::Invisible => write!(f, "Invisible"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ActivityType {
#[default]
Unknown,
Idle,
OnMission,
InDojo,
InOrbiter,
InRelay,
}
impl std::fmt::Display for ActivityType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ActivityType::Unknown => write!(f, "Unknown"),
ActivityType::Idle => write!(f, "Idle"),
ActivityType::OnMission => write!(f, "On Mission"),
ActivityType::InDojo => write!(f, "In Dojo"),
ActivityType::InOrbiter => write!(f, "In Orbiter"),
ActivityType::InRelay => write!(f, "In Relay"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Activity {
#[serde(rename = "type")]
pub activity_type: ActivityType,
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<String>,
#[serde(rename = "startedAt", skip_serializing_if = "Option::is_none")]
pub started_at: Option<DateTime<Utc>>,
}
impl Activity {
pub fn new(activity_type: ActivityType) -> Self {
Self {
activity_type,
details: None,
started_at: None,
}
}
pub fn with_details(mut self, details: impl Into<String>) -> Self {
self.details = Some(details.into());
self
}
pub fn with_started_at(mut self, started_at: DateTime<Utc>) -> Self {
self.started_at = Some(started_at);
self
}
}