cortexfs_channels/platform/
telegram.rs1use serde_json::json;
2
3use super::{ChannelCodec, OutboundRequest, object, participant, scalar, text, timestamp_ms};
4use crate::{
5 ChannelError, ChannelId, ConversationId, InboundMessage, MessageTarget, OutboundMessage,
6};
7
8#[derive(Clone, Copy, Debug, Default)]
10pub struct TelegramCodec;
11
12impl ChannelCodec for TelegramCodec {
13 fn channel(&self) -> ChannelId {
14 ChannelId::from_static("telegram")
15 }
16
17 fn decode(&self, payload: &str) -> Result<Option<InboundMessage>, ChannelError> {
18 let root = object(payload)?;
19 if root.get("ok").and_then(serde_json::Value::as_bool) == Some(false) {
20 return Ok(None);
21 }
22 let message = root.get("message").or_else(|| root.get("channel_post"));
23 let Some(message) = message else {
24 return Ok(None);
25 };
26 let id = scalar(message.get("message_id"), "message_id")?;
27 let chat = message
28 .get("chat")
29 .ok_or_else(|| ChannelError::Protocol("telegram chat is missing".to_owned()))?;
30 let conversation = ConversationId::new(scalar(chat.get("id"), "chat.id")?)?;
31 let sender_id = message
32 .get("from")
33 .map(|from| scalar(from.get("id"), "from.id"))
34 .transpose()?
35 .unwrap_or_else(|| conversation.to_string());
36 Ok(Some(InboundMessage {
37 id,
38 target: MessageTarget {
39 channel: self.channel(),
40 conversation,
41 thread: message
42 .get("message_thread_id")
43 .map(|value| scalar(Some(value), "message_thread_id"))
44 .transpose()?,
45 reply_to: message
46 .get("reply_to_message")
47 .and_then(|reply| reply.get("message_id"))
48 .map(|value| scalar(Some(value), "reply_to_message.message_id"))
49 .transpose()?,
50 },
51 sender: participant(message.get("from"), sender_id),
52 body: text(message.get("text").or_else(|| message.get("caption")))?,
53 timestamp_ms: timestamp_ms(message.get("date")),
54 metadata: std::collections::BTreeMap::new(),
55 }))
56 }
57
58 fn encode(&self, message: &OutboundMessage) -> Result<OutboundRequest, ChannelError> {
59 message.body.validate()?;
60 if !message.body.attachments.is_empty() {
61 return Err(ChannelError::Unsupported(
62 "telegram media attachments".to_owned(),
63 ));
64 }
65 let mut fields = serde_json::Map::new();
66 fields.insert(
67 "chat_id".to_owned(),
68 json!(message.target.conversation.as_str()),
69 );
70 fields.insert("text".to_owned(), json!(message.body.text));
71 if let Some(reply) = message.target.reply_to.as_deref() {
72 fields.insert("reply_to_message_id".to_owned(), json!(reply));
73 }
74 Ok(OutboundRequest {
75 method: "POST".to_owned(),
76 path: "sendMessage".to_owned(),
77 content_type: "application/json".to_owned(),
78 body: serde_json::Value::Object(fields).to_string(),
79 headers: std::collections::BTreeMap::new(),
80 })
81 }
82}