use std::time::{SystemTime, UNIX_EPOCH};
use grammers_tl_types as tl;
use super::reply_markup::ReplyMarkup;
use crate::media::{Attribute, Media, Uploaded};
const SCHEDULE_ONCE_ONLINE: i32 = 0x7ffffffe;
#[derive(Clone, Default)]
pub struct InputMessage {
pub(crate) background: bool,
pub(crate) clear_draft: bool,
pub(crate) entities: Vec<tl::enums::MessageEntity>,
pub(crate) invert_media: bool,
pub(crate) link_preview: bool,
pub(crate) reply_markup: Option<tl::enums::ReplyMarkup>,
pub(crate) reply_to: Option<i32>,
pub(crate) schedule_date: Option<i32>,
pub(crate) silent: bool,
pub(crate) text: String,
pub(crate) media: Option<tl::enums::InputMedia>,
media_ttl: Option<i32>,
mime_type: Option<String>,
}
impl InputMessage {
pub fn new() -> Self {
Self::default()
}
pub fn background(mut self, background: bool) -> Self {
self.background = background;
self
}
pub fn clear_draft(mut self, clear_draft: bool) -> Self {
self.clear_draft = clear_draft;
self
}
pub fn text<T>(mut self, s: T) -> Self
where
T: Into<String>,
{
self.text = s.into();
self
}
pub fn fmt_entities<I>(mut self, entities: I) -> Self
where
I: IntoIterator<Item = tl::enums::MessageEntity>,
{
self.entities = entities.into_iter().collect();
self
}
#[cfg(feature = "markdown")]
pub fn markdown<T>(mut self, s: T) -> Self
where
T: AsRef<str>,
{
let (text, entities) = crate::parsers::parse_markdown_message(s.as_ref());
self.text = text;
self.entities = entities;
self
}
#[cfg(feature = "html")]
pub fn html<T>(mut self, s: T) -> Self
where
T: AsRef<str>,
{
let (text, entities) = crate::parsers::parse_html_message(s.as_ref());
self.text = text;
self.entities = entities;
self
}
pub fn invert_media(mut self, invert_media: bool) -> Self {
self.invert_media = invert_media;
self
}
pub fn link_preview(mut self, link_preview: bool) -> Self {
self.link_preview = link_preview;
self
}
pub fn reply_markup(mut self, markup: ReplyMarkup) -> Self {
self.reply_markup = Some(markup.raw);
self
}
pub fn reply_to(mut self, reply_to: Option<i32>) -> Self {
self.reply_to = reply_to;
self
}
pub fn schedule_date(mut self, schedule_date: Option<SystemTime>) -> Self {
self.schedule_date = schedule_date.map(|t| {
t.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs() as i32)
.unwrap_or(0)
});
self
}
pub fn schedule_once_online(mut self) -> Self {
self.schedule_date = Some(SCHEDULE_ONCE_ONLINE);
self
}
pub fn silent(mut self, silent: bool) -> Self {
self.silent = silent;
self
}
pub fn photo(mut self, file: Uploaded) -> Self {
self.media = Some(
(tl::types::InputMediaUploadedPhoto {
spoiler: false,
file: file.raw,
stickers: None,
ttl_seconds: self.media_ttl,
live_photo: false,
video: None,
})
.into(),
);
self
}
pub fn photo_url(mut self, url: impl Into<String>) -> Self {
self.media = Some(
(tl::types::InputMediaPhotoExternal {
spoiler: false,
url: url.into(),
ttl_seconds: self.media_ttl,
})
.into(),
);
self
}
pub fn document(mut self, file: Uploaded) -> Self {
let mime_type = self.get_file_mime(&file);
self.media = Some(crate::media::uploaded_document(
file,
mime_type,
false,
self.media_ttl,
));
self
}
pub fn media<M: Into<tl::enums::InputMedia>>(mut self, media: M) -> Self {
self.media = Some(media.into());
self
}
pub fn thumbnail(mut self, thumb: Uploaded) -> Self {
if let Some(tl::enums::InputMedia::UploadedDocument(document)) = &mut self.media {
document.thumb = Some(thumb.raw);
}
self
}
pub fn document_url(mut self, url: impl Into<String>) -> Self {
self.media = Some(
(tl::types::InputMediaDocumentExternal {
spoiler: false,
url: url.into(),
ttl_seconds: self.media_ttl,
video_cover: None,
video_timestamp: None,
})
.into(),
);
self
}
pub fn attribute(mut self, attr: Attribute) -> Self {
if let Some(tl::enums::InputMedia::UploadedDocument(document)) = &mut self.media {
document.attributes.push(attr.into());
}
self
}
pub fn copy_media(mut self, media: &Media) -> Self {
self.media = media.to_raw_input_media();
self
}
pub fn file(mut self, file: Uploaded) -> Self {
let mime_type = self.get_file_mime(&file);
self.media = Some(crate::media::uploaded_document(
file,
mime_type,
true,
self.media_ttl,
));
self
}
pub fn media_ttl(mut self, seconds: i32) -> Self {
self.media_ttl = if seconds < 0 { None } else { Some(seconds) };
self
}
pub fn mime_type(mut self, mime_type: &str) -> Self {
self.mime_type = Some(mime_type.to_string());
self
}
fn get_file_mime(&self, file: &Uploaded) -> String {
if let Some(mime) = self.mime_type.as_ref() {
mime.clone()
} else if let Some(mime) = mime_guess::from_path(file.name()).first() {
mime.essence_str().to_string()
} else {
"application/octet-stream".to_string()
}
}
}
impl<S> From<S> for InputMessage
where
S: Into<String>,
{
fn from(text: S) -> Self {
Self::new().text(text)
}
}
impl From<super::Message> for InputMessage {
fn from(message: super::Message) -> Self {
let (text, entities, media) = match message.raw {
tl::enums::Message::Empty(_) => (None, None, None),
tl::enums::Message::Message(message) => {
(Some(message.message), message.entities, message.media)
}
tl::enums::Message::Service(_) => (None, None, None),
};
Self {
text: text.unwrap_or_default(),
entities: entities.unwrap_or_default(),
media: media
.and_then(Media::from_raw)
.and_then(|m| m.to_raw_input_media()),
..Default::default()
}
}
}