From 49cc1451d42a77225325c43050d84d46aaad2f54 Mon Sep 17 00:00:00 2001
From: Waffle <wafflewafflerov@gmail.com>
Date: Thu, 7 Nov 2019 01:25:07 +0300
Subject: [PATCH] Add `Bot::execute_{dyn,json,multipart,simple}` methods

---
 src/bot/execute.rs | 119 +++++++++++++++++++++++++++++++++++++++++++++
 src/bot/mod.rs     |   1 +
 2 files changed, 120 insertions(+)
 create mode 100644 src/bot/execute.rs

diff --git a/src/bot/execute.rs b/src/bot/execute.rs
new file mode 100644
index 00000000..455e42ae
--- /dev/null
+++ b/src/bot/execute.rs
@@ -0,0 +1,119 @@
+use serde::de::DeserializeOwned;
+
+use crate::{
+    Bot,
+    requests::{dynamic, json, multipart, Method, ResponseResult},
+    network::{request_dynamic, request_json, request_multipart, request_simple},
+};
+
+impl Bot {
+    /// Execute dyn-request
+    ///
+    /// ## Example
+    /// ```no_run
+    /// # use telebofr::{Bot, requests::payloads::SendMessage};
+    /// # #[tokio::main] async fn main() {
+    /// let bot = Bot::new("TOKEN");
+    /// let payload = SendMessage::new(123456, "text");
+    /// bot.execute_dyn(&payload).await;
+    /// # }
+    /// ```
+    ///
+    /// **NOTES**:
+    /// 1. we recommend to use `bot.send_message(id, "text").send().await`
+    ///   instead
+    /// 2. this is _dynamic_ version of execute, so it has a _little_ overhead,
+    ///   prefer using [`execute_json`], [`execute_multipart`] or
+    ///   [`execute_simple`] depending on type of payload when possible.
+    ///
+    /// [`execute_json`]: self::Bot::execute_json
+    /// [`execute_multipart`]: self::Bot::execute_multipart
+    /// [`execute_simple`]: self::Bot::execute_simple
+    pub async fn execute_dyn<O>(
+        &self,
+        payload: &dyn dynamic::Payload<Output = O>
+    ) -> ResponseResult<O>
+    where
+        O: DeserializeOwned,
+    {
+        request_dynamic(
+            self.client(),
+            self.token(),
+            payload.name(),
+            payload.kind()
+        ).await
+    }
+
+    /// Execute json-request
+    ///
+    /// ## Example
+    /// ```no_run
+    /// # use telebofr::{Bot, requests::payloads::SendMessage};
+    /// # #[tokio::main] async fn main() {
+    /// let bot = Bot::new("TOKEN");
+    /// let payload = SendMessage::new(123456, "text");
+    /// bot.execute_json(&payload).await;
+    /// # }
+    /// ```
+    ///
+    /// **NOTE**: we recommend to use
+    ///   `bot.send_message(id, "text").send().await` instead
+    pub async fn execute_json<P>(&self, payload: &P) -> ResponseResult<P::Output>
+    where
+        P: json::Payload,
+        P::Output: DeserializeOwned,
+    {
+        request_json(self.client(), self.token(), P::NAME, payload).await
+    }
+
+    /// Execute multipart-request
+    ///
+    /// ## Example
+    /// ```no_run
+    /// # use telebofr::{Bot, requests::payloads::SendAnimation, types::InputFile};
+    /// # #[tokio::main] async fn main() {
+    /// let bot = Bot::new("TOKEN");
+    /// let payload = SendAnimation::new(
+    ///     123456,
+    ///     InputFile::Url(String::from("https://example.com"))
+    /// );
+    /// bot.execute_multipart(&payload).await;
+    /// # }
+    /// ```
+    ///
+    /// **NOTE**: we recommend to use
+    ///   `bot.send_animation(id, InputFile::...).send().await` instead
+    pub async fn execute_multipart<P>(&self, payload: &P) -> ResponseResult<P::Output>
+    where
+        P: multipart::Payload,
+        P::Output: DeserializeOwned,
+    {
+        request_multipart(
+            self.client(),
+            self.token(),
+            P::NAME,
+            payload.payload()
+        ).await
+    }
+
+    /// Execute simple-request
+    ///
+    /// ## Example
+    /// ```no_run
+    /// # use telebofr::{Bot, requests::payloads::GetMe};
+    /// # #[tokio::main] async fn main() {
+    /// let bot = Bot::new("TOKEN");
+    /// bot.execute_simple(&GetMe /* the only one "simple" request */).await;
+    /// # }
+    /// ```
+    ///
+    /// **NOTE**: we recommend to use
+    ///   `bot.get_me().send().await` instead
+    pub async fn execute_simple<P>(&self, payload: &P) -> ResponseResult<P::Output>
+    where
+        P: Method,
+        P::Output: DeserializeOwned,
+    {
+        request_simple(self.client(), self.token(), P::NAME).await
+    }
+}
diff --git a/src/bot/mod.rs b/src/bot/mod.rs
index f2b45f51..dd0cb3cc 100644
--- a/src/bot/mod.rs
+++ b/src/bot/mod.rs
@@ -2,6 +2,7 @@ use reqwest::Client;
 
 mod api;
 mod download;
+mod execute;
 
 /// A Telegram bot used to build requests.
 #[derive(Debug, Clone)]