mostro_client/cli/
send_msg.rs1use crate::cli::{Commands, Context};
2use crate::db::{Order, User};
3use crate::util::{send_dm, wait_for_dm};
4
5use anyhow::Result;
6use mostro_core::prelude::*;
7use nostr_sdk::prelude::*;
8use uuid::Uuid;
9
10pub async fn execute_send_msg(
11 command: Commands,
12 order_id: Option<Uuid>,
13 ctx: &Context,
14 text: Option<&str>,
15) -> Result<()> {
16 let requested_action = match command {
18 Commands::FiatSent { .. } => Action::FiatSent,
19 Commands::Release { .. } => Action::Release,
20 Commands::Cancel { .. } => Action::Cancel,
21 Commands::Dispute { .. } => Action::Dispute,
22 Commands::AdmCancel { .. } => Action::AdminCancel,
23 Commands::AdmSettle { .. } => Action::AdminSettle,
24 Commands::AdmAddSolver { .. } => Action::AdminAddSolver,
25 _ => {
26 return Err(anyhow::anyhow!("Invalid command for send msg"));
27 }
28 };
29
30 println!(
31 "Sending {} command for order {:?} to mostro pubId {}",
32 requested_action,
33 order_id.as_ref(),
34 &ctx.mostro_pubkey
35 );
36
37 let payload = match requested_action {
39 Action::FiatSent | Action::Release => create_next_trade_payload(ctx, &order_id).await?,
40 _ => text.map(|t| Payload::TextMessage(t.to_string())),
41 };
42 if let Some(Payload::NextTrade(_, trade_index)) = &payload {
44 match User::get(&ctx.pool).await {
46 Ok(mut user) => {
47 user.set_last_trade_index(*trade_index as i64);
48 if let Err(e) = user.save(&ctx.pool).await {
49 println!("Failed to update user: {}", e);
50 }
51 }
52 Err(e) => println!("Failed to get user: {}", e),
53 }
54 }
55
56 let request_id = Uuid::new_v4().as_u128() as u64;
58
59 let message = Message::new_order(order_id, Some(request_id), None, requested_action, payload);
61 let idkey = ctx.identity_keys.to_owned();
62
63 if let Some(order_id) = order_id {
64 let order = Order::get_by_id(&ctx.pool, &order_id.to_string()).await?;
65
66 if let Some(trade_keys_str) = order.trade_keys.clone() {
67 let trade_keys = Keys::parse(&trade_keys_str)?;
68 let subscription = Filter::new()
70 .pubkey(trade_keys.public_key())
71 .kind(nostr_sdk::Kind::GiftWrap)
72 .limit(0);
73
74 let opts =
75 SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::WaitForEvents(1));
76 ctx.client.subscribe(subscription, Some(opts)).await?;
78 let message_json = message
80 .as_json()
81 .map_err(|e| anyhow::anyhow!("Failed to serialize message: {e}"))?;
82 send_dm(
83 &ctx.client,
84 Some(&idkey),
85 &trade_keys,
86 &ctx.mostro_pubkey,
87 message_json,
88 None,
89 false,
90 )
91 .await
92 .map_err(|e| anyhow::anyhow!("Failed to send DM: {e}"))?;
93
94 wait_for_dm(
96 &ctx.client,
97 &trade_keys,
98 request_id,
99 None,
100 Some(order),
101 &ctx.pool,
102 )
103 .await
104 .map_err(|e| anyhow::anyhow!("Failed to wait for DM: {e}"))?;
105 }
106 }
107
108 Ok(())
109}
110
111async fn create_next_trade_payload(
112 ctx: &Context,
113 order_id: &Option<Uuid>,
114) -> Result<Option<Payload>> {
115 if let Some(order_id) = order_id {
116 let order = Order::get_by_id(&ctx.pool, &order_id.to_string()).await?;
117
118 if let (Some(_), Some(min_amount), Some(max_amount)) =
119 (order.is_mine, order.min_amount, order.max_amount)
120 {
121 if max_amount - order.fiat_amount >= min_amount {
122 let (trade_keys, trade_index) = User::get_next_trade_keys(&ctx.pool).await?;
123 return Ok(Some(Payload::NextTrade(
124 trade_keys.public_key().to_string(),
125 trade_index.try_into()?,
126 )));
127 }
128 }
129 }
130 Ok(None)
131}