mostro_client/parser/
disputes.rs

1use anyhow::Result;
2use chrono::DateTime;
3use comfy_table::presets::UTF8_FULL;
4use comfy_table::*;
5use log::info;
6use mostro_core::prelude::*;
7use nostr_sdk::prelude::*;
8
9use crate::parser::common::{apply_status_color, create_error_cell};
10use crate::util::Event;
11
12use crate::nip33::dispute_from_tags;
13
14pub fn parse_dispute_events(events: Events) -> Vec<Dispute> {
15    // Extracted Disputes List
16    let mut disputes_list = Vec::<Dispute>::new();
17
18    // Scan events to extract all disputes
19    for event in events.into_iter() {
20        if let Ok(mut dispute) = dispute_from_tags(event.tags) {
21            info!("Found Dispute id : {:?}", dispute.id);
22            // Get created at field from Nostr event
23            dispute.created_at = event.created_at.as_u64() as i64;
24            disputes_list.push(dispute.clone());
25        }
26    }
27
28    let buffer_dispute_list = disputes_list.clone();
29    // Order all element ( orders ) received to filter - discard disaligned messages
30    // if an order has an older message with the state we received is discarded for the latest one
31    disputes_list.retain(|keep| {
32        !buffer_dispute_list
33            .iter()
34            .any(|x| x.id == keep.id && x.created_at > keep.created_at)
35    });
36
37    // Sort by id to remove duplicates
38    disputes_list.sort_by(|a, b| b.id.cmp(&a.id));
39    disputes_list.dedup_by(|a, b| a.id == b.id);
40
41    // Finally sort list by creation time
42    disputes_list.sort_by(|a, b| b.created_at.cmp(&a.created_at));
43    disputes_list
44}
45
46pub fn print_disputes_table(disputes_table: Vec<Event>) -> Result<String> {
47    // Convert Event to Dispute
48    let disputes_table: Vec<Dispute> = disputes_table
49        .into_iter()
50        .filter_map(|event| {
51            if let Event::Dispute(dispute) = event {
52                Some(dispute)
53            } else {
54                None
55            }
56        })
57        .collect();
58
59    // Create table
60    let mut table = Table::new();
61    //Table rows
62    let mut rows: Vec<Row> = Vec::new();
63
64    if disputes_table.is_empty() {
65        table
66            .load_preset(UTF8_FULL)
67            .set_content_arrangement(ContentArrangement::Dynamic)
68            .set_width(160)
69            .set_header(vec![Cell::new("📭 No Disputes")
70                .add_attribute(Attribute::Bold)
71                .set_alignment(CellAlignment::Center)]);
72
73        // Single row for error
74        let mut r = Row::new();
75
76        r.add_cell(create_error_cell(
77            "No disputes found with requested parameters…",
78        ));
79
80        //Push single error row
81        rows.push(r);
82    } else {
83        table
84            .load_preset(UTF8_FULL)
85            .set_content_arrangement(ContentArrangement::Dynamic)
86            .set_width(160)
87            .set_header(vec![
88                Cell::new("🆔 Dispute Id")
89                    .add_attribute(Attribute::Bold)
90                    .set_alignment(CellAlignment::Center),
91                Cell::new("📊 Status")
92                    .add_attribute(Attribute::Bold)
93                    .set_alignment(CellAlignment::Center),
94                Cell::new("📅 Created")
95                    .add_attribute(Attribute::Bold)
96                    .set_alignment(CellAlignment::Center),
97            ]);
98
99        //Iterate to create table of orders
100        for single_dispute in disputes_table.into_iter() {
101            let date = DateTime::from_timestamp(single_dispute.created_at, 0);
102
103            let status_str = single_dispute.status.to_string();
104            let status_cell = apply_status_color(
105                Cell::new(&status_str).set_alignment(CellAlignment::Center),
106                &status_str,
107            );
108
109            let r = Row::from(vec![
110                Cell::new(single_dispute.id).set_alignment(CellAlignment::Center),
111                status_cell,
112                Cell::new(
113                    date.map(|d| d.to_string())
114                        .unwrap_or_else(|| "Invalid date".to_string()),
115                )
116                .set_alignment(CellAlignment::Center),
117            ]);
118            rows.push(r);
119        }
120    }
121
122    table.add_rows(rows);
123
124    Ok(table.to_string())
125}
126
127#[cfg(test)]
128mod tests {}