use serde::{Deserialize, Serialize};
pub use self::{input::*, mask::*, set::*};
use crate::{
api::{Form, Method, Payload, PayloadError, WriteForm},
types::{
ChatId,
File,
InputFile,
Integer,
Message,
PhotoSize,
ReplyMarkup,
ReplyParameters,
SuggestedPostParameters,
},
};
mod input;
mod mask;
mod set;
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
pub struct Sticker {
pub file_id: String,
pub file_unique_id: String,
pub height: Integer,
pub is_animated: bool,
pub is_video: bool,
#[serde(rename = "type")]
pub sticker_type: StickerType,
pub width: Integer,
pub custom_emoji_id: Option<String>,
pub emoji: Option<String>,
pub file_size: Option<Integer>,
pub mask_position: Option<MaskPosition>,
pub needs_repainting: Option<bool>,
pub premium_animation: Option<File>,
pub set_name: Option<String>,
pub thumbnail: Option<PhotoSize>,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum StickerFormat {
Static,
Animated,
Video,
}
impl AsRef<str> for StickerFormat {
fn as_ref(&self) -> &str {
match self {
Self::Static => "static",
Self::Animated => "animated",
Self::Video => "video",
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum StickerType {
CustomEmoji,
Mask,
Regular,
}
impl AsRef<str> for StickerType {
fn as_ref(&self) -> &str {
match self {
Self::CustomEmoji => "custom_emoji",
Self::Mask => "mask",
Self::Regular => "regular",
}
}
}
#[derive(Clone, Debug, Serialize)]
pub struct GetCustomEmojiStickers {
custom_emoji_ids: Vec<String>,
}
impl GetCustomEmojiStickers {
pub fn new<A, B>(custom_emoji_ids: A) -> Self
where
A: IntoIterator<Item = B>,
B: Into<String>,
{
Self {
custom_emoji_ids: custom_emoji_ids.into_iter().map(Into::into).collect(),
}
}
}
impl Method for GetCustomEmojiStickers {
type Response = Vec<Sticker>;
fn into_payload(self) -> Result<Payload, PayloadError> {
Payload::json("getCustomEmojiStickers", self)
}
}
#[derive(Debug)]
pub struct SendSticker {
sticker: InputFile,
parameters: SendStickerParameters,
}
impl SendSticker {
pub fn new<A, B>(chat_id: A, sticker: B) -> Self
where
A: Into<ChatId>,
B: Into<InputFile>,
{
Self {
sticker: sticker.into(),
parameters: SendStickerParameters {
chat_id: Some(chat_id.into()),
..Default::default()
},
}
}
pub fn with_allow_paid_broadcast(mut self, value: bool) -> Self {
self.parameters.allow_paid_broadcast = Some(value);
self
}
pub fn with_business_connection_id<T>(mut self, value: T) -> Self
where
T: Into<String>,
{
self.parameters.business_connection_id = Some(value.into());
self
}
pub fn with_callback_query_id<T>(mut self, value: T) -> Self
where
T: Into<String>,
{
self.parameters.callback_query_id = Some(value.into());
self
}
pub fn with_direct_messages_topic_id(mut self, value: Integer) -> Self {
self.parameters.direct_messages_topic_id = Some(value);
self
}
pub fn with_disable_notification(mut self, value: bool) -> Self {
self.parameters.disable_notification = Some(value);
self
}
pub fn with_emoji<T>(mut self, value: T) -> Self
where
T: Into<String>,
{
self.parameters.emoji = Some(value.into());
self
}
pub fn with_message_effect_id<T>(mut self, value: T) -> Self
where
T: Into<String>,
{
self.parameters.message_effect_id = Some(value.into());
self
}
pub fn with_message_thread_id(mut self, value: Integer) -> Self {
self.parameters.message_thread_id = Some(value);
self
}
pub fn with_protect_content(mut self, value: bool) -> Self {
self.parameters.protect_content = Some(value);
self
}
pub fn with_receiver_user_id(mut self, value: Integer) -> Self {
self.parameters.receiver_user_id = Some(value);
self
}
pub fn with_reply_markup<T>(mut self, value: T) -> Self
where
T: Into<ReplyMarkup>,
{
self.parameters.reply_markup = Some(value.into());
self
}
pub fn with_reply_parameters(mut self, value: ReplyParameters) -> Self {
self.parameters.reply_parameters = Some(value);
self
}
pub fn with_suggested_post_parameters(mut self, value: SuggestedPostParameters) -> Self {
self.parameters.suggested_post_parameters = Some(value);
self
}
}
#[serde_with::skip_serializing_none]
#[derive(Debug, Default, Serialize)]
struct SendStickerParameters {
allow_paid_broadcast: Option<bool>,
business_connection_id: Option<String>,
callback_query_id: Option<String>,
chat_id: Option<ChatId>,
direct_messages_topic_id: Option<Integer>,
disable_notification: Option<bool>,
emoji: Option<String>,
message_effect_id: Option<String>,
message_thread_id: Option<Integer>,
protect_content: Option<bool>,
receiver_user_id: Option<Integer>,
reply_markup: Option<ReplyMarkup>,
reply_parameters: Option<ReplyParameters>,
sticker: Option<String>,
suggested_post_parameters: Option<SuggestedPostParameters>,
}
impl Method for SendSticker {
type Response = Message;
fn into_payload(self) -> Result<Payload, PayloadError> {
let Self {
sticker,
mut parameters,
} = self;
let mut form = Form::default();
parameters.sticker = Some(sticker.write(&mut form));
parameters.serialize(&mut form)?;
Payload::form("sendSticker", form)
}
}
#[derive(Clone, Debug, Serialize)]
pub struct SetStickerEmojiList {
sticker: String,
emoji_list: Vec<String>,
}
impl SetStickerEmojiList {
pub fn new<A, B, C>(sticker: A, emoji_list: B) -> Self
where
A: Into<String>,
B: IntoIterator<Item = C>,
C: Into<String>,
{
Self {
sticker: sticker.into(),
emoji_list: emoji_list.into_iter().map(Into::into).collect(),
}
}
}
impl Method for SetStickerEmojiList {
type Response = bool;
fn into_payload(self) -> Result<Payload, PayloadError> {
Payload::json("setStickerEmojiList", self)
}
}
#[derive(Clone, Debug, Serialize)]
pub struct SetStickerKeywords {
sticker: String,
keywords: Vec<String>,
}
impl SetStickerKeywords {
pub fn new<A, B, C>(sticker: A, keywords: B) -> Self
where
A: Into<String>,
B: IntoIterator<Item = C>,
C: Into<String>,
{
Self {
sticker: sticker.into(),
keywords: keywords.into_iter().map(Into::into).collect(),
}
}
}
impl Method for SetStickerKeywords {
type Response = bool;
fn into_payload(self) -> Result<Payload, PayloadError> {
Payload::json("setStickerKeywords", self)
}
}
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Serialize)]
pub struct SetStickerMaskPosition {
sticker: String,
mask_position: Option<MaskPosition>,
}
impl SetStickerMaskPosition {
pub fn new<T>(sticker: T) -> Self
where
T: Into<String>,
{
Self {
sticker: sticker.into(),
mask_position: None,
}
}
pub fn with_mask_position(mut self, value: MaskPosition) -> Self {
self.mask_position = Some(value);
self
}
}
impl Method for SetStickerMaskPosition {
type Response = bool;
fn into_payload(self) -> Result<Payload, PayloadError> {
Payload::json("setStickerMaskPosition", self)
}
}
#[derive(Debug)]
pub struct UploadStickerFile {
parameters: UploadStickerFileParameters,
sticker: InputFile,
}
impl UploadStickerFile {
pub fn new<T>(user_id: Integer, sticker: T, sticker_format: StickerFormat) -> Self
where
T: Into<InputFile>,
{
Self {
sticker: sticker.into(),
parameters: UploadStickerFileParameters {
user_id: Some(user_id),
sticker_format: Some(sticker_format),
..Default::default()
},
}
}
}
#[serde_with::skip_serializing_none]
#[derive(Debug, Default, Serialize)]
struct UploadStickerFileParameters {
sticker: Option<String>,
sticker_format: Option<StickerFormat>,
user_id: Option<Integer>,
}
impl Method for UploadStickerFile {
type Response = File;
fn into_payload(self) -> Result<Payload, PayloadError> {
let Self {
sticker,
mut parameters,
} = self;
let mut form = Form::default();
parameters.sticker = Some(sticker.write(&mut form));
parameters.serialize(&mut form)?;
Payload::form("uploadStickerFile", form)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sticker_format() {
assert_eq!(StickerFormat::Animated.as_ref(), "animated");
assert_eq!(StickerFormat::Static.as_ref(), "static");
assert_eq!(StickerFormat::Video.as_ref(), "video");
}
#[test]
fn sticker_type() {
assert_eq!(StickerType::CustomEmoji.as_ref(), "custom_emoji");
assert_eq!(StickerType::Mask.as_ref(), "mask");
assert_eq!(StickerType::Regular.as_ref(), "regular");
}
}