Annotation For src/telegram.rs
Logged in as anonymous

Lines of src/telegram.rs from check-in a044f68fa7 that are changed by the sequence of edits moving toward check-in 14ef340959:

                         1: use crate::utils::{
                         2: 	Attachment,
                         3: 	RE_SPECIAL,
                         4: };
                         5: 
                         6: use std::{
                         7: 	borrow::Cow,
                         8: 	collections::HashMap,
                         9: 	fmt::Debug,
                        10: };
                        11: 
                        12: use stacked_errors::{
                        13: 	Result,
                        14: 	StackableErr,
                        15: };
                        16: use tgbot::{
                        17: 	api::Client,
                        18: 	types::{
                        19: 		ChatPeerId,
                        20: 		InputFile,
                        21: 		InputFileReader,
                        22: 		InputMediaDocument,
                        23: 		MediaGroup,
                        24: 		MediaGroupItem,
                        25: 		Message,
                        26: 		ParseMode::MarkdownV2,
                        27: 		SendMediaGroup,
                        28: 		SendMessage,
                        29: 		SendDocument,
                        30: 	},
                        31: };
                        32: 
                        33: /// Encodes special HTML entities to prevent them interfering with Telegram HTML
                        34: pub fn encode (text: &str) -> Cow<'_, str> {
                        35: 	RE_SPECIAL.replace_all(text, "\\$1")
                        36: }
                        37: 
                        38: #[derive(Debug)]
                        39: pub struct TelegramTransport {
                        40: 	tg: Client,
                        41: 	recipients: HashMap<String, ChatPeerId>,
                        42: 	pub default: ChatPeerId,
                        43: }
                        44: 
                        45: impl TelegramTransport {
                        46: 
a044f68fa7 2025-08-23   47: 	pub fn new (api_key: String, recipients: HashMap<String, i64>, default: i64) -> Result<TelegramTransport> {
                        48: 		let tg = Client::new(api_key)
a044f68fa7 2025-08-23   49: 			.context("Failed to create API.\n")?;
                        50: 		let recipients = recipients.into_iter()
                        51: 			.map(|(a, b)| (a, ChatPeerId::from(b))).collect();
                        52: 		let default = ChatPeerId::from(default);
                        53: 
                        54: 		Ok(TelegramTransport {
                        55: 			tg,
                        56: 			recipients,
                        57: 			default,
                        58: 		})
                        59: 	}
                        60: 
                        61: 	/// Send message to default user, used for debug/log/info purposes
                        62: 	pub async fn debug (&self, msg: &str) -> Result<Message> {
                        63: 		self.send(&self.default, encode(msg)).await
                        64: 	}
                        65: 
                        66: 	/// Get recipient by address
                        67: 	pub fn get (&self, name: &str) -> Result<&ChatPeerId> {
                        68: 		self.recipients.get(name)
                        69: 			.with_context(|| format!("Recipient \"{name}\" not found in configuration"))
                        70: 	}
                        71: 
                        72: 	/// Send message to specified user
                        73: 	pub async fn send <S> (&self, to: &ChatPeerId, msg: S) -> Result<Message>
                        74: 	where S: Into<String> + Debug{
                        75: 		self.tg.execute(
                        76: 			SendMessage::new(*to, msg)
                        77: 			.with_parse_mode(MarkdownV2)
                        78: 		).await.stack()
                        79: 	}
                        80: 
                        81: 	/// Send media to specified user
                        82: 	pub async fn sendgroup (&self, to: &ChatPeerId, media: Vec<Attachment>, msg: &str) -> Result<()> {
                        83: 		if media.len() > 1 {
                        84: 			let mut attach = vec![];
                        85: 			let mut pos = media.len();
                        86: 			for file in media {
                        87: 				let mut caption = InputMediaDocument::default();
                        88: 				if pos == 1 {
                        89: 					caption = caption.with_caption(msg)
                        90: 						.with_caption_parse_mode(MarkdownV2);
                        91: 				}
                        92: 				pos -= 1;
                        93: 				attach.push(
                        94: 					MediaGroupItem::for_document(
                        95: 						InputFile::from(
                        96: 							InputFileReader::from(file.data)
                        97: 								.with_file_name(file.name)
                        98: 						),
                        99: 						caption
                       100: 					)
                       101: 				);
                       102: 			}
                       103: 			self.tg.execute(SendMediaGroup::new(*to, MediaGroup::new(attach).stack()?)).await.stack()?;
                       104: 		} else {
                       105: 			self.tg.execute(
                       106: 				SendDocument::new(
                       107: 					*to,
                       108: 					InputFileReader::from(media[0].data.clone())
                       109: 					.with_file_name(media[0].name.clone())
                       110: 				).with_caption(msg)
                       111: 				.with_caption_parse_mode(MarkdownV2)
                       112: 			).await.stack()?;
                       113: 		}
                       114: 		Ok(())
                       115: 	}
                       116: }