use crate::types::{poll::PollKind, True};
use serde::Serialize;
use std::ops::Not;
#[derive(Clone, Debug, Default, Serialize)]
pub struct ReplyKeyboardMarkup {
keyboard: Vec<Vec<KeyboardButton>>,
#[serde(skip_serializing_if = "Not::not")]
resize_keyboard: bool,
#[serde(skip_serializing_if = "Not::not")]
one_time_keyboard: bool,
#[serde(skip_serializing_if = "Option::is_none")]
input_field_placeholder: Option<String>,
#[serde(skip_serializing_if = "Not::not")]
selective: bool,
}
impl ReplyKeyboardMarkup {
pub fn from_vec(keyboard: Vec<Vec<KeyboardButton>>) -> Self {
ReplyKeyboardMarkup {
keyboard,
resize_keyboard: false,
one_time_keyboard: false,
input_field_placeholder: None,
selective: false,
}
}
pub fn resize_keyboard(mut self, value: bool) -> Self {
self.resize_keyboard = value;
self
}
pub fn one_time_keyboard(mut self, value: bool) -> Self {
self.one_time_keyboard = value;
self
}
pub fn input_field_placeholder<T>(mut self, value: T) -> Self
where
T: Into<String>,
{
self.input_field_placeholder = Some(value.into());
self
}
pub fn selective(mut self, value: bool) -> Self {
self.selective = value;
self
}
pub fn row(mut self, value: Vec<KeyboardButton>) -> Self {
self.keyboard.push(value);
self
}
}
impl From<Vec<Vec<KeyboardButton>>> for ReplyKeyboardMarkup {
fn from(keyboard: Vec<Vec<KeyboardButton>>) -> ReplyKeyboardMarkup {
ReplyKeyboardMarkup::from_vec(keyboard)
}
}
#[derive(Clone, Debug, Serialize)]
pub struct KeyboardButton {
text: String,
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
kind: Option<KeyboardButtonKind>,
}
#[derive(Clone, Debug, Serialize)]
#[allow(clippy::enum_variant_names)]
#[serde(rename_all = "snake_case")]
enum KeyboardButtonKind {
RequestContact(True),
RequestLocation(True),
RequestPoll(KeyboardButtonPollType),
}
impl KeyboardButton {
pub fn new<S: Into<String>>(text: S) -> Self {
KeyboardButton {
text: text.into(),
kind: None,
}
}
pub fn request_contact(mut self) -> Self {
self.kind = Some(KeyboardButtonKind::RequestContact(True));
self
}
pub fn request_location(mut self) -> Self {
self.kind = Some(KeyboardButtonKind::RequestLocation(True));
self
}
pub fn request_poll<T>(mut self, button_type: T) -> Self
where
T: Into<KeyboardButtonPollType>,
{
self.kind = Some(KeyboardButtonKind::RequestPoll(button_type.into()));
self
}
}
#[derive(Clone, Copy, Debug, Serialize, PartialEq, PartialOrd)]
pub struct KeyboardButtonPollType {
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "type")]
kind: Option<PollKind>,
}
impl From<PollKind> for KeyboardButtonPollType {
fn from(kind: PollKind) -> Self {
KeyboardButtonPollType { kind: Some(kind) }
}
}
impl From<Option<PollKind>> for KeyboardButtonPollType {
fn from(kind: Option<PollKind>) -> Self {
KeyboardButtonPollType { kind }
}
}
#[derive(Clone, Debug, Serialize)]
pub struct ReplyKeyboardRemove {
remove_keyboard: bool,
#[serde(skip_serializing_if = "Option::is_none")]
selective: Option<bool>,
}
impl Default for ReplyKeyboardRemove {
fn default() -> ReplyKeyboardRemove {
ReplyKeyboardRemove {
remove_keyboard: true,
selective: None,
}
}
}
impl ReplyKeyboardRemove {
pub fn selective(mut self, selective: bool) -> Self {
self.selective = Some(selective);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::ReplyMarkup;
#[test]
fn serialize() {
let row = vec![
KeyboardButton::new("test"),
KeyboardButton::new("request contact").request_contact(),
KeyboardButton::new("request location").request_location(),
KeyboardButton::new("request quiz").request_poll(PollKind::Quiz),
KeyboardButton::new("request regular poll").request_poll(PollKind::Regular),
KeyboardButton::new("request any poll").request_poll(None),
];
let markup = ReplyKeyboardMarkup::from(vec![row.clone()])
.one_time_keyboard(true)
.selective(true)
.resize_keyboard(true)
.input_field_placeholder("placeholder");
let data = serde_json::to_value(&ReplyMarkup::from(markup)).unwrap();
assert_eq!(
data,
serde_json::json!({
"keyboard": [
[
{"text": "test"},
{"text": "request contact", "request_contact": true},
{"text": "request location", "request_location": true},
{"text": "request quiz", "request_poll": {"type": "quiz"}},
{"text": "request regular poll", "request_poll": {"type": "regular"}},
{"text": "request any poll", "request_poll": {}},
]
],
"resize_keyboard": true,
"one_time_keyboard": true,
"input_field_placeholder": "placeholder",
"selective": true
})
);
let markup: ReplyMarkup = ReplyKeyboardMarkup::default().row(row).into();
let data = serde_json::to_value(&markup).unwrap();
assert_eq!(
data,
serde_json::json!({
"keyboard": [
[
{"text": "test"},
{"text": "request contact","request_contact":true},
{"text": "request location","request_location":true},
{"text": "request quiz", "request_poll": {"type": "quiz"}},
{"text": "request regular poll", "request_poll": {"type": "regular"}},
{"text": "request any poll", "request_poll": {}},
]
]
})
);
let markup: ReplyMarkup = ReplyKeyboardRemove::default().selective(true).into();
let j = serde_json::to_value(&markup).unwrap();
assert_eq!(j, serde_json::json!({"remove_keyboard":true,"selective":true}));
}
}