toby 0.1.3

A simple, opinionated Telegram bot library with structured command parsing
Documentation
use chrono::{DateTime, Utc};
use std::{future::Future, pin::Pin, sync::Arc};
use teloxide::prelude::*;

use super::command::{Command, parse_command};

#[derive(Debug, Clone)]
pub struct Msg {
    pub group_id: String,
    pub sender_username: Option<String>,
    pub ts: DateTime<Utc>,
    pub cmd: Command,
}

#[derive(Debug, Clone)]
pub struct ReplyMsg {
    pub text: String,
}

pub type HandlerFn = fn(&Msg) -> Pin<Box<dyn Future<Output = anyhow::Result<ReplyMsg>> + Send>>;

pub struct Toby {
    bot: Bot,
    handler: Arc<HandlerFn>,
}

impl Toby {
    pub fn new<TToken>(token: TToken, handler: HandlerFn) -> Self
    where
        TToken: Into<String>,
    {
        let bot = Bot::new(token);

        return Self {
            bot,
            handler: Arc::new(handler),
        };
    }

    pub async fn listen(self) {
        let hfn = self.handler.clone();

        teloxide::repl(self.bot, move |bot: Bot, msg: Message| {
            let hfn = hfn.clone();
            async move {
                dbg!(&msg);

                if let Some(text) = msg.text() {
                    dbg!(text);

                    if let Some(cmd) = parse_command(text) {
                        let msg_cmd = Msg {
                            group_id: msg.chat.id.to_string(),
                            sender_username: msg.from.as_ref().and_then(|a| a.username.clone()),
                            ts: msg.date,
                            cmd: cmd,
                        };

                        dbg!(&msg_cmd);

                        let reply = hfn(&msg_cmd).await;

                        match reply {
                            Ok(reply_msg) => {
                                dbg!(&reply_msg);
                                let _ = bot.send_message(msg.chat.id, reply_msg.text).await;
                            }
                            Err(e) => {
                                let _ = bot.send_message(msg.chat.id, e.to_string()).await;
                            }
                        }
                    }
                }

                Ok(())
            }
        })
        .await;
    }
}