tablo_test/protocol/
bell.rs1use super::dom::{attr_value, strip_text, tags_where};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Bell {
10 pub unread: u64,
12 pub notifications: Vec<BellNotification>,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct BellNotification {
19 pub id: String,
21 pub title: String,
22 pub read: bool,
23 pub status: String,
25 pub actions: Vec<(String, String)>,
27}
28
29pub fn bell(html: &str) -> Option<Bell> {
31 let trigger = tags_where(html, |tag, attrs| {
32 tag == "button"
33 && attr_value(attrs, "aria-controls").as_deref() == Some("tablo-notifications")
34 });
35 if trigger.is_empty() {
36 return None;
37 }
38 let unread = tags_where(html, |tag, attrs| {
39 tag == "span" && attr_value(attrs, "data-unread").is_some()
40 })
41 .first()
42 .and_then(|(_, attrs, _)| attr_value(attrs, "data-unread")?.parse().ok())
43 .unwrap_or(0);
44 let notifications = tags_where(html, |tag, attrs| {
45 tag == "li" && attr_value(attrs, "data-notification").is_some()
46 })
47 .into_iter()
48 .map(|(_, attrs, inner)| BellNotification {
49 id: attr_value(&attrs, "data-notification").unwrap_or_default(),
50 title: tags_where(&inner, |tag, _| tag == "p")
51 .first()
52 .map(|(_, _, text)| strip_text(text))
53 .unwrap_or_default(),
54 read: attr_value(&attrs, "data-read").as_deref() == Some("true"),
55 status: attr_value(&attrs, "data-type").unwrap_or_default(),
56 actions: tags_where(&inner, |tag, _| tag == "a")
57 .into_iter()
58 .map(|(_, attrs, text)| {
59 (
60 strip_text(&text),
61 attr_value(&attrs, "href").unwrap_or_default(),
62 )
63 })
64 .collect(),
65 })
66 .collect();
67 Some(Bell {
68 unread,
69 notifications,
70 })
71}