1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
use std::cmp::Ordering;
use std::fmt::Debug;
use message::formatted_detail::FormattedMessageDetail;
use serde::{Serialize, Deserialize};
use crate::message;
use crate::message::author::Author;
use crate::message::component::Component;
pub mod formatted_detail;
pub mod author;
pub mod component;
pub mod builder;
pub mod detail_builder;
/// A Message represents a [`MessageDestination`] independent way to send a message to a platform.
/// **However** - not every destination will support every type of formatting, or may have length / size
/// restrictions - so be aware of this. Destinations should do their best to receive the message, even if they
/// have to ignore formatting to do so.
///
/// To construct a Message, consider using [`MessageBuilder`] or [`MessageDetailBuilder`] to make
/// your life easier.
///
/// # Parts of a Message #
/// - [Level] - Severity of message
/// - Title - Optional, short snappy summary of what the message is about
/// - [MessageDetail] - Structured body text supporting formatting
/// - [Component] - Optional, indicating what the message is about, e.g a program or server.
/// - [Author] - Who created the message
/// - Timestamp - The unix timestamp in milliseconds, showing when the message was sent.
///
/// [`MessageDestination`]: crate::destination::MessageDestination
/// [`MessageBuilder`]: builder::MessageBuilder
/// [`MessageDetailBuilder`]: detail_builder::MessageDetailBuilder
#[derive(Debug, Clone, PartialEq)]
pub struct Message {
level: Level,
title: Option<String>,
message_detail: MessageDetail,
component: Option<Component>,
author: Author,
unix_timestamp_millis: i64,
}
impl Message {
pub fn new(level: Level, title: Option<String>,
message_detail: MessageDetail, component: Option<Component>,
author: Author, unix_timestamp_millis: i64,
) -> Self {
Self {
level,
title,
message_detail,
component,
author,
unix_timestamp_millis
}
}
pub fn get_level(&self) -> &Level {
&self.level
}
pub fn get_title(&self) -> &Option<String> {
&self.title
}
pub fn get_message_detail(&self) -> &MessageDetail {
&self.message_detail
}
pub fn get_unix_timestamp_millis(&self) -> i64 {
self.unix_timestamp_millis
}
pub fn get_author(&self) -> &Author {
&self.author
}
pub fn get_component(&self) -> &Option<Component> {
&self.component
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum MessageDetail {
Raw(String),
Formatted(FormattedMessageDetail),
}
impl MessageDetail {
pub fn raw(&self) -> &str {
match &self {
MessageDetail::Raw(raw) => raw,
MessageDetail::Formatted(formatted) => formatted.raw()
}
}
pub fn has_formatting(&self) -> bool {
matches!(&self, MessageDetail::Formatted(_))
}
}
impl Default for MessageDetail {
fn default() -> Self {
Self::Raw(String::new())
}
}
/// The level / severity of the [Message]. This can be thought of as the log level.
/// This is used in conjunction to [Component] to indicate how a message should be
/// routed.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "binary", derive(clap::ArgEnum))]
pub enum Level {
/// Indicates an informational message when everything is working properly.
/// # Examples #
/// - A job has completed successfully, e.g a backup
/// - A daily status update to confirm that everything is running correctly.
Info,
/// Used when something unexpected occurs that could be the source of an error,
/// but requires the user to check whether it is actually an issue.
///
/// # Examples #
/// - A job took longer than normal
/// - A job failed that fails fairly regularly, but will presumably sort itself out soon.
Warn,
/// Indicates a failure has occurred.
///
/// # Examples #
/// - A program crashed / had a non-zero exit code
/// - A monitoring program detected that another program has not completed its job
/// - Possibly indicating the program is not running
/// - Or the program is malfunctioning
/// - A program restarted in attempt to recover itself, but is expected to recover safely
Error,
/// Indicates a failure in the notifications own configuration / workings.
///
/// # Examples #
/// - Sent by [`MessageRouter`] to [`Root`] level [`MessageDestination`]s when a message
/// cannot be sent to one or more destinations (e.g. network failure, invalid tokens)
///
/// [`Root`]: crate::destination::routed_destination::MessageRoutingBehaviour::Root
/// [`MessageDestination`]: crate::destination::MessageDestination
/// [`MessageRouter`]: crate::message_router::MessageRouter
SelfError,
}
impl Default for Level {
fn default() -> Self {
Self::Info
}
}
impl Level {
pub(crate) fn get_priority(&self) -> u32 {
match &self {
Self::Info => 1,
Self::Warn => 3,
Self::Error => 4,
Self::SelfError => 5,
}
}
/// Gets the least severe [Level]
pub fn min() -> Level {
Level::Info
}
/// Gets the most severe [Level]
pub fn max() -> Level {
Level::SelfError
}
}
impl PartialOrd<Self> for Level {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Level {
fn cmp(&self, other: &Self) -> Ordering {
self.get_priority().cmp(&other.get_priority())
}
}