use serde::Serialize;
use std::path::PathBuf;
#[derive(Debug, Clone)]
pub enum AttachmentSource {
LocalFile(PathBuf),
Token(String),
}
#[derive(Debug, Clone, Serialize)]
pub struct ContactData {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contact_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vcf_info: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vcf_phone: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct InlineKeyboardButton {
pub r#type: String,
pub text: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub payload: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quick: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub web_app: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contact_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub app_payload: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub message_text: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct InlineKeyboard {
pub buttons: Vec<Vec<InlineKeyboardButton>>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ShareData {
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token: Option<String>,
}
#[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", content = "payload")]
pub enum Attachment {
#[serde(rename = "image")]
Image {
#[serde(skip)]
source: AttachmentSource,
token: Option<String>,
url: Option<String>,
},
#[serde(rename = "video")]
Video {
#[serde(skip)]
source: AttachmentSource,
token: Option<String>,
url: Option<String>,
},
#[serde(rename = "audio")]
Audio {
#[serde(skip)]
source: AttachmentSource,
token: Option<String>,
url: Option<String>,
},
#[serde(rename = "file")]
File {
#[serde(skip)]
source: AttachmentSource,
token: Option<String>,
url: Option<String>,
},
#[serde(rename = "sticker")]
Sticker {
code: String,
},
#[serde(rename = "contact")]
Contact(ContactData),
#[serde(rename = "inline_keyboard")]
InlineKeyboard(InlineKeyboard),
#[serde(rename = "location")]
Location {
latitude: f64,
longitude: f64,
},
#[serde(rename = "share")]
Share(ShareData),
}
impl Attachment {
pub fn get_type(&self) -> &'static str {
match self {
Attachment::Image { .. } => "image",
Attachment::Video { .. } => "video",
Attachment::Audio { .. } => "audio",
Attachment::File { .. } => "file",
Attachment::Sticker { .. } => "sticker",
Attachment::Contact(_) => "contact",
Attachment::InlineKeyboard(_) => "inline_keyboard",
Attachment::Location { .. } => "location",
Attachment::Share(_) => "share",
}
}
pub fn image_local(path: impl Into<PathBuf>) -> Self {
Attachment::Image {
source: AttachmentSource::LocalFile(path.into()),
token: None,
url: None,
}
}
pub fn image_token(token: impl Into<String>) -> Self {
Attachment::Image {
source: AttachmentSource::Token(token.into()),
token: None,
url: None,
}
}
pub fn image_url(url: impl Into<String>) -> Self {
Attachment::Image {
source: AttachmentSource::Token(String::new()), token: None,
url: Some(url.into()),
}
}
pub fn video_local(path: impl Into<PathBuf>) -> Self {
Attachment::Video {
source: AttachmentSource::LocalFile(path.into()),
token: None,
url: None,
}
}
pub fn video_token(token: impl Into<String>) -> Self {
Attachment::Video {
source: AttachmentSource::Token(token.into()),
token: None,
url: None,
}
}
pub fn video_url(url: impl Into<String>) -> Self {
Attachment::Video {
source: AttachmentSource::Token(String::new()),
token: None,
url: Some(url.into()),
}
}
pub fn audio_local(path: impl Into<PathBuf>) -> Self {
Attachment::Audio {
source: AttachmentSource::LocalFile(path.into()),
token: None,
url: None,
}
}
pub fn audio_token(token: impl Into<String>) -> Self {
Attachment::Audio {
source: AttachmentSource::Token(token.into()),
token: None,
url: None,
}
}
pub fn audio_url(url: impl Into<String>) -> Self {
Attachment::Audio {
source: AttachmentSource::Token(String::new()),
token: None,
url: Some(url.into()),
}
}
pub fn file_local(path: impl Into<PathBuf>) -> Self {
Attachment::File {
source: AttachmentSource::LocalFile(path.into()),
token: None,
url: None,
}
}
pub fn file_token(token: impl Into<String>) -> Self {
Attachment::File {
source: AttachmentSource::Token(token.into()),
token: None,
url: None,
}
}
pub fn file_url(url: impl Into<String>) -> Self {
Attachment::File {
source: AttachmentSource::Token(String::new()),
token: None,
url: Some(url.into()),
}
}
pub fn sticker(code: impl Into<String>) -> Self {
Attachment::Sticker { code: code.into() }
}
pub fn contact(data: ContactData) -> Self {
Attachment::Contact(data)
}
pub fn inline_keyboard(keyboard: InlineKeyboard) -> Self {
Attachment::InlineKeyboard(keyboard)
}
pub fn location(latitude: f64, longitude: f64) -> Self {
Attachment::Location { latitude, longitude }
}
pub fn share(data: ShareData) -> Self {
Attachment::Share(data)
}
}
pub struct InlineKeyboardBuilder {
rows: Vec<Vec<InlineKeyboardButton>>,
}
impl InlineKeyboardBuilder {
pub fn new() -> Self {
Self { rows: vec![] }
}
pub fn row(mut self, buttons: Vec<InlineKeyboardButton>) -> Self {
self.rows.push(buttons);
self
}
pub fn button(mut self, btn: InlineKeyboardButton) -> Self {
if self.rows.is_empty() {
self.rows.push(vec![]);
}
self.rows.last_mut().unwrap().push(btn);
self
}
pub fn buttons(mut self, btns: Vec<InlineKeyboardButton>) -> Self {
if self.rows.is_empty() {
self.rows.push(vec![]);
}
self.rows.last_mut().unwrap().extend(btns);
self
}
pub fn build(self) -> InlineKeyboard {
InlineKeyboard { buttons: self.rows }
}
}
impl Default for InlineKeyboardBuilder {
fn default() -> Self {
Self::new()
}
}
impl InlineKeyboardButton {
pub fn callback(text: impl Into<String>, payload: impl Into<String>) -> Self {
Self {
r#type: "callback".to_string(),
text: text.into(),
payload: Some(payload.into()),
url: None,
quick: None,
web_app: None,
contact_id: None,
app_payload: None,
message_text: None,
}
}
pub fn link(text: impl Into<String>, url: impl Into<String>) -> Self {
Self {
r#type: "link".to_string(),
text: text.into(),
payload: None,
url: Some(url.into()),
quick: None,
web_app: None,
contact_id: None,
app_payload: None,
message_text: None,
}
}
pub fn request_contact(text: impl Into<String>) -> Self {
Self {
r#type: "request_contact".to_string(),
text: text.into(),
payload: None,
url: None,
quick: Some(true),
web_app: None,
contact_id: None,
app_payload: None,
message_text: None,
}
}
pub fn request_location(text: impl Into<String>) -> Self {
Self {
r#type: "request_geo_location".to_string(),
text: text.into(),
payload: None,
url: None,
quick: Some(true),
web_app: None,
contact_id: None,
app_payload: None,
message_text: None,
}
}
pub fn open_app(
text: impl Into<String>,
web_app_url: impl Into<String>,
contact_id: i64,
payload: Option<String>,
) -> Self {
Self {
r#type: "open_app".to_string(),
text: text.into(),
payload,
url: None,
quick: None,
web_app: Some(web_app_url.into()),
contact_id: Some(contact_id),
app_payload: None,
message_text: None,
}
}
pub fn message(text: impl Into<String>, message_text: impl Into<String>) -> Self {
Self {
r#type: "message".to_string(),
text: text.into(),
payload: None,
url: None,
quick: None,
web_app: None,
contact_id: None,
app_payload: None,
message_text: Some(message_text.into()),
}
}
}