codoseo_notify/
discord.rs1use codoseo_core::check::Severity;
5use serde_json::{Value, json};
6
7use crate::message::{AlertItem, AlertMessage, fit_lines, one_line, truncate};
8
9const DESCRIPTION_BUDGET: usize = 3900;
10
11fn emoji(s: Severity) -> &'static str {
12 match s {
13 Severity::Critical => ":red_circle:",
14 Severity::Warning => ":orange_circle:",
15 Severity::Notice => ":blue_circle:",
16 }
17}
18
19fn color(s: Severity) -> u32 {
20 match s {
21 Severity::Critical => 0xE5484D,
22 Severity::Warning => 0xF5A524,
23 Severity::Notice => 0x3E63DD,
24 }
25}
26
27fn line(item: &AlertItem) -> String {
28 let mut out = format!("{} **{}**", emoji(item.severity), item.kind_label);
29 if let Some(url) = &item.url {
30 out.push_str(&format!(" <{}>", url.replace('>', "%3E")));
32 }
33 let change = item.change_text();
34 if !change.is_empty() {
35 out.push_str(&format!(": {}", truncate(&one_line(&change), 80)));
36 }
37 truncate(&out, 300)
38}
39
40pub fn payload(msg: &AlertMessage) -> Value {
41 let lines: Vec<String> = msg.items.iter().map(line).collect();
42 let (mut description, left_out) = fit_lines(&lines, DESCRIPTION_BUDGET);
43 let more = msg.more as usize + left_out;
44 if more > 0 {
45 if !description.is_empty() {
46 description.push_str("\n\n");
47 }
48 description.push_str(&format!("and {more} more"));
49 }
50 let mut embed = json!({
51 "title": truncate(&msg.site_domain, 256),
52 "url": msg.site_url,
53 "color": color(msg.severity()),
54 });
55 if !description.is_empty() {
56 embed["description"] = Value::String(description);
57 }
58 json!({
59 "content": truncate(&msg.headline, 2000),
60 "allowed_mentions": {"parse": []},
62 "embeds": [embed],
63 })
64}