use serde::{Deserialize, Serialize}; use std::{collections::HashMap, error::Error}; const API_BASE: &str = "https://api.telegram.org"; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TelegramAPIResponse { pub ok: bool, pub error_code: Option, pub description: Option, pub result: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TelegramStickerSet { pub name: String, pub title: String, pub is_animated: bool, pub is_video: bool, pub stickers: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TelegramSticker { pub file_id: String, pub file_unique_id: String, pub is_animated: bool, pub is_video: bool, pub emoji: Option, } #[derive(Debug)] struct TelegramError { error_code: u16, description: String, } impl TelegramError { fn new(error_code: u16, description: String) -> TelegramError { TelegramError { error_code, description, } } } impl std::fmt::Display for TelegramError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{} {}", self.error_code, self.description) } } impl Error for TelegramError { fn description(&self) -> &str { self.description.as_str() } } pub struct TelegramAPI { token: String, client: reqwest::Client, } impl TelegramAPI { pub fn new(token: String) -> Self { Self { token, client: reqwest::Client::new(), } } pub async fn get_sticker_set( &self, pack_name: &str, ) -> Result> { let url = format!("{}/bot{}/getStickerSet", API_BASE, self.token); let res = self .client .get(url) .form(&HashMap::from([("name", pack_name)])) .send() .await?; let res_json = res .json::>() .await?; if !res_json.ok { return Err(Box::new(TelegramError::new( res_json.error_code.unwrap(), res_json.description.unwrap(), ))); } Ok(res_json.result.unwrap()) } pub async fn delete_sticker(&self, sticker_file_id: &str) -> Result> { let url = format!("{}/bot{}/deleteStickerFromSet", API_BASE, self.token); let res = self .client .get(url) .form(&HashMap::from([("sticker", sticker_file_id)])) .send() .await?; let res_json = res.json::>().await?; if !res_json.ok { return Err(Box::new(TelegramError::new( res_json.error_code.unwrap(), res_json.description.unwrap(), ))); } Ok(res_json.result.unwrap()) } #[allow(clippy::too_many_arguments)] pub async fn create_sticker_pack( &self, user_id: u64, name: String, title: String, emojis: String, png_sticker: Option>, tgs_sticker: Option>, webm_sticker: Option>, ) -> Result> { let url = format!("{}/bot{}/createNewStickerSet", API_BASE, self.token); let mut form = reqwest::multipart::Form::new(); form = form.text("user_id", user_id.to_string()); form = form.text("name", name); form = form.text("title", title); form = form.text("emojis", emojis); if png_sticker.is_some() { form = form.part( "png_sticker", reqwest::multipart::Part::bytes(png_sticker.unwrap()).file_name(""), ); } if tgs_sticker.is_some() { form = form.part( "tgs_sticker", reqwest::multipart::Part::bytes(tgs_sticker.unwrap()), ); } if webm_sticker.is_some() { form = form.part( "webm_sticker", reqwest::multipart::Part::bytes(webm_sticker.unwrap()), ); } let res = self.client.get(url).multipart(form).send().await?; let res_json = res.json::>().await?; if !res_json.ok { return Err(Box::new(TelegramError::new( res_json.error_code.unwrap(), res_json.description.unwrap(), ))); } Ok(res_json.result.unwrap()) } pub async fn upload_sticker( &self, user_id: u64, sticker_pack_name: String, emojis: Option, png_sticker: Option>, tgs_sticker: Option>, webm_sticker: Option>, ) -> Result> { let url = format!("{}/bot{}/addStickerToSet", API_BASE, self.token); let mut form = reqwest::multipart::Form::new(); form = form.text("user_id", user_id.to_string()); form = form.text("name", sticker_pack_name); if emojis.is_some() { form = form.text("emojis", emojis.unwrap()); } if png_sticker.is_some() { form = form.part( "png_sticker", reqwest::multipart::Part::bytes(png_sticker.unwrap()).file_name(""), ); } if tgs_sticker.is_some() { form = form.part( "tgs_sticker", reqwest::multipart::Part::bytes(tgs_sticker.unwrap()), ); } if webm_sticker.is_some() { form = form.part( "webm_sticker", reqwest::multipart::Part::bytes(webm_sticker.unwrap()), ); } let res = self.client.get(url).multipart(form).send().await?; let res_json = res.json::>().await?; if !res_json.ok { return Err(Box::new(TelegramError::new( res_json.error_code.unwrap(), res_json.description.unwrap(), ))); } Ok(res_json.result.unwrap()) } pub async fn set_sticker_position( &self, sticker_file_id: String, sticker_position: usize, ) -> Result> { let url = format!("{}/bot{}/setStickerPositionInSet", API_BASE, self.token); let res = self .client .get(url) .form(&HashMap::from([ ("sticker", sticker_file_id), ("position", sticker_position.to_string()), ])) .send() .await?; let res_json = res.json::>().await?; if !res_json.ok { return Err(Box::new(TelegramError::new( res_json.error_code.unwrap(), res_json.description.unwrap(), ))); } Ok(res_json.result.unwrap()) } }