13265e7697 2026-01-10 1: use serde::{
13265e7697 2026-01-10 2: Deserialize,
13265e7697 2026-01-10 3: Serialize,
13265e7697 2026-01-10 4: };
9c4f09193a 2026-01-09 5: use stacked_errors::{
9c4f09193a 2026-01-09 6: Result,
9c4f09193a 2026-01-09 7: StackableErr,
9c4f09193a 2026-01-09 8: };
9c4f09193a 2026-01-09 9: use tgbot::{
9c4f09193a 2026-01-09 10: api::Client,
9c4f09193a 2026-01-09 11: types::{
9c4f09193a 2026-01-09 12: Bot,
9c4f09193a 2026-01-09 13: ChatPeerId,
9c4f09193a 2026-01-09 14: GetBot,
13265e7697 2026-01-10 15: InlineKeyboardButton,
13265e7697 2026-01-10 16: InlineKeyboardMarkup,
9c4f09193a 2026-01-09 17: Message,
9c4f09193a 2026-01-09 18: ParseMode,
9c4f09193a 2026-01-09 19: SendMessage,
9c4f09193a 2026-01-09 20: },
9c4f09193a 2026-01-09 21: };
13265e7697 2026-01-10 22:
13265e7697 2026-01-10 23: #[derive(Serialize, Deserialize, Debug)]
13265e7697 2026-01-10 24: enum Callback {
13265e7697 2026-01-10 25: // List all feeds (version, name to show)
13265e7697 2026-01-10 26: List(u8, String),
13265e7697 2026-01-10 27: }
13265e7697 2026-01-10 28:
13265e7697 2026-01-10 29: fn get_kb (cb: &Callback) -> Result<InlineKeyboardMarkup> {
13265e7697 2026-01-10 30: let mark = InlineKeyboardMarkup::from(vec![vec![
13265e7697 2026-01-10 31: InlineKeyboardButton::for_callback_data("1",
13265e7697 2026-01-10 32: toml::to_string(&Callback::List(0,"xxx".to_owned())).stack()?),
13265e7697 2026-01-10 33: ]]);
13265e7697 2026-01-10 34: Ok(mark)
13265e7697 2026-01-10 35: }
9c4f09193a 2026-01-09 36:
9c4f09193a 2026-01-09 37: #[derive(Clone)]
9c4f09193a 2026-01-09 38: pub struct Tg {
9c4f09193a 2026-01-09 39: pub me: Bot,
9c4f09193a 2026-01-09 40: pub owner: ChatPeerId,
9c4f09193a 2026-01-09 41: pub client: Client,
9c4f09193a 2026-01-09 42: }
9c4f09193a 2026-01-09 43:
9c4f09193a 2026-01-09 44: impl Tg {
fabcca1eaf 2026-01-09 45: /// Construct a new `Tg` instance from configuration.
fabcca1eaf 2026-01-09 46: ///
fabcca1eaf 2026-01-09 47: /// The `settings` must provide the following keys:
fabcca1eaf 2026-01-09 48: /// - `"api_key"` (string),
fabcca1eaf 2026-01-09 49: /// - `"owner"` (integer chat id),
fabcca1eaf 2026-01-09 50: /// - `"api_gateway"` (string).
fabcca1eaf 2026-01-09 51: ///
fabcca1eaf 2026-01-09 52: /// The function initialises the client, configures the gateway and fetches the bot identity
fabcca1eaf 2026-01-09 53: /// before returning the constructed `Tg`.
9c4f09193a 2026-01-09 54: pub async fn new (settings: &config::Config) -> Result<Tg> {
9c4f09193a 2026-01-09 55: let api_key = settings.get_string("api_key").stack()?;
9c4f09193a 2026-01-09 56:
9c4f09193a 2026-01-09 57: let owner = ChatPeerId::from(settings.get_int("owner").stack()?);
9c4f09193a 2026-01-09 58: let client = Client::new(&api_key).stack()?
9c4f09193a 2026-01-09 59: .with_host(settings.get_string("api_gateway").stack()?)
9c4f09193a 2026-01-09 60: .with_max_retries(0);
9c4f09193a 2026-01-09 61: let me = client.execute(GetBot).await.stack()?;
9c4f09193a 2026-01-09 62: Ok(Tg {
9c4f09193a 2026-01-09 63: me,
9c4f09193a 2026-01-09 64: owner,
9c4f09193a 2026-01-09 65: client,
9c4f09193a 2026-01-09 66: })
9c4f09193a 2026-01-09 67: }
9c4f09193a 2026-01-09 68:
fabcca1eaf 2026-01-09 69: /// Send a text message to a chat, using an optional target and parse mode.
fabcca1eaf 2026-01-09 70: ///
fabcca1eaf 2026-01-09 71: /// # Returns
fabcca1eaf 2026-01-09 72: /// The sent `Message` on success.
9c4f09193a 2026-01-09 73: pub async fn send <S>(&self, msg: S, target: Option<ChatPeerId>, mode: Option<ParseMode>) -> Result<Message>
9c4f09193a 2026-01-09 74: where S: Into<String> {
9c4f09193a 2026-01-09 75: let msg = msg.into();
9c4f09193a 2026-01-09 76:
9c4f09193a 2026-01-09 77: let mode = mode.unwrap_or(ParseMode::Html);
9c4f09193a 2026-01-09 78: let target = target.unwrap_or(self.owner);
9c4f09193a 2026-01-09 79: self.client.execute(
9c4f09193a 2026-01-09 80: SendMessage::new(target, msg)
9c4f09193a 2026-01-09 81: .with_parse_mode(mode)
9c4f09193a 2026-01-09 82: ).await.stack()
9c4f09193a 2026-01-09 83: }
9c4f09193a 2026-01-09 84:
fabcca1eaf 2026-01-09 85: /// Create a copy of this `Tg` with the owner replaced by the given chat ID.
fabcca1eaf 2026-01-09 86: ///
fabcca1eaf 2026-01-09 87: /// # Parameters
fabcca1eaf 2026-01-09 88: /// - `owner`: The Telegram chat identifier to set as the new owner (expressed as an `i64`).
fabcca1eaf 2026-01-09 89: ///
fabcca1eaf 2026-01-09 90: /// # Returns
fabcca1eaf 2026-01-09 91: /// A new `Tg` instance identical to the original except its `owner` field is set to the provided chat ID.
fabcca1eaf 2026-01-09 92: pub fn with_owner <O>(&self, owner: O) -> Tg
fabcca1eaf 2026-01-09 93: where O: Into<i64> {
9c4f09193a 2026-01-09 94: Tg {
fabcca1eaf 2026-01-09 95: owner: ChatPeerId::from(owner.into()),
9c4f09193a 2026-01-09 96: ..self.clone()
9c4f09193a 2026-01-09 97: }
9c4f09193a 2026-01-09 98: }
9c4f09193a 2026-01-09 99: }