From a61b5b226cfdadf0675c4c9b563c359809e2736a Mon Sep 17 00:00:00 2001 From: Temirkhan Myrzamadi <gymmasssorla@gmail.com> Date: Mon, 4 Nov 2019 01:03:56 +0600 Subject: [PATCH] Oops --- src/requests/form_builder.rs | 136 +++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/requests/form_builder.rs diff --git a/src/requests/form_builder.rs b/src/requests/form_builder.rs new file mode 100644 index 00000000..f19bc864 --- /dev/null +++ b/src/requests/form_builder.rs @@ -0,0 +1,136 @@ +use std::{borrow::Cow, path::PathBuf}; + +use reqwest::multipart::Form; + +use crate::{ + requests::utils::file_to_part, + types::{ChatId, InputFile, InputMedia, ParseMode}, +}; + +/// This is a convenient struct that builds `reqwest::multipart::Form` +/// from scratch. +pub(crate) struct FormBuilder { + form: Form, +} + +impl FormBuilder { + pub fn new() -> Self { + Self { form: Form::new() } + } + + /// Add the supplied key-value pair to this `FormBuilder`. + pub fn add<'a, T, N>(self, name: N, value: T) -> Self + where + N: Into<Cow<'a, str>>, + T: IntoFormValue, + { + let name = name.into().into_owned(); + match value.into_form_value() { + Some(FormValue::Str(string)) => Self { + form: self.form.text(name, string), + }, + Some(FormValue::File(path)) => self.add_file(name, path), + None => self, + } + } + + // used in SendMediaGroup + pub fn add_file<'a, N>(self, name: N, path_to_file: PathBuf) -> Self + where + N: Into<Cow<'a, str>>, + { + Self { + form: self + .form + .part(name.into().into_owned(), file_to_part(path_to_file)), + } + } + + pub fn build(self) -> Form { + self.form + } +} + +pub(crate) enum FormValue { + File(PathBuf), + Str(String), +} + +pub(crate) trait IntoFormValue { + fn into_form_value(self) -> Option<FormValue>; +} + +macro_rules! impl_for_struct { + ($($name:ty),*) => { + $( + impl IntoFormValue for $name { + fn into_form_value(self) -> Option<FormValue> { + let json = serde_json::to_string(&self) + .expect("serde_json::to_string failed"); + Some(FormValue::Str(json)) + } + } + )* + }; +} + +impl_for_struct!(bool, i32, i64); + +impl<T> IntoFormValue for Option<T> +where + T: IntoFormValue, +{ + fn into_form_value(self) -> Option<FormValue> { + self.and_then(IntoFormValue::into_form_value) + } +} + +impl IntoFormValue for &[InputMedia] { + fn into_form_value(self) -> Option<FormValue> { + let json = + serde_json::to_string(self).expect("serde_json::to_string failed"); + Some(FormValue::Str(json)) + } +} + +impl IntoFormValue for &str { + fn into_form_value(self) -> Option<FormValue> { + Some(FormValue::Str(self.to_owned())) + } +} + +impl IntoFormValue for ParseMode { + fn into_form_value(self) -> Option<FormValue> { + let string = match self { + ParseMode::HTML => String::from("HTML"), + ParseMode::Markdown => String::from("Markdown"), + }; + Some(FormValue::Str(string)) + } +} + +impl IntoFormValue for ChatId { + fn into_form_value(self) -> Option<FormValue> { + let string = match self { + ChatId::Id(id) => id.to_string(), + ChatId::ChannelUsername(username) => username, + }; + Some(FormValue::Str(string)) + } +} + +impl IntoFormValue for String { + fn into_form_value(self) -> Option<FormValue> { + Some(FormValue::Str(self)) + } +} + +impl IntoFormValue for InputFile { + fn into_form_value(self) -> Option<FormValue> { + match self { + InputFile::File(path) => Some(FormValue::File(path)), + InputFile::Url(url) => Some(FormValue::Str(url)), + InputFile::FileId(file_id) => Some(FormValue::Str(file_id)), + } + } +}