diff --git a/README.md b/README.md
index d70c314..bb24b31 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,5 @@
![frankenstein](frankenstein_logo.png)
-[![Crates.io][s1]][ci] [![docs page][docs-badge]][docs] ![test][ga-test]
-
# Frankenstein
Telegram bot API client for Rust.
@@ -79,50 +77,42 @@ Optional fields are described as `Option`.
Every struct can be created with the associated builder. Only required fields are required to set, optional fields are set to `None` when not provided:
```rust
+use frankenstein::api_params::SendMessageParams;
let send_message_params = SendMessageParams::builder()
- .chat_id(message.chat.id)
+ .chat_id(1337)
.text("hello")
- .reply_to_message_id(message.message_id)
.build();
```
-For API parameters, the same approach is used. The only difference for parameters is the name of the struct in Frankenstein ends with `Params` postfix.
-
-For example, parameters for `leaveChat` method:
-
-```rust
-pub struct LeaveChatParams {
- chat_id: ChatId,
-}
-```
-
### Making requests
-To make a request to the Telegram bot API initialize the `Api` struct.
-
-```rust
-use frankenstein::Api;
+```rust,no_run
+#![cfg(feature = "client-ureq")]
use frankenstein::TelegramApi;
+use frankenstein::api_params::{GetUpdatesParams, SendMessageParams};
+use frankenstein::client_ureq::Bot;
+use frankenstein::objects::AllowedUpdate;
-...
+let token = "123:ABC";
+let bot = Bot::new(token);
-let token = "My_token";
-let api = Api::new(token);
-```
-
-Then use this API object to make requests to the Bot API:
+// Send a message
+let send_message_params = SendMessageParams::builder()
+ .chat_id(1337)
+ .text("hello")
+ .build();
+let result = bot.send_message(&send_message_params);
-```rust
+// or get the updates (= interactions with the bot)
let update_params = GetUpdatesParams::builder()
.allowed_updates(vec![AllowedUpdate::Message])
.build();
-
-let result = api.get_updates(&update_params);
+let result = bot.get_updates(&update_params);
```
-Every function returns a `Result` enum with a successful response or failed response.
+Every function returns a `Result` with a successful response or failed response.
-See a complete example in the `examples` directory.
+See more examples in the [`examples`](https://github.com/ayrat555/frankenstein/tree/0.38.0/examples) directory.
### Uploading files
@@ -144,46 +134,9 @@ It has two variants:
- `FileUpload::String` is used to pass the ID of the already uploaded file
- `FileUpload::InputFile` is used to upload a new file using multipart upload.
-### Customizing HTTP clients
-
-Both the async (`reqwest`) and the blocking (`ureq`) HTTP clients can be customized with their builders.
-
-Customizing the blocking client:
-
-```rust
-use frankenstein::ureq;
-use frankenstein::Api;
-use std::time::Duration;
-
-let request_agent = ureq::builder().timeout(Duration::from_secs(100)).build();
-let api_url = format!("{}{}", BASE_API_URL, TOKEN);
-
-Api::builder()
- .api_url(api_url)
- .request_agent(request_agent)
- .build()
-```
-
-Customizing the async client:
-
-```rust
-use frankenstein::reqwest;
-use frankenstein::AsyncApi;
-use std::time::Duration;
-
-let client = reqwest::ClientBuilder::new()
- .connect_timeout(Duration::from_secs(100))
- .timeout(Duration::from_secs(100))
- .build()
- .unwrap();
-let api_url = format!("{}{}", BASE_API_URL, TOKEN);
-
-AsyncApi::builder().api_url(api_url).client(client).build()
-```
-
### Documentation
-Frankenstein implements all Telegram bot API methods. To see which parameters you should pass, check [docs.rs](https://docs.rs/frankenstein/0.38.0/frankenstein/api_traits/telegram_api/trait.TelegramApi.html#provided-methods)
+Frankenstein implements all Telegram bot API methods. To see which parameters you should pass, check the [official Telegram Bot API documentation](https://core.telegram.org/bots/api#available-methods) or [docs.rs/frankenstein](https://docs.rs/frankenstein/0.38.0/frankenstein/trait.TelegramApi.html#provided-methods)
You can check out real-world bots created using this library:
@@ -192,24 +145,6 @@ You can check out real-world bots created using this library:
- [wdr-maus-downloader](https://github.com/EdJoPaTo/wdr-maus-downloader) - checks for a new episode of the WDR Maus and downloads it.
- [weather_bot_rust](https://github.com/pxp9/weather_bot_rust) - A Telegram bot that provides weather info around the world.
-## 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.
-This is described here for the `trait-sync` and can be done similarly with `trait-async` based on your needs.
-
-```toml
-frankenstein = { version = "0.39", features = ["trait-sync"] }
-```
-
-Then implement the `TelegramApi` trait for your HTTP client 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](https://github.com/ayrat555/frankenstein/blob/aac88c01d06aa945393db7255ef2485a7c764d47/src/api_impl.rs) for `ureq`.
-
-Also, you can take a look at the [implementation for `isahc` HTTP client](https://github.com/ayrat555/frankenstein/blob/master/examples/api_trait_implementation.rs) in the `examples` directory.
-
## Contributing
1. [Fork it!](https://github.com/ayrat555/frankenstein/fork)
@@ -221,9 +156,3 @@ Also, you can take a look at the [implementation for `isahc` HTTP client](https:
## Author
Ayrat Badykov (@ayrat555)
-
-[s1]: https://img.shields.io/crates/v/frankenstein.svg
-[docs-badge]: https://img.shields.io/badge/docs-website-blue.svg
-[ci]: https://crates.io/crates/frankenstein
-[docs]: https://docs.rs/frankenstein/
-[ga-test]: https://github.com/ayrat555/frankenstein/actions/workflows/rust.yml/badge.svg
diff --git a/examples/api_trait_implementation.rs b/examples/api_trait_implementation.rs
index aa973a9..8f7be4d 100644
--- a/examples/api_trait_implementation.rs
+++ b/examples/api_trait_implementation.rs
@@ -10,7 +10,7 @@ static TOKEN: &str = "TOKEN";
static BASE_API_URL: &str = "https://api.telegram.org/bot";
static CHAT_ID: i64 = 1;
-pub struct Api {
+pub struct MyApiClient {
pub api_url: String,
}
@@ -20,7 +20,7 @@ pub enum Error {
Api(ErrorResponse),
}
-impl Api {
+impl MyApiClient {
#[must_use]
pub fn new(api_key: &str) -> Self {
let api_url = format!("{BASE_API_URL}{api_key}");
@@ -47,7 +47,7 @@ impl From for Error {
}
}
-impl TelegramApi for Api {
+impl TelegramApi for MyApiClient {
type Error = Error;
fn request(
@@ -105,14 +105,14 @@ impl TelegramApi for Api {
}
fn main() {
- let api = Api::new(TOKEN);
+ let bot = MyApiClient::new(TOKEN);
let params = SendMessageParams::builder()
.chat_id(CHAT_ID)
.text("Hello!")
.build();
- let result = api.send_message(¶ms);
+ let result = bot.send_message(¶ms);
eprintln!("{result:?}");
}
diff --git a/examples/async_custom_client.rs b/examples/async_custom_client.rs
index 9e9e98f..e1ff52c 100644
--- a/examples/async_custom_client.rs
+++ b/examples/async_custom_client.rs
@@ -1,15 +1,16 @@
use std::time::Duration;
-use frankenstein::{AsyncApi, AsyncTelegramApi};
+use frankenstein::client_reqwest::Bot;
+use frankenstein::AsyncTelegramApi;
static TOKEN: &str = "API_TOKEN";
static BASE_API_URL: &str = "https://api.telegram.org/bot";
#[tokio::main]
async fn main() {
- let api = custom_client();
+ let bot = custom_client();
- match api.get_me().await {
+ match bot.get_me().await {
Ok(response) => {
let user = response.result;
println!(
@@ -24,7 +25,7 @@ async fn main() {
}
}
-fn custom_client() -> AsyncApi {
+fn custom_client() -> Bot {
let client = frankenstein::reqwest::ClientBuilder::new()
.connect_timeout(Duration::from_secs(100))
.timeout(Duration::from_secs(100))
@@ -32,5 +33,5 @@ fn custom_client() -> AsyncApi {
.unwrap();
let api_url = format!("{BASE_API_URL}{TOKEN}");
- AsyncApi::builder().api_url(api_url).client(client).build()
+ Bot::builder().api_url(api_url).client(client).build()
}
diff --git a/examples/async_file_upload.rs b/examples/async_file_upload.rs
index 58e6a1e..4a25df6 100644
--- a/examples/async_file_upload.rs
+++ b/examples/async_file_upload.rs
@@ -1,12 +1,13 @@
use frankenstein::api_params::SendPhotoParams;
-use frankenstein::{AsyncApi, AsyncTelegramApi};
+use frankenstein::client_reqwest::Bot;
+use frankenstein::AsyncTelegramApi;
static TOKEN: &str = "TOKEN";
static CHAT_ID: i64 = 1;
#[tokio::main]
async fn main() {
- let api = AsyncApi::new(TOKEN);
+ let bot = Bot::new(TOKEN);
let file = std::path::PathBuf::from("./frankenstein_logo.png");
@@ -15,7 +16,7 @@ async fn main() {
.photo(file)
.build();
- match api.send_photo(¶ms).await {
+ match bot.send_photo(¶ms).await {
Ok(response) => {
println!("Photo was uploaded {response:?}");
}
diff --git a/examples/async_get_me.rs b/examples/async_get_me.rs
index ef0e104..d497c47 100644
--- a/examples/async_get_me.rs
+++ b/examples/async_get_me.rs
@@ -1,12 +1,13 @@
-use frankenstein::{AsyncApi, AsyncTelegramApi};
+use frankenstein::client_reqwest::Bot;
+use frankenstein::AsyncTelegramApi;
static TOKEN: &str = "API_TOKEN";
#[tokio::main]
async fn main() {
- let api = AsyncApi::new(TOKEN);
+ let bot = Bot::new(TOKEN);
- match api.get_me().await {
+ match bot.get_me().await {
Ok(response) => {
let user = response.result;
println!(
diff --git a/examples/async_reply_to_message_updates.rs b/examples/async_reply_to_message_updates.rs
index 9c8abd1..fe0ba26 100644
--- a/examples/async_reply_to_message_updates.rs
+++ b/examples/async_reply_to_message_updates.rs
@@ -1,17 +1,18 @@
use frankenstein::api_params::{GetUpdatesParams, ReplyParameters, SendMessageParams};
+use frankenstein::client_reqwest::Bot;
use frankenstein::objects::{Message, UpdateContent};
-use frankenstein::{AsyncApi, AsyncTelegramApi};
+use frankenstein::AsyncTelegramApi;
static TOKEN: &str = "API_TOKEN";
#[tokio::main]
async fn main() {
- let api = AsyncApi::new(TOKEN);
+ let bot = Bot::new(TOKEN);
let mut update_params = GetUpdatesParams::builder().build();
loop {
- let result = api.get_updates(&update_params).await;
+ let result = bot.get_updates(&update_params).await;
println!("result: {result:?}");
@@ -19,10 +20,10 @@ async fn main() {
Ok(response) => {
for update in response.result {
if let UpdateContent::Message(message) = update.content {
- let api_clone = api.clone();
+ let bot_clone = bot.clone();
tokio::spawn(async move {
- process_message(message, api_clone).await;
+ process_message(message, bot_clone).await;
});
}
update_params.offset = Some(i64::from(update.update_id) + 1);
@@ -35,7 +36,7 @@ async fn main() {
}
}
-async fn process_message(message: Message, api: AsyncApi) {
+async fn process_message(message: Message, bot: Bot) {
let reply_parameters = ReplyParameters::builder()
.message_id(message.message_id)
.build();
@@ -44,7 +45,7 @@ async fn process_message(message: Message, api: AsyncApi) {
.text("hello")
.reply_parameters(reply_parameters)
.build();
- if let Err(error) = api.send_message(&send_message_params).await {
+ if let Err(error) = bot.send_message(&send_message_params).await {
println!("Failed to send message: {error:?}");
}
}
diff --git a/examples/custom_client.rs b/examples/custom_client.rs
index 0a97e10..52bae57 100644
--- a/examples/custom_client.rs
+++ b/examples/custom_client.rs
@@ -1,14 +1,15 @@
use std::time::Duration;
-use frankenstein::{Api, TelegramApi};
+use frankenstein::client_ureq::Bot;
+use frankenstein::TelegramApi;
static TOKEN: &str = "API_TOKEN";
static BASE_API_URL: &str = "https://api.telegram.org/bot";
fn main() {
- let api = custom_client();
+ let bot = custom_client();
- match api.get_me() {
+ match bot.get_me() {
Ok(response) => {
let user = response.result;
println!(
@@ -23,7 +24,7 @@ fn main() {
}
}
-fn custom_client() -> Api {
+fn custom_client() -> Bot {
let config = frankenstein::ureq::Agent::config_builder()
.http_status_as_error(false)
.timeout_global(Some(Duration::from_secs(100)))
@@ -31,7 +32,7 @@ fn custom_client() -> Api {
let request_agent = frankenstein::ureq::Agent::new_with_config(config);
let api_url = format!("{BASE_API_URL}{TOKEN}");
- Api::builder()
+ Bot::builder()
.api_url(api_url)
.request_agent(request_agent)
.build()
diff --git a/examples/get_me.rs b/examples/get_me.rs
index 7ce6198..9804af1 100644
--- a/examples/get_me.rs
+++ b/examples/get_me.rs
@@ -1,11 +1,12 @@
-use frankenstein::{Api, TelegramApi};
+use frankenstein::client_ureq::Bot;
+use frankenstein::TelegramApi;
static TOKEN: &str = "API_TOKEN";
fn main() {
- let api = Api::new(TOKEN);
+ let bot = Bot::new(TOKEN);
- match api.get_me() {
+ match bot.get_me() {
Ok(response) => {
let user = response.result;
println!(
diff --git a/examples/inline_keyboard.rs b/examples/inline_keyboard.rs
index 32b178d..ecf8ece 100644
--- a/examples/inline_keyboard.rs
+++ b/examples/inline_keyboard.rs
@@ -1,6 +1,7 @@
use frankenstein::api_params::{ReplyMarkup, SendMessageParams};
+use frankenstein::client_ureq::Bot;
use frankenstein::objects::{InlineKeyboardButton, InlineKeyboardMarkup};
-use frankenstein::{Api, TelegramApi};
+use frankenstein::TelegramApi;
// replace with your token
static TOKEN: &str = "TOKEN";
@@ -8,7 +9,7 @@ static TOKEN: &str = "TOKEN";
static CHAT_ID: i64 = 275_808_073;
fn main() {
- let api = Api::new(TOKEN);
+ let bot = Bot::new(TOKEN);
let mut keyboard: Vec> = Vec::new();
@@ -38,5 +39,5 @@ fn main() {
.reply_markup(ReplyMarkup::InlineKeyboardMarkup(inline_keyboard))
.build();
- api.send_message(&send_message_params).unwrap();
+ bot.send_message(&send_message_params).unwrap();
}
diff --git a/examples/reply_keyboard.rs b/examples/reply_keyboard.rs
index 2014347..ba155b6 100644
--- a/examples/reply_keyboard.rs
+++ b/examples/reply_keyboard.rs
@@ -1,6 +1,7 @@
use frankenstein::api_params::{ReplyMarkup, SendMessageParams};
+use frankenstein::client_ureq::Bot;
use frankenstein::objects::{KeyboardButton, ReplyKeyboardMarkup};
-use frankenstein::{Api, TelegramApi};
+use frankenstein::TelegramApi;
// replace with your token
static TOKEN: &str = "TOKEN";
@@ -8,7 +9,7 @@ static TOKEN: &str = "TOKEN";
static CHAT_ID: i64 = 275_808_073;
fn main() {
- let api = Api::new(TOKEN);
+ let bot = Bot::new(TOKEN);
let mut keyboard: Vec> = Vec::new();
@@ -33,5 +34,5 @@ fn main() {
.reply_markup(ReplyMarkup::ReplyKeyboardMarkup(keyboard_markup))
.build();
- api.send_message(&send_message_params).unwrap();
+ bot.send_message(&send_message_params).unwrap();
}
diff --git a/examples/reply_to_message_updates.rs b/examples/reply_to_message_updates.rs
index dcbf262..4acf922 100644
--- a/examples/reply_to_message_updates.rs
+++ b/examples/reply_to_message_updates.rs
@@ -1,16 +1,17 @@
use frankenstein::api_params::{GetUpdatesParams, ReplyParameters, SendMessageParams};
+use frankenstein::client_ureq::Bot;
use frankenstein::objects::UpdateContent;
-use frankenstein::{Api, TelegramApi};
+use frankenstein::TelegramApi;
static TOKEN: &str = "API_TOKEN";
fn main() {
- let api = Api::new(TOKEN);
+ let bot = Bot::new(TOKEN);
let mut update_params = GetUpdatesParams::builder().build();
loop {
- let result = api.get_updates(&update_params);
+ let result = bot.get_updates(&update_params);
println!("result: {result:?}");
@@ -26,7 +27,7 @@ fn main() {
.text("hello")
.reply_parameters(reply_parameters)
.build();
- if let Err(error) = api.send_message(&send_message_params) {
+ if let Err(error) = bot.send_message(&send_message_params) {
println!("Failed to send message: {error:?}");
}
}
diff --git a/src/client_reqwest.rs b/src/client_reqwest.rs
index 03accab..0b1daa3 100644
--- a/src/client_reqwest.rs
+++ b/src/client_reqwest.rs
@@ -6,10 +6,10 @@ use bon::Builder;
use crate::trait_async::AsyncTelegramApi;
use crate::Error;
-/// Asynchronous [`AsyncTelegramApi`] client implementation with [`reqwest`].
+/// Asynchronous [`AsyncTelegramApi`] implementation with [`reqwest`]
#[derive(Debug, Clone, Builder)]
-#[must_use = "API needs to be used in order to be useful"]
-pub struct AsyncApi {
+#[must_use = "Bot needs to be used in order to be useful"]
+pub struct Bot {
#[builder(into)]
pub api_url: String,
@@ -28,13 +28,13 @@ fn default_client() -> reqwest::Client {
client_builder.build().unwrap()
}
-impl AsyncApi {
- /// Create a new `AsyncApi`. You can use [`AsyncApi::new_url`] or [`AsyncApi::builder`] for more options.
+impl Bot {
+ /// Create a new `Bot`. You can use [`Bot::new_url`] or [`Bot::builder`] for more options.
pub fn new(api_key: &str) -> Self {
Self::new_url(format!("{}{api_key}", crate::BASE_API_URL))
}
- /// Create a new `AsyncApi`. You can use [`AsyncApi::builder`] for more options.
+ /// Create a new `Bot`. You can use [`Bot::builder`] for more options.
pub fn new_url>(api_url: S) -> Self {
Self::builder().api_url(api_url).build()
}
@@ -63,7 +63,7 @@ impl From for Error {
// Wasm target need not be `Send` because it is single-threaded
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
-impl AsyncTelegramApi for AsyncApi {
+impl AsyncTelegramApi for Bot {
type Error = Error;
async fn request(
@@ -169,7 +169,7 @@ mod tests {
.with_body(response_string)
.create_async()
.await;
- let api = AsyncApi::new_url(server.url());
+ let api = Bot::new_url(server.url());
let response = api.send_message(¶ms).await.unwrap();
mock.assert();
@@ -193,7 +193,7 @@ mod tests {
.with_body(response_string)
.create_async()
.await;
- let api = AsyncApi::new_url(server.url());
+ let api = Bot::new_url(server.url());
let error = api.send_message(¶ms).await.unwrap_err().unwrap_api();
mock.assert();
diff --git a/src/client_ureq.rs b/src/client_ureq.rs
index 37ef6d6..10b5087 100644
--- a/src/client_ureq.rs
+++ b/src/client_ureq.rs
@@ -8,10 +8,10 @@ use serde_json::Value;
use crate::trait_sync::TelegramApi;
use crate::Error;
-/// Synchronous [`TelegramApi`] client implementation with [`ureq`].
+/// Synchronous [`TelegramApi`] implementation with [`ureq`].
#[derive(Debug, Clone, Builder)]
-#[must_use = "API needs to be used in order to be useful"]
-pub struct Api {
+#[must_use = "Bot needs to be used in order to be useful"]
+pub struct Bot {
#[builder(into)]
pub api_url: String,
@@ -28,13 +28,13 @@ fn default_agent() -> ureq::Agent {
)
}
-impl Api {
- /// Create a new `Api`. You can use [`Api::new_url`] or [`Api::builder`] for more options.
+impl Bot {
+ /// Create a new `Bot`. You can use [`Bot::new_url`] or [`Bot::builder`] for more options.
pub fn new(api_key: &str) -> Self {
Self::new_url(format!("{}{api_key}", crate::BASE_API_URL))
}
- /// Create a new `Api`. You can use [`Api::builder`] for more options.
+ /// Create a new `Bot`. You can use [`Bot::builder`] for more options.
pub fn new_url>(api_url: S) -> Self {
Self::builder().api_url(api_url).build()
}
@@ -56,7 +56,7 @@ impl Api {
}
}
-impl TelegramApi for Api {
+impl TelegramApi for Bot {
type Error = Error;
fn request(&self, method: &str, params: Option) -> Result