1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
use std::{cmp::max, collections::HashMap, sync::Arc};
use crate::{
Action, ChatAction, ChatEvent, ChatHandler, GetUpdatesRequest, MessageEvent, TelegramClient,
UpdateEvent, API,
};
// Handler routing:
// - by chat ID
// - by user
// - by message type
// - by message text regex
//
// create filtering functions for each of these, and then compose them together
pub struct Router<R, S, T>
where
R: Into<Action<ChatAction>>,
T: TelegramClient,
{
api: Arc<API<T>>,
chat_handlers: Vec<ChatHandler<R, S, T>>,
chat_state: HashMap<i64, S>,
}
impl<R: Into<Action<ChatAction>>, S: Clone, T: TelegramClient> Router<R, S, T> {
pub fn new(client: T) -> Self {
Self {
api: Arc::new(API::new(client)),
chat_handlers: vec![],
chat_state: HashMap::new(),
}
}
pub fn add_chat_handler(&mut self, h: ChatHandler<R, S, T>) {
self.chat_handlers.push(h)
}
pub async fn handle_action(&self, chat_id: i64, action: ChatAction) -> anyhow::Result<()> {
match action {
ChatAction::ReplyText(text) => {
self.api
.send_message(&crate::SendMessageRequest {
chat_id,
text,
reply_to_message_id: None,
})
.await?;
}
ChatAction::ReplySticker(sticker) => {
self.api
.send_sticker(&crate::SendStickerRequest::new(chat_id, sticker))
.await?;
}
ChatAction::None => {}
}
Ok(())
}
pub async fn start(&mut self) {
let mut last_update_id = 0;
loop {
debug!("last_update_id = {}", last_update_id);
let updates = self
.api
.get_update_events(
&GetUpdatesRequest::new()
.with_timeout(60)
.with_offset(last_update_id + 1),
)
.await
.unwrap();
for update in updates {
match update {
UpdateEvent::NewMessage(id, message) => {
last_update_id = max(last_update_id, id);
let chat_id = message.chat.id;
for handler in &self.chat_handlers {
let state = self
.chat_state
.entry(chat_id)
.or_insert(handler.state.clone());
let reply = (handler.f)(
ChatEvent {
api: Arc::clone(&self.api),
message: MessageEvent::New(message.clone()),
},
state.clone(),
)
.await
.unwrap();
match reply.into() {
Action::Next(ChatAction::None) => {}
Action::Done(ChatAction::None) => {
break;
}
Action::Next(action) => {
self.handle_action(chat_id, action).await.unwrap();
}
Action::Done(action) => {
self.handle_action(chat_id, action).await.unwrap();
break;
}
}
}
}
_ => {
warn!("Unhandled update: {update:?}");
}
}
}
}
}
}