mostro_client/util/
events.rs1use anyhow::Result;
2use mostro_core::prelude::*;
3use nostr_sdk::prelude::*;
4
5use crate::db::User;
6use crate::parser::{parse_dispute_events, parse_dm_events, parse_orders_events};
7use crate::util::messaging::get_admin_keys;
8
9pub const FETCH_EVENTS_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(15);
10const FAKE_SINCE: i64 = 2880;
11
12use super::types::{Event, ListKind};
13
14fn create_fake_timestamp() -> Result<Timestamp> {
15 let fake_since_time = chrono::Utc::now()
16 .checked_sub_signed(chrono::Duration::minutes(FAKE_SINCE))
17 .ok_or(anyhow::anyhow!("Failed to get fake since time"))?
18 .timestamp() as u64;
19 Ok(Timestamp::from(fake_since_time))
20}
21
22fn create_seven_days_filter(letter: Alphabet, value: String, pubkey: PublicKey) -> Result<Filter> {
23 let since_time = chrono::Utc::now()
24 .checked_sub_signed(chrono::Duration::days(7))
25 .ok_or(anyhow::anyhow!("Failed to get since days ago"))?
26 .timestamp() as u64;
27 let timestamp = Timestamp::from(since_time);
28 Ok(Filter::new()
29 .author(pubkey)
30 .limit(50)
31 .since(timestamp)
32 .custom_tag(SingleLetterTag::lowercase(letter), value)
33 .kind(nostr_sdk::Kind::Custom(NOSTR_REPLACEABLE_EVENT_KIND)))
34}
35
36pub fn create_filter(
37 list_kind: ListKind,
38 pubkey: PublicKey,
39 since: Option<&i64>,
40) -> Result<Filter> {
41 match list_kind {
42 ListKind::Orders => create_seven_days_filter(Alphabet::Z, "order".to_string(), pubkey),
43 ListKind::Disputes => create_seven_days_filter(Alphabet::Z, "dispute".to_string(), pubkey),
44 ListKind::DirectMessagesAdmin | ListKind::DirectMessagesUser => {
45 let fake_timestamp = create_fake_timestamp()?;
46 Ok(Filter::new()
47 .kind(nostr_sdk::Kind::GiftWrap)
48 .pubkey(pubkey)
49 .since(fake_timestamp))
50 }
51 ListKind::PrivateDirectMessagesUser => {
52 let since = if let Some(mins) = since {
53 chrono::Utc::now()
54 .checked_sub_signed(chrono::Duration::minutes(*mins))
55 .unwrap()
56 .timestamp()
57 } else {
58 chrono::Utc::now()
59 .checked_sub_signed(chrono::Duration::minutes(30))
60 .unwrap()
61 .timestamp()
62 } as u64;
63 Ok(Filter::new()
64 .kind(nostr_sdk::Kind::PrivateDirectMessage)
65 .pubkey(pubkey)
66 .since(Timestamp::from(since)))
67 }
68 }
69}
70
71#[allow(clippy::too_many_arguments)]
72pub async fn fetch_events_list(
73 list_kind: ListKind,
74 status: Option<Status>,
75 currency: Option<String>,
76 kind: Option<mostro_core::order::Kind>,
77 ctx: &crate::cli::Context,
78 since: Option<&i64>,
79) -> Result<Vec<Event>> {
80 match list_kind {
81 ListKind::Orders => {
82 let filters = create_filter(list_kind, ctx.mostro_pubkey, None)?;
83 let fetched_events = ctx
84 .client
85 .fetch_events(filters, FETCH_EVENTS_TIMEOUT)
86 .await?;
87 let orders = parse_orders_events(fetched_events, currency, status, kind);
88 Ok(orders.into_iter().map(Event::SmallOrder).collect())
89 }
90 ListKind::DirectMessagesAdmin => {
91 let admin_keys = get_admin_keys(ctx)?;
93 let filters = create_filter(list_kind, admin_keys.public_key(), None)?;
95 let fetched_events = ctx
96 .client
97 .fetch_events(filters, FETCH_EVENTS_TIMEOUT)
98 .await?;
99 let direct_messages_mostro = parse_dm_events(fetched_events, admin_keys, since).await;
100 Ok(direct_messages_mostro
101 .into_iter()
102 .map(|(message, timestamp, sender_pubkey)| {
103 Event::MessageTuple(Box::new((message, timestamp, sender_pubkey)))
104 })
105 .collect())
106 }
107 ListKind::PrivateDirectMessagesUser => {
108 let mut direct_messages: Vec<(Message, u64, PublicKey)> = Vec::new();
109 for index in 1..=ctx.trade_index {
110 let trade_key = User::get_trade_keys(&ctx.pool, index).await?;
111 let filter = create_filter(
112 ListKind::PrivateDirectMessagesUser,
113 trade_key.public_key(),
114 None,
115 )?;
116 let fetched_user_messages = ctx
117 .client
118 .fetch_events(filter, FETCH_EVENTS_TIMEOUT)
119 .await?;
120 let direct_messages_for_trade_key =
121 parse_dm_events(fetched_user_messages, &trade_key, since).await;
122 direct_messages.extend(direct_messages_for_trade_key);
124 }
125 Ok(direct_messages
126 .into_iter()
127 .map(|t| Event::MessageTuple(Box::new(t)))
128 .collect())
129 }
130 ListKind::DirectMessagesUser => {
131 let mut direct_messages: Vec<(Message, u64, PublicKey)> = Vec::new();
132 for index in 1..=ctx.trade_index {
133 let trade_key = User::get_trade_keys(&ctx.pool, index).await?;
134 let filter =
135 create_filter(ListKind::DirectMessagesUser, trade_key.public_key(), None)?;
136 let fetched_user_messages = ctx
137 .client
138 .fetch_events(filter, FETCH_EVENTS_TIMEOUT)
139 .await?;
140 let direct_messages_for_trade_key =
141 parse_dm_events(fetched_user_messages, &trade_key, since).await;
142 direct_messages.extend(direct_messages_for_trade_key);
144 }
145 Ok(direct_messages
146 .into_iter()
147 .map(|t| Event::MessageTuple(Box::new(t)))
148 .collect())
149 }
150 ListKind::Disputes => {
151 let filters = create_filter(list_kind, ctx.mostro_pubkey, None)?;
152 let fetched_events = ctx
153 .client
154 .fetch_events(filters, FETCH_EVENTS_TIMEOUT)
155 .await?;
156 let disputes = parse_dispute_events(fetched_events);
157 Ok(disputes.into_iter().map(Event::Dispute).collect())
158 }
159 }
160}