aboutsummaryrefslogblamecommitdiffstats
path: root/filamento/src/logic/mod.rs
blob: 365a0dfe9197347004e14960d05b813963250793 (plain) (tree)
1
2
3
4
5
6
7
8




                                           
                                 
 
                                                                  










                        
                   






                                                                                     
                       







                                                                                         
                   


         



                                     










                                                                                                  
















                                                                       

















                                                                      

                                                                                                    
















                                                                                      



                                                                             
 
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<Mutex<HashMap<String, oneshot::Sender<Result<Stanza, ReadError>>>>>,
    update_sender: mpsc::Sender<UpdateMessage>,
}

impl ClientLogic {
    pub fn new(
        client: Client,
        db: Db,
        pending: Arc<Mutex<HashMap<String, oneshot::Sender<Result<Stanza, ReadError>>>>>,
        update_sender: mpsc::Sender<UpdateMessage>,
    ) -> 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<HashMap<String, oneshot::Sender<Result<Stanza, ReadError>>>> {
        &self.pending.as_ref()
    }

    pub fn update_sender(&self) -> &mpsc::Sender<UpdateMessage> {
        &self.update_sender
    }

    pub async fn handle_unsupported(&self, stanza: impl Into<Stanza>) {
        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;
    }
}