watchbird_api 0.2.2-rc.0

A self-hosted and API-driven uptime monitor
Documentation
use std::fmt::Display;

use aide::OperationIo;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use uuid::Uuid;

use crate::v1alpha1::Url;

pub type AlertId = Uuid;

/// An alert is an event triggered if something important happens in a watch.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, OperationIo)]
#[serde(rename_all = "camelCase")]
pub struct Alert {
    pub id: AlertId,
    /// User-readable identifier
    pub name: String,
    /// Unique identifier of this alerts owner. Will fire for watches with the same owner. Cannot be updated
    pub owner_ref: String,
    pub config: AlertConfig,
    pub status: AlertStatus,
}
impl Display for Alert {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} - {}", self.name, self.config.provider)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct CreateAlert {
    /// User-readable identifier
    pub name: String,
    /// Unique identifier of this alerts owner. Will fire for watches with the same owner. Cannot be updated
    pub owner_ref: String,
    pub config: AlertConfig,
}
impl From<Alert> for CreateAlert {
    fn from(value: Alert) -> Self {
        CreateAlert {
            name: value.name,
            owner_ref: value.owner_ref,
            config: value.config,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct AlertConfig {
    /// Type of provider that this alert connects to
    pub provider: Provider,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, Default)]
#[serde(rename_all = "camelCase")]
pub struct AlertStatus {}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub enum Provider {
    Discord(Discord),
    Webhook(Webhook),
}
impl Display for Provider {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Provider::Discord(_) => "Discord",
                Provider::Webhook(_) => "Webhook",
            }
        )
    }
}

/// A discord Webhook sending messages to a channel
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct Discord {
    /// Full URL of the webhook
    pub webhook_url: Url,
}

/// A generic webhook implementation for sending alerts to services which have no dedicated provider.
/// This provider should only be used if your service does not have a provider of if you need its templating capabilities.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct Webhook {
    /// Full URL of the webhook
    pub url: Url,
    /// JSON payload template to send to the webhook.
    /// Expects a string that must parse to a valid JSON Value
    /// Templating happens by fixed string replacement.
    /// The following strings will be replaced in any string that contains them in the payload:
    ///
    /// - `<watch_id>`: ID of the watch this update is for
    /// - `<watch_name>`: Name of the watch this update is for
    /// - `<watch_status>`: What happened, failing, recovering, fixed, etc.
    /// - `<failing_probes>`: For failing and recovering messages, newline-separated list of failing probes
    /// - `<recovered_probe>`: For recovering messages only, wich probe has recovered
    /// - `<failing_watches>`: newline-separated list of failing watch names, if any
    ///
    /// Example:
    /// ```rust
    /// # use std::str::FromStr;
    /// # use watchbird_api::v1alpha1::*;
    ///
    /// let payload = "{\"title\": \"Alert\", \"message\": \"<update_kind> for <watch>: <update_msg>\"}".to_string();
    /// let webhook = Webhook {
    ///   url: Url::from_str("https://webhook-host/path").unwrap(),
    ///   payload,
    /// };
    /// ```
    pub payload: String,
}