diff --git a/api.go b/api.go index a66f6211..2d2cd1ef 100644 --- a/api.go +++ b/api.go @@ -212,6 +212,33 @@ func (b *Bot) sendMedia(media Media, params map[string]string, files map[string] return extractMessage(data) } +func (b *Bot) sendPaidMedia(to Recipient, media Media, stars int, opts ...interface{}) (*Message, error) { + sendOpts := b.extractOptions(opts) + + kind := media.MediaType() + what := "send" + strings.Title(kind) + + if kind == "videoNote" { + kind = "video_note" + } + + sendFiles := map[string]File{kind: *media.MediaFile()} + sendFiles[media.MediaFile().FileURL] = *media.MediaFile() + + params := map[string]string{ + "chat_id": to.Recipient(), + "star_count": strconv.Itoa(stars), + } + b.embedSendOptions(params, sendOpts) + + data, err := b.sendFiles(what, sendFiles, params) + if err != nil { + return nil, err + } + + return extractMessage(data) +} + func (b *Bot) getMe() (*User, error) { data, err := b.Raw("getMe", nil) if err != nil { diff --git a/chat.go b/chat.go index d4b73569..4d031797 100644 --- a/chat.go +++ b/chat.go @@ -59,6 +59,7 @@ type Chat struct { SlowMode int `json:"slow_mode_delay,omitempty"` StickerSet string `json:"sticker_set_name,omitempty"` CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` + CanSendPaidMedia bool `json:"can_send_paid_media"` CustomEmojiStickerSet string `json:"custom_emoji_sticker_set_name"` LinkedChatID int64 `json:"linked_chat_id,omitempty"` ChatLocation *ChatLocation `json:"location,omitempty"` diff --git a/context.go b/context.go index f5c49656..7ef3b309 100644 --- a/context.go +++ b/context.go @@ -69,6 +69,9 @@ type Context interface { // Returns nil if chat is not presented. Chat() *Chat + // Payment returns payment instance. + Payment() *Payment + // Recipient combines both Sender and Chat functions. If there is no user // the chat will be returned. The native context cannot be without sender, // but it is useful in the case when the context created intentionally @@ -328,6 +331,10 @@ func (c *nativeContext) Chat() *Chat { } } +func (c *nativeContext) Payment() *Payment { + return c.u.Message.Payment +} + func (c *nativeContext) Recipient() Recipient { chat := c.Chat() if chat != nil { diff --git a/media.go b/media.go index 3926802e..060a5813 100644 --- a/media.go +++ b/media.go @@ -34,6 +34,20 @@ type InputMedia struct { HasSpoiler bool `json:"has_spoiler,omitempty"` } +type PaidMediaInfo struct { + Stars int `json:"star_count"` + PaidMedia []PaidMedia `json:"paid_media"` +} + +type PaidMedia struct { + Type string `json:"type"` + Photo *Photo `json:"photo,omitempty"` + Video Video `json:"video,omitempty"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + Duration int `json:"duration,omitempty"` +} + // Inputtable is a generic type for all kinds of media you // can put into an album. type Inputtable interface { @@ -344,6 +358,7 @@ type Contact struct { // (Optional) LastName string `json:"last_name"` UserID int64 `json:"user_id,omitempty"` + VCard string `json:"vcard,omitempty"` } // LiveForever is an alias for math.MaxInt32. diff --git a/message.go b/message.go index 160a5f0c..749ca7d3 100644 --- a/message.go +++ b/message.go @@ -128,6 +128,9 @@ type Message struct { // For a general file, information about it. Document *Document `json:"document"` + // Message contains paid media; information about the paid media + PaidMedia PaidMediaInfo `json:"paid_media"` + // For a photo, all available sizes (thumbnails). Photo *Photo `json:"photo"` @@ -663,6 +666,9 @@ type ExternalReplyInfo struct { // (Optional) Message is a general file, information about the file. Document *Document `json:"document"` + // Message contains paid media; information about the paid media + PaidMedia PaidMediaInfo `json:"paid_media"` + // (Optional) Message is a photo, available sizes of the photo. Photo []Photo `json:"photo"`