teamtalk 6.0.0

TeamTalk SDK for Rust
Documentation
use super::router::HandlerResult;
use super::{MemoryStateStore, Router, Scheduler, StateStore};
use crate::async_api::AsyncClient;
use crate::client::{EventData, Message};
use crate::events::{Event, Result};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

#[derive(Debug, Clone, Copy, Default)]
pub struct AsyncBotConfig;

pub struct AsyncBot {
    client: AsyncClient,
    router: Router,
    scheduler: Scheduler,
    state: Box<dyn StateStore>,
    stop: Arc<AtomicBool>,
    _config: AsyncBotConfig,
}

pub struct AsyncBotBuilder {
    client: AsyncClient,
    router: Router,
    scheduler: Scheduler,
    state: Box<dyn StateStore>,
    config: AsyncBotConfig,
}

impl AsyncBotBuilder {
    pub fn new(client: AsyncClient) -> Self {
        Self {
            client,
            router: Router::new(),
            scheduler: Scheduler::new(),
            state: Box::new(MemoryStateStore::new()),
            config: AsyncBotConfig,
        }
    }

    pub fn with_router(mut self, router: Router) -> Self {
        self.router = router;
        self
    }

    pub fn with_scheduler(mut self, scheduler: Scheduler) -> Self {
        self.scheduler = scheduler;
        self
    }

    pub fn with_state_store(mut self, store: impl StateStore + 'static) -> Self {
        self.state = Box::new(store);
        self
    }

    pub fn with_boxed_state_store(mut self, store: Box<dyn StateStore>) -> Self {
        self.state = store;
        self
    }

    pub fn with_config(mut self, config: AsyncBotConfig) -> Self {
        self.config = config;
        self
    }

    pub fn build(self) -> AsyncBot {
        AsyncBot {
            client: self.client,
            router: self.router,
            scheduler: self.scheduler,
            state: self.state,
            stop: Arc::new(AtomicBool::new(false)),
            _config: self.config,
        }
    }
}

impl AsyncBot {
    pub fn builder(client: AsyncClient) -> AsyncBotBuilder {
        AsyncBotBuilder::new(client)
    }

    pub fn stop_handle(&self) -> Arc<AtomicBool> {
        Arc::clone(&self.stop)
    }

    pub fn request_stop(&self) {
        self.stop.store(true, Ordering::Relaxed);
    }

    pub async fn run(&mut self) -> Result<()> {
        while !self.stop.load(Ordering::Relaxed) {
            let next = self.client.next_event().await;
            let Some((event, message)) = next else {
                break;
            };

            let outcome = self
                .client
                .with_client(|client| {
                    self.router
                        .dispatch(client, event, &message, self.state.as_mut())
                })
                .unwrap_or(Ok(HandlerResult::Continue))?;

            if matches!(outcome, HandlerResult::Stop) {
                self.request_stop();
            }

            if let Some(result) = self
                .client
                .with_client(|client| self.scheduler.tick(client, self.state.as_mut()))
            {
                result?;
            }
        }

        Ok(())
    }

    pub fn client_mut(&mut self) -> &mut AsyncClient {
        &mut self.client
    }

    pub async fn wait_for_event(&mut self, event: Event) -> Option<Message> {
        self.client.wait_for_event(event).await
    }

    pub async fn wait_for_predicate<F>(&mut self, predicate: F) -> Option<(Event, Message)>
    where
        F: FnMut(Event, &Message) -> bool,
    {
        self.client.wait_for_predicate(predicate).await
    }

    pub async fn wait_for_data(&mut self) -> Option<(Event, Message, EventData)> {
        self.client.wait_for_data().await
    }

    #[cfg(feature = "async-tokio")]
    pub async fn wait_for_event_timeout(
        &mut self,
        event: Event,
        timeout: std::time::Duration,
    ) -> Option<Message> {
        self.client.wait_for_event_timeout(event, timeout).await
    }

    #[cfg(feature = "async-tokio")]
    pub async fn wait_for_data_timeout(
        &mut self,
        timeout: std::time::Duration,
    ) -> Option<(Event, Message, EventData)> {
        self.client.wait_for_data_timeout(timeout).await
    }
}