garudust_platforms/
telegram.rs1use std::pin::Pin;
2use std::sync::Arc;
3
4use async_trait::async_trait;
5use futures::Stream;
6use garudust_core::{
7 error::PlatformError,
8 platform::{MessageHandler, PlatformAdapter},
9 types::{ChannelId, InboundMessage, OutboundMessage},
10};
11use teloxide::prelude::*;
12
13pub struct TelegramAdapter {
14 bot: Bot,
15}
16
17impl TelegramAdapter {
18 pub fn new(token: String) -> Self {
19 Self {
20 bot: Bot::new(token),
21 }
22 }
23}
24
25#[async_trait]
26impl PlatformAdapter for TelegramAdapter {
27 fn name(&self) -> &'static str {
28 "telegram"
29 }
30
31 async fn start(&self, handler: Arc<dyn MessageHandler>) -> Result<(), PlatformError> {
32 let bot = self.bot.clone();
33 tokio::spawn(async move {
34 teloxide::repl(bot, move |_bot: Bot, msg: Message| {
35 let handler = handler.clone();
36 async move {
37 if let Some(text) = msg.text() {
38 let is_group = msg.chat.is_group() || msg.chat.is_supergroup();
39 let inbound = InboundMessage {
40 channel: ChannelId {
41 platform: "telegram".into(),
42 chat_id: msg.chat.id.to_string(),
43 thread_id: None,
44 },
45 user_id: msg
46 .from
47 .as_ref()
48 .map(|u| u.id.to_string())
49 .unwrap_or_default(),
50 user_name: msg
51 .from
52 .as_ref()
53 .and_then(|u| u.username.clone())
54 .unwrap_or_default(),
55 text: text.to_string(),
56 session_key: format!("telegram:{}", msg.chat.id),
57 is_group,
58 };
59 let _ = handler.handle(inbound).await;
60 }
61 respond(())
62 }
63 })
64 .await;
65 });
66 Ok(())
67 }
68
69 async fn send_message(
70 &self,
71 channel: &ChannelId,
72 message: OutboundMessage,
73 ) -> Result<(), PlatformError> {
74 let chat_id: i64 = channel
75 .chat_id
76 .parse()
77 .map_err(|_| PlatformError::Send("invalid chat_id".into()))?;
78 self.bot
79 .send_message(ChatId(chat_id), &message.text)
80 .await
81 .map_err(|e| PlatformError::Send(e.to_string()))?;
82 Ok(())
83 }
84
85 async fn send_stream(
86 &self,
87 channel: &ChannelId,
88 mut stream: Pin<Box<dyn Stream<Item = String> + Send>>,
89 ) -> Result<(), PlatformError> {
90 use futures::StreamExt;
91 let mut buf = String::new();
92 while let Some(chunk) = stream.next().await {
93 buf.push_str(&chunk);
94 }
95 self.send_message(channel, OutboundMessage::text(buf)).await
96 }
97}