Skip to main content

chipa_webhooks/
hints.rs

1use serde_json::{Map, Value};
2
3pub struct WithHints {
4    pub(crate) map: Map<String, Value>,
5}
6
7impl WithHints {
8    pub fn new() -> Self {
9        Self { map: Map::new() }
10    }
11
12    pub fn d_color(mut self, color: u32) -> Self {
13        self.map
14            .insert("__d_color".to_owned(), Value::Number(color.into()));
15        self
16    }
17
18    pub fn d_title(mut self, title: impl Into<String>) -> Self {
19        self.map
20            .insert("__d_title".to_owned(), Value::String(title.into()));
21        self
22    }
23
24    pub fn tg_silent(mut self) -> Self {
25        self.map.insert("__tg_silent".to_owned(), Value::Bool(true));
26        self
27    }
28
29    pub fn tg_disable_preview(mut self) -> Self {
30        self.map
31            .insert("__tg_disable_preview".to_owned(), Value::Bool(true));
32        self
33    }
34
35    pub fn slack_username(mut self, username: impl Into<String>) -> Self {
36        self.map.insert(
37            "__slack_username".to_owned(),
38            Value::String(username.into()),
39        );
40        self
41    }
42
43    pub fn slack_emoji(mut self, emoji: impl Into<String>) -> Self {
44        self.map
45            .insert("__slack_emoji".to_owned(), Value::String(emoji.into()));
46        self
47    }
48
49    pub fn ntfy_title(mut self, title: impl Into<String>) -> Self {
50        self.map
51            .insert("__ntfy_title".to_owned(), Value::String(title.into()));
52        self
53    }
54
55    /// Priority: 1 (min) to 5 (max).
56    pub fn ntfy_priority(mut self, priority: u8) -> Self {
57        self.map.insert(
58            "__ntfy_priority".to_owned(),
59            Value::Number(priority.clamp(1, 5).into()),
60        );
61        self
62    }
63
64    /// Comma-separated tags, e.g. `"trading,alert,btc"`.
65    pub fn ntfy_tags(mut self, tags: impl Into<String>) -> Self {
66        self.map
67            .insert("__ntfy_tags".to_owned(), Value::String(tags.into()));
68        self
69    }
70}
71
72impl Default for WithHints {
73    fn default() -> Self {
74        Self::new()
75    }
76}
77
78/// Extracts and removes all `__`-prefixed hint keys from a Value::Object.
79/// Returns the hints as a separate map. Non-object values return empty hints.
80pub fn extract_hints(value: &mut Value) -> Map<String, Value> {
81    let Some(map) = value.as_object_mut() else {
82        return Map::new();
83    };
84
85    let hint_keys: Vec<String> = map
86        .keys()
87        .filter(|k| k.starts_with("__"))
88        .cloned()
89        .collect();
90
91    let mut hints = Map::new();
92    for key in hint_keys {
93        if let Some(v) = map.remove(&key) {
94            hints.insert(key, v);
95        }
96    }
97
98    hints
99}