ironnotify-rust/src/types.rs

210 lines
5.8 KiB
Rust

//! Type definitions for IronNotify SDK.
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Severity level for notifications.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum SeverityLevel {
#[default]
Info,
Success,
Warning,
Error,
Critical,
}
impl std::fmt::Display for SeverityLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Info => "info",
Self::Success => "success",
Self::Warning => "warning",
Self::Error => "error",
Self::Critical => "critical",
};
write!(f, "{}", s)
}
}
/// WebSocket connection state.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ConnectionState {
#[default]
Disconnected,
Connecting,
Connected,
Reconnecting,
}
impl std::fmt::Display for ConnectionState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Disconnected => "disconnected",
Self::Connecting => "connecting",
Self::Connected => "connected",
Self::Reconnecting => "reconnecting",
};
write!(f, "{}", s)
}
}
/// Action button on a notification.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NotificationAction {
pub label: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub action: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub style: Option<String>,
}
impl NotificationAction {
/// Creates a new action with just a label.
pub fn new(label: impl Into<String>) -> Self {
Self {
label: label.into(),
url: None,
action: None,
style: Some("default".to_string()),
}
}
/// Creates an action with a URL.
pub fn with_url(label: impl Into<String>, url: impl Into<String>) -> Self {
Self {
label: label.into(),
url: Some(url.into()),
action: None,
style: Some("default".to_string()),
}
}
/// Creates an action with an action handler.
pub fn with_handler(label: impl Into<String>, action: impl Into<String>) -> Self {
Self {
label: label.into(),
url: None,
action: Some(action.into()),
style: Some("default".to_string()),
}
}
/// Sets the style.
pub fn style(mut self, style: impl Into<String>) -> Self {
self.style = Some(style.into());
self
}
}
/// Payload for creating a notification.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NotificationPayload {
pub event_type: String,
pub title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub severity: Option<SeverityLevel>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub actions: Option<Vec<NotificationAction>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub group_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deduplication_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_at: Option<DateTime<Utc>>,
}
impl NotificationPayload {
/// Creates a new notification payload.
pub fn new(event_type: impl Into<String>, title: impl Into<String>) -> Self {
Self {
event_type: event_type.into(),
title: title.into(),
message: None,
severity: Some(SeverityLevel::Info),
metadata: None,
actions: None,
user_id: None,
group_key: None,
deduplication_key: None,
expires_at: None,
}
}
}
/// A notification received from the server.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Notification {
pub id: String,
pub event_type: String,
pub title: String,
#[serde(default)]
pub message: Option<String>,
pub severity: SeverityLevel,
#[serde(default)]
pub metadata: Option<HashMap<String, serde_json::Value>>,
#[serde(default)]
pub actions: Option<Vec<NotificationAction>>,
#[serde(default)]
pub user_id: Option<String>,
#[serde(default)]
pub group_key: Option<String>,
pub read: bool,
pub created_at: DateTime<Utc>,
#[serde(default)]
pub expires_at: Option<DateTime<Utc>>,
}
/// Result of sending a notification.
#[derive(Debug, Clone)]
pub struct SendResult {
pub success: bool,
pub notification_id: Option<String>,
pub error: Option<String>,
pub queued: bool,
}
impl SendResult {
/// Creates a success result.
pub fn success(notification_id: Option<String>) -> Self {
Self {
success: true,
notification_id,
error: None,
queued: false,
}
}
/// Creates a failure result.
pub fn failure(error: impl Into<String>) -> Self {
Self {
success: false,
notification_id: None,
error: Some(error.into()),
queued: false,
}
}
/// Creates a queued result.
pub fn queued(error: impl Into<String>) -> Self {
Self {
success: false,
notification_id: None,
error: Some(error.into()),
queued: true,
}
}
}