Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
yongkangc committed Nov 22, 2023
1 parent cab3e48 commit fc47888
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 39 deletions.
50 changes: 15 additions & 35 deletions src/bot.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use reqwest::Client;
use serde::{de::DeserializeOwned, Serialize};
use std::{future::Future, sync::Arc, time::Duration};
use std::{sync::Arc, time::Duration};

use crate::{
errors::{ErrorResult, TelegramErrorResult},
types::{SendMessageOption, StatusCode},
types::{RequestObj, SendMessageOption, StatusCode},
utils,
};

// const BOT_TOKEN: &str = "BOT_TOKEN";
pub const TELEGRAM_API_URL: &str = "https://api.telegram.org";
const SEND_MESSAGE_METHOD: &str = "sendMessage";

Expand Down Expand Up @@ -39,8 +37,8 @@ impl Bot {
/// [http-client](reqwest::Client).
///
/// # Panics
///
/// If it cannot create [`reqwest::Client`].
///
pub fn new<S>(token: S, chat_id: S) -> Self
where
S: Into<String>,
Expand Down Expand Up @@ -90,34 +88,8 @@ impl Bot {
msg: &str,
options: Option<SendMessageOption>,
) -> Result<(), ErrorResult> {
// declare a request struct used only in this function scope
// NOTE: serde::Serialize can work with &str
#[derive(Debug, serde::Serialize)]
struct RequestObj<'a> {
chat_id: &'a str,
text: &'a str,

// this is required unfortunately, see https://github.com/serde-rs/serde/issues/947
#[serde(skip_serializing_if = "Option::is_none")]
parse_mode: Option<&'a str>,
}
let request_json_obj = self.build_request_obj(msg, options);

// create a request object which contains parameters needed for the API
let request_json_obj = RequestObj {
chat_id: &self.chat_id,
text: msg,
parse_mode: if options.is_some() && options.as_ref().unwrap().parse_mode.is_some() {
Some(utils::get_send_message_parse_mode_str(
options.unwrap().parse_mode.unwrap(),
))
} else {
None
},
};

// telegram supports both GET, and POST with various content-type
// 'application/json' is one of them that telegram supports
// makes a request using the reqwest client
let response = self
.client
.post(method_url(
Expand All @@ -132,13 +104,13 @@ impl Bot {
match response {
Ok(res) => {
if res.status().is_success() {
return Ok(());
Ok(())
} else {
match res.json::<TelegramErrorResult>().await {
Ok(json) => {
Ok(err_result) => {
return utils::create_error_result_str(
StatusCode::ErrorInternalError,
&json.description.to_owned(),
&err_result.description.to_owned(),
)
}
Err(_) => {
Expand All @@ -158,6 +130,14 @@ impl Bot {
}
}
}
fn build_request_obj(&self, msg: &str, options: Option<SendMessageOption>) -> RequestObj {
let parse_mode = options
.as_ref()
.and_then(|option| option.parse_mode.as_ref()) // Avoid repeated unwrap calls
.map(|mode| utils::get_send_message_parse_mode_str(mode).to_owned());

RequestObj::new(&self.chat_id, msg, parse_mode)
}
}

/// Getters
Expand Down
15 changes: 12 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
/// High Level Wrapper API of Bot.
///
/// This module provides a high-level API for interacting with Telegram's bot API. It provides
/// functionality for creating a bot with a token and chat ID, and for sending messages.
///
/// The `create_bot` function is used to create a new `Bot` instance. The `bot_token` parameter
/// should be the token provided by the BotFather on Telegram, and `chat_id` should be the ID
/// of the chat where the bot should send messages.
///
/// The `send_message` function is used to send a message to the chat associated with the `Bot`.
/// The `msg` parameter is the text of the message to send, and the `options` parameter can be
/// used to specify additional options like parse mode.
use bot::Bot;

pub mod bot;
pub mod errors;
pub mod tests;
pub mod types;
pub mod utils;

/// High Level Wrapper API of Bot.

/// Create a Bot to interact with APIs.
/// Returns a `Bot` configured with the provided bot token and chat id.
///
Expand Down
23 changes: 23 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,26 @@ pub enum StatusCode {
/// value will be used.
ErrorInternalError,
}

/// Request Object for `sendMessage` API
/// See https://core.telegram.org/bots/api#sendmessage
/// NOTE: serde::Serialize can work with &str
#[derive(Debug, serde::Serialize)]
pub struct RequestObj {
chat_id: String,
text: String,
// this is required unfortunately, see https://github.com/serde-rs/serde/issues/947
#[serde(skip_serializing_if = "Option::is_none")]
parse_mode: Option<String>,
}

impl RequestObj {
/// Create a new `RequestObj` with given chat id and message.
pub fn new(chat_id: &str, text: &str, parse_mode: Option<String>) -> Self {
Self {
chat_id: chat_id.to_owned(),
text: text.to_owned(),
parse_mode,
}
}
}
2 changes: 1 addition & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
///
/// # Arguments
/// * `mode` - parse mode
pub fn get_send_message_parse_mode_str(mode: SendMessageParseMode) -> &'static str {
pub fn get_send_message_parse_mode_str(mode: &SendMessageParseMode) -> &'static str {
match mode {
SendMessageParseMode::MarkdownV2 => "MarkdownV2",
SendMessageParseMode::HTML => "HTML",
Expand Down

0 comments on commit fc47888

Please sign in to comment.