From e1f4f1b228e5de71b385172c799261fdb8740206 Mon Sep 17 00:00:00 2001 From: Ian Byrd Date: Fri, 17 Nov 2017 15:10:18 +0200 Subject: [PATCH] Thumbnail -> Photo, new types supported: Voice, VideoNote. --- api.go | 4 ++ message.go | 46 +++++++++++++++--- types.go | 127 +++++++++++++++++++++++++------------------------- types_send.go | 48 +++++++++++++++++-- 4 files changed, 152 insertions(+), 73 deletions(-) diff --git a/api.go b/api.go index f5619db..5301560 100644 --- a/api.go +++ b/api.go @@ -97,6 +97,10 @@ func (b *Bot) sendFile(method, name, path string, params map[string]string) ([]b func (b *Bot) sendObject(f *File, what string, params map[string]string) (*Message, error) { sendWhat := "send" + strings.Title(what) + if what == "videoNote" { + what = "video_note" + } + var respJSON []byte var err error diff --git a/message.go b/message.go index 58a8090..113d868 100644 --- a/message.go +++ b/message.go @@ -11,7 +11,10 @@ type Message struct { // For message sent to channels, Sender will be nil Sender *User `json:"from"` - Unixtime int `json:"date"` + Unixtime int64 `json:"date"` + + // (Optional) Time of last edit in Unix + LastEdited int64 `json:"edit_date"` // For forwarded messages, sender of the original message. OriginalSender *User `json:"forward_from"` @@ -28,21 +31,30 @@ type Message struct { // itself is a reply. ReplyTo *Message `json:"reply_to_message"` - // For a text message, the actual UTF-8 text of the message + // For a text message, the actual UTF-8 text of the message. Text string `json:"text"` + // Author signature (in channels). + Signature string `json:"author_signature"` + // For an audio recording, information about it. Audio *Audio `json:"audio"` // For a general file, information about it. Document *Document `json:"document"` - // For a photo, available thumbnails. - Photo []Thumbnail `json:"photo"` + // For a photo, all available sizes (thumnails). + Photo []Photo `json:"photo"` // For a sticker, information about it. Sticker *Sticker `json:"sticker"` + // For a voice message, information about it. + Voice *Voice `json:"voice"` + + // For a video note, information about it. + VideoNote *VideoNote `json:"video_note"` + // For a video, information about it. Video *Video `json:"video"` @@ -82,7 +94,7 @@ type Message struct { // thumbnails of new chat photo. // // Sender would lead to a User, capable of change. - NewChatPhoto []Thumbnail `json:"new_chat_photo"` + NewChatPhoto []Photo `json:"new_chat_photo"` // For a service message, true if chat photo just // got removed. @@ -132,11 +144,33 @@ type Message struct { // Sender would lead to creator of the migration. MigrateFrom int64 `json:"migrate_from_chat_id"` - Entities []MessageEntity `json:"entities,omitempty"` + Entities []MessageEntity `json:"entities,omitempty"` + CaptionEntities []MessageEntity `json:"caption_entities,omitempty"` Caption string `json:"caption,omitempty"` } +// MessageEntity object represents "special" parts of text messages, +// including hashtags, usernames, URLs, etc. +type MessageEntity struct { + // Specifies entity type. + Type EntityType `json:"type"` + + // Offset in UTF-16 code units to the start of the entity. + Offset int `json:"offset"` + + // Length of the entity in UTF-16 code units. + Length int `json:"length"` + + // (Optional) For EntityTextLink entity type only. + // + // URL will be opened after user taps on the text. + URL string `json:"url,omitempty"` + + // (Optional) For EntityTMention entity type only. + User *User `json:"user,omitempty"` +} + // Origin returns an origin of message: group chat / personal. func (m *Message) Origin() *User { return m.Sender diff --git a/types.go b/types.go index cd6d0bf..72cb2b1 100644 --- a/types.go +++ b/types.go @@ -71,33 +71,23 @@ type Update struct { Query *Query `json:"inline_query"` } -// Thumbnail object represents an image/sticker of a particular size. -type Thumbnail struct { +// Photo object represents a photo (with or without caption). +type Photo struct { File Width int `json:"width"` Height int `json:"height"` -} - -// Photo object represents a photo with caption. -type Photo struct { - File - Thumbnail - - Caption string + Caption string `json:"caption,omitempty"` } -// Audio object represents an audio file (voice note). +// Audio object represents an audio file. type Audio struct { File // Duration of the recording in seconds as defined by sender. Duration int `json:"duration"` - // FileSize (optional) of the audio file. - FileSize int `json:"file_size"` - // Title (optional) as defined by sender or by audio tags. Title string `json:"title"` @@ -106,6 +96,21 @@ type Audio struct { // MIME type (optional) of the file as defined by sender. Mime string `json:"mime_type"` + + Caption string `json:"caption,omitempty"` +} + +// Voice object represents a voice note. +type Voice struct { + File + + // Duration of the recording in seconds as defined by sender. + Duration int `json:"duration"` + + // MIME type (optional) of the file as defined by sender. + Mime string `json:"mime_type"` + + Caption string `json:"caption,omitempty"` } // Document object represents a general file (as opposed to Photo or Audio). @@ -114,13 +119,15 @@ type Document struct { File // Document thumbnail as defined by sender. - Preview Thumbnail `json:"thumb"` + Preview Photo `json:"thumb"` // Original filename as defined by sender. FileName string `json:"file_name"` // MIME type of the file as defined by sender. Mime string `json:"mime_type"` + + Caption string `json:"caption,omitempty"` } // Sticker object represents a WebP image, so-called sticker. @@ -131,7 +138,10 @@ type Sticker struct { Height int `json:"height"` // Sticker thumbnail in .webp or .jpg format. - Preview Thumbnail `json:"thumb"` + Thumbnail Photo `json:"thumb"` + + // Associated emoji + Emoji string `json:"emoji"` } // Video object represents an MP4-encoded video. @@ -141,11 +151,46 @@ type Video struct { Width int `json:"width"` Height int `json:"height"` - // Text description of the video as defined by sender (usually empty). - Caption string `json:"caption"` + // Text description of the video as defined by sender. + Caption string `json:"caption,omitempty"` // Video thumbnail. - Preview Thumbnail `json:"thumb"` + Thumbnail Photo `json:"thumb"` +} + +// This object represents a video message (available in Telegram apps +// as of v.4.0). +type VideoNote struct { + File + + // Duration of the recording in seconds as defined by sender. + Duration int `json:"duration"` + + // Video note thumbnail. + Thumbnail Photo `json:"thumb"` +} + +// Contact object represents a contact to Telegram user +type Contact struct { + UserID int `json:"user_id"` + PhoneNumber string `json:"phone_number"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` +} + +// Location object represents geographic position. +type Location struct { + Lat float32 `json:"latitude"` + Lng float32 `json:"longitude"` +} + +// Venue object represents a venue location with name, address and +// optional foursquare ID. +type Venue struct { + Location Location `json:"location"` + Title string `json:"title"` + Address string `json:"address"` + FoursquareID string `json:"foursquare_id,omitempty"` } // KeyboardButton represents a button displayed on in a message. @@ -164,20 +209,6 @@ type InlineKeyboardMarkup struct { InlineKeyboard [][]KeyboardButton `json:"inline_keyboard,omitempty"` } -// Contact object represents a contact to Telegram user -type Contact struct { - UserID int `json:"user_id"` - PhoneNumber string `json:"phone_number"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` -} - -// Location object represents geographic position. -type Location struct { - Latitude float32 `json:"latitude"` - Longitude float32 `json:"longitude"` -} - // Callback object represents a query from a callback button in an // inline keyboard. type Callback struct { @@ -222,36 +253,6 @@ type CallbackResponse struct { URL string `json:"url,omitempty"` } -// Venue object represents a venue location with name, address and -// optional foursquare ID. -type Venue struct { - Location Location `json:"location"` - Title string `json:"title"` - Address string `json:"address"` - FoursquareID string `json:"foursquare_id,omitempty"` -} - -// MessageEntity object represents "special" parts of text messages, -// including hashtags, usernames, URLs, etc. -type MessageEntity struct { - // Specifies entity type. - Type EntityType `json:"type"` - - // Offset in UTF-16 code units to the start of the entity. - Offset int `json:"offset"` - - // Length of the entity in UTF-16 code units. - Length int `json:"length"` - - // (Optional) For EntityTextLink entity type only. - // - // URL will be opened after user taps on the text. - URL string `json:"url,omitempty"` - - // (Optional) For EntityTMention entity type only. - User *User `json:"user,omitempty"` -} - // ChatMember object represents information about a single chat member. type ChatMember struct { User User `json:"user"` diff --git a/types_send.go b/types_send.go index 4eb9c89..dcb8360 100644 --- a/types_send.go +++ b/types_send.go @@ -41,6 +41,7 @@ func (p *Photo) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { func (a *Audio) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { params := map[string]string{ "chat_id": to.Destination(), + "caption": a.Caption, } embedSendOptions(params, opt) @@ -59,6 +60,7 @@ func (a *Audio) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { func (d *Document) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { params := map[string]string{ "chat_id": to.Destination(), + "caption": d.Caption, } embedSendOptions(params, opt) @@ -95,6 +97,7 @@ func (s *Sticker) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) func (v *Video) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { params := map[string]string{ "chat_id": to.Destination(), + "caption": v.Caption, } embedSendOptions(params, opt) @@ -110,11 +113,48 @@ func (v *Video) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { return msg, nil } +func (v *Voice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { + params := map[string]string{ + "chat_id": to.Destination(), + "caption": v.Caption, + } + embedSendOptions(params, opt) + + msg, err := b.sendObject(&v.File, "voice", params) + if err != nil { + return nil, err + } + + fname := v.filename + *v = *msg.Voice + v.filename = fname + + return msg, nil +} + +func (v *VideoNote) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { + params := map[string]string{ + "chat_id": to.Destination(), + } + embedSendOptions(params, opt) + + msg, err := b.sendObject(&v.File, "videoNote", params) + if err != nil { + return nil, err + } + + fname := v.filename + *v = *msg.VideoNote + v.filename = fname + + return msg, nil +} + func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { params := map[string]string{ "chat_id": to.Destination(), - "latitude": fmt.Sprintf("%f", x.Latitude), - "longitude": fmt.Sprintf("%f", x.Longitude), + "latitude": fmt.Sprintf("%f", x.Lat), + "longitude": fmt.Sprintf("%f", x.Lng), } embedSendOptions(params, opt) @@ -129,8 +169,8 @@ func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error func (v *Venue) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { params := map[string]string{ "chat_id": to.Destination(), - "latitude": fmt.Sprintf("%f", v.Location.Latitude), - "longitude": fmt.Sprintf("%f", v.Location.Longitude), + "latitude": fmt.Sprintf("%f", v.Location.Lat), + "longitude": fmt.Sprintf("%f", v.Location.Lng), "title": v.Title, "address": v.Address, "foursquare_id": v.FoursquareID,