frankenstein 0.9.0

Telegram bot API client for Rust
Documentation

Crates.io docs page test style

Frankenstein

Telegram bot API client for Rust.

It's a complete wrapper for Telegram bot API and it's up to date with version 5.4 of the API.

Frankenstein data structures (rust structs and enums) are mapped one-to-one from Telegram bot API objects and method params.

Installation

Add this to your Cargo.toml

[dependencies]
frankenstein = "0.9"

Usage

Data structures

All objects described in the API docs have direct counterparts in the frankenstein. For example, in the docs there is the user type:

id	Integer	Unique identifier for this user or bot. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a 64-bit integer or double-precision float type are safe for storing this identifier.
is_bot	Boolean	True, if this user is a bot
first_name	String	User's or bot's first name
last_name	String	Optional. User's or bot's last name
username	String	Optional. User's or bot's username
language_code	String	Optional. IETF language tag of the user's language
can_join_groups	Boolean	Optional. True, if the bot can be invited to groups. Returned only in getMe.
can_read_all_group_messages	Boolean	Optional. True, if privacy mode is disabled for the bot. Returned only in getMe.
supports_inline_queries	Boolean	Optional. True, if the bot supports inline queries. Returned only in getMe.

In frankenstein, it's described as:

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Builder)]
#[builder(setter(into))]
pub struct User {
    pub id: u64,

    pub is_bot: bool,

    pub first_name: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[builder(setter(strip_option), default)]
    pub last_name: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[builder(setter(strip_option), default)]
    pub username: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[builder(setter(strip_option), default)]
    pub language_code: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[builder(setter(strip_option), default)]
    pub can_join_groups: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[builder(setter(strip_option), default)]
    pub can_read_all_group_messages: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    #[builder(setter(strip_option), default)]
    pub supports_inline_queries: Option<bool>,
}

Optional fields are described as Option enum.

Every struct can be created with the associated builder. It accepts only required fields, optional fields are set to None:

let send_message_params = SendMessageParamsBuilder::default()
    .chat_id(message.chat.id)
    .text("hello")
    .reply_to_message_id(message.message_id)
    .build()
    .unwrap();

For example, parameters for leaveChat method:

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct LeaveChatParams {
    chat_id: ChatId,
}

Making requests

To make a request to the telegram bot api:

  1. Initialize the Api struct:
use frankenstein::Api;
use frankenstein::TelegramApi;

...

let token = "My_token";
let api = Api::new(token);
  1. Use this api object to make requests to the Bot API:
let mut update_params_builder = GetUpdatesParamsBuilder::default();
update_params_builder.allowed_updates(vec!["message".to_string()]);

let update_params = update_params_builder.build().unwrap();

let result = api.get_updates(&update_params);

Every function returns a Result enum with a successful response or failed response.

See a complete example in the examples directory.

Uploading files

Some methods in the API allow uploading files. In the frankenstein for this File struct is used:

pub enum File {
    InputFile(InputFile),
    String(String),
}

pub struct InputFile {
    path: std::path::PathBuf
}

It has two variants:

  • File::String is used to pass id of the already uploaded file
  • File::InputFile is used to upload a new file using multipart upload.

Documentation

Frankenstein implements all telegram bot api methods. To see which parameters you should pass, check docs.rs

You can check out a real world bot created using this library - El Monitorro. El Monitorro is a feed reader bot.

Replacing the default http client

The library uses ureq http client by default, but it can be easily replaced with any http client of your choice:

  1. ureq comes with a default feature (impl). So the feature should be disabled:
frankenstein = { version = "0.9", default-features = false }
  1. Implement TelegramApi trait which requires two functions:
  • request_with_form_data is used to upload files
  • request is used for requests without file uploads

You can check the default TelegramApi trait implementation for ureq.

Also, you can take a look at the implementation for isahc http client in the examples directory.

Without the default ureq implementation, frankenstein has only one dependency - serde.

Contributing

  1. Fork it!
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Author

Ayrat Badykov (@ayrat555)