use std::{collections::HashMap, sync::Arc}; use lampada::{Logic, error::ReadError}; use stanza::client::Stanza; use tokio::sync::{Mutex, mpsc, oneshot}; use tracing::{error, info, warn}; use crate::{Client, Command, UpdateMessage, db::Db, error::Error}; mod abort; mod connect; mod connection_error; mod disconnect; mod offline; mod online; mod process_stanza; #[derive(Clone)] pub struct ClientLogic { client: Client, db: Db, pending: Arc>>>>, update_sender: mpsc::Sender, } impl ClientLogic { pub fn new( client: Client, db: Db, pending: Arc>>>>, update_sender: mpsc::Sender, ) -> Self { Self { db, pending, update_sender, client, } } pub fn client(&self) -> &Client { &self.client } pub fn db(&self) -> &Db { &self.db } pub fn pending(&self) -> &Mutex>>> { &self.pending.as_ref() } pub fn update_sender(&self) -> &mpsc::Sender { &self.update_sender } pub async fn handle_unsupported(&self, stanza: impl Into) { let stanza: Stanza = stanza.into(); warn!("received unsupported stanza: {:?}", stanza); self.handle_update(UpdateMessage::Unsupported(stanza)).await; } pub async fn handle_update(&self, update: UpdateMessage) { // TODO: impl fmt info!("{:?}", update); self.update_sender().send(update).await; } pub async fn handle_error(&self, e: Error) { error!("{}", e); self.handle_update(UpdateMessage::Error(e)).await; } } impl Logic for ClientLogic { type Cmd = Command; // pub async fn handle_stream_error(self, error) {} // stanza errors (recoverable) // pub async fn handle_error(self, error: Error) {} // when it aborts, must clear iq map no matter what async fn handle_connect(self, connection: lampada::Connected) { connect::handle_connect(self, connection).await; } async fn handle_disconnect(self, connection: lampada::Connected) { disconnect::handle_disconnect(self, connection).await; } async fn handle_stanza(self, stanza: ::stanza::client::Stanza, connection: lampada::Connected) { process_stanza::handle_stanza(self, stanza, connection).await; } async fn handle_online(self, command: Self::Cmd, connection: lampada::Connected) { online::handle_online(self, command, connection).await; } async fn handle_offline(self, command: Self::Cmd) { offline::handle_offline(self, command).await; } async fn on_abort(self) { abort::on_abort(self).await; } async fn handle_connection_error(self, error: lampada::error::ConnectionError) { connection_error::handle_connection_error(self, error).await; } async fn handle_stream_error(self, stream_error: stanza::stream::Error) { self.handle_error(Error::Stream(stream_error)).await; } }