all repos — telegram-bot-api @ 80bdd621f775d115d6e781d9d2f91e79d0f41169

Golang bindings for the Telegram Bot API

types.go (view raw)

  1package tgbotapi
  2
  3import (
  4	"encoding/json"
  5	"errors"
  6	"fmt"
  7	"net/url"
  8	"strings"
  9	"time"
 10)
 11
 12// APIResponse is a response from the Telegram API with the result
 13// stored raw.
 14type APIResponse struct {
 15	Ok          bool                `json:"ok"`
 16	Result      json.RawMessage     `json:"result"`
 17	ErrorCode   int                 `json:"error_code"`
 18	Description string              `json:"description"`
 19	Parameters  *ResponseParameters `json:"parameters"`
 20}
 21
 22// ResponseParameters are various errors that can be returned in APIResponse.
 23type ResponseParameters struct {
 24	MigrateToChatID int64 `json:"migrate_to_chat_id"` // optional
 25	RetryAfter      int   `json:"retry_after"`        // optional
 26}
 27
 28// Update is an update response, from GetUpdates.
 29type Update struct {
 30	UpdateID           int                 `json:"update_id"`
 31	Message            *Message            `json:"message"`
 32	EditedMessage      *Message            `json:"edited_message"`
 33	ChannelPost        *Message            `json:"channel_post"`
 34	EditedChannelPost  *Message            `json:"edited_channel_post"`
 35	InlineQuery        *InlineQuery        `json:"inline_query"`
 36	ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"`
 37	CallbackQuery      *CallbackQuery      `json:"callback_query"`
 38}
 39
 40//updatesChannel is the channel for getting updates.
 41type updatesChannel <-chan Update
 42
 43//Clear discards all the actual incoming updates
 44func (ch updatesChannel) Clear() {
 45	for len(ch) != 0 {
 46		<-ch
 47	}
 48}
 49
 50// User is a user on Telegram.
 51type User struct {
 52	ID        int    `json:"id"`
 53	FirstName string `json:"first_name"`
 54	LastName  string `json:"last_name"` // optional
 55	UserName  string `json:"username"`  // optional
 56}
 57
 58// String displays a simple text version of a user.
 59//
 60// It is normally a user's username, but falls back to a first/last
 61// name as available.
 62func (u *User) String() string {
 63	if u.UserName != "" {
 64		return u.UserName
 65	}
 66
 67	name := u.FirstName
 68	if u.LastName != "" {
 69		name += " " + u.LastName
 70	}
 71
 72	return name
 73}
 74
 75// GroupChat is a group chat.
 76type GroupChat struct {
 77	ID    int    `json:"id"`
 78	Title string `json:"title"`
 79}
 80
 81// Chat contains information about the place a message was sent.
 82type Chat struct {
 83	ID                  int64  `json:"id"`
 84	Type                string `json:"type"`
 85	Title               string `json:"title"`                          // optional
 86	UserName            string `json:"username"`                       // optional
 87	FirstName           string `json:"first_name"`                     // optional
 88	LastName            string `json:"last_name"`                      // optional
 89	AllMembersAreAdmins bool   `json:"all_members_are_administrators"` // optional
 90}
 91
 92// IsPrivate returns if the Chat is a private conversation.
 93func (c Chat) IsPrivate() bool {
 94	return c.Type == "private"
 95}
 96
 97// IsGroup returns if the Chat is a group.
 98func (c Chat) IsGroup() bool {
 99	return c.Type == "group"
100}
101
102// IsSuperGroup returns if the Chat is a supergroup.
103func (c Chat) IsSuperGroup() bool {
104	return c.Type == "supergroup"
105}
106
107// IsChannel returns if the Chat is a channel.
108func (c Chat) IsChannel() bool {
109	return c.Type == "channel"
110}
111
112// ChatConfig returns a ChatConfig struct for chat related methods.
113func (c Chat) ChatConfig() ChatConfig {
114	return ChatConfig{ChatID: c.ID}
115}
116
117// Message is returned by almost every request, and contains data about
118// almost anything.
119type Message struct {
120	MessageID             int              `json:"message_id"`
121	From                  *User            `json:"from"` // optional
122	Date                  int              `json:"date"`
123	Chat                  *Chat            `json:"chat"`
124	ForwardFrom           *User            `json:"forward_from"`            // optional
125	ForwardFromChat       *Chat            `json:"forward_from_chat"`       // optional
126	ForwardFromMessageID  int              `json:"forward_from_message_id"` // optional
127	ForwardDate           int              `json:"forward_date"`            // optional
128	ReplyToMessage        *Message         `json:"reply_to_message"`        // optional
129	EditDate              int              `json:"edit_date"`               // optional
130	Text                  string           `json:"text"`                    // optional
131	Entities              *[]MessageEntity `json:"entities"`                // optional
132	Audio                 *Audio           `json:"audio"`                   // optional
133	Document              *Document        `json:"document"`                // optional
134	Game                  *Game            `json:"game"`                    // optional
135	Photo                 *[]PhotoSize     `json:"photo"`                   // optional
136	Sticker               *Sticker         `json:"sticker"`                 // optional
137	Video                 *Video           `json:"video"`                   // optional
138	Voice                 *Voice           `json:"voice"`                   // optional
139	Caption               string           `json:"caption"`                 // optional
140	Contact               *Contact         `json:"contact"`                 // optional
141	Location              *Location        `json:"location"`                // optional
142	Venue                 *Venue           `json:"venue"`                   // optional
143	NewChatMember         *User            `json:"new_chat_member"`         // optional
144	LeftChatMember        *User            `json:"left_chat_member"`        // optional
145	NewChatTitle          string           `json:"new_chat_title"`          // optional
146	NewChatPhoto          *[]PhotoSize     `json:"new_chat_photo"`          // optional
147	DeleteChatPhoto       bool             `json:"delete_chat_photo"`       // optional
148	GroupChatCreated      bool             `json:"group_chat_created"`      // optional
149	SuperGroupChatCreated bool             `json:"supergroup_chat_created"` // optional
150	ChannelChatCreated    bool             `json:"channel_chat_created"`    // optional
151	MigrateToChatID       int64            `json:"migrate_to_chat_id"`      // optional
152	MigrateFromChatID     int64            `json:"migrate_from_chat_id"`    // optional
153	PinnedMessage         *Message         `json:"pinned_message"`          // optional
154}
155
156// Time converts the message timestamp into a Time.
157func (m *Message) Time() time.Time {
158	return time.Unix(int64(m.Date), 0)
159}
160
161// IsCommand returns true if message starts with '/'.
162func (m *Message) IsCommand() bool {
163	return m.Text != "" && m.Text[0] == '/'
164}
165
166// Command checks if the message was a command and if it was, returns the
167// command. If the Message was not a command, it returns an empty string.
168//
169// If the command contains the at bot syntax, it removes the bot name.
170func (m *Message) Command() string {
171	if !m.IsCommand() {
172		return ""
173	}
174
175	command := strings.SplitN(m.Text, " ", 2)[0][1:]
176
177	if i := strings.Index(command, "@"); i != -1 {
178		command = command[:i]
179	}
180
181	return command
182}
183
184// CommandArguments checks if the message was a command and if it was,
185// returns all text after the command name. If the Message was not a
186// command, it returns an empty string.
187func (m *Message) CommandArguments() string {
188	if !m.IsCommand() {
189		return ""
190	}
191
192	split := strings.SplitN(m.Text, " ", 2)
193	if len(split) != 2 {
194		return ""
195	}
196
197	return strings.SplitN(m.Text, " ", 2)[1]
198}
199
200// MessageEntity contains information about data in a Message.
201type MessageEntity struct {
202	Type   string `json:"type"`
203	Offset int    `json:"offset"`
204	Length int    `json:"length"`
205	URL    string `json:"url"`  // optional
206	User   *User  `json:"user"` // optional
207}
208
209// ParseURL attempts to parse a URL contained within a MessageEntity.
210func (entity MessageEntity) ParseURL() (*url.URL, error) {
211	if entity.URL == "" {
212		return nil, errors.New(ErrBadURL)
213	}
214
215	return url.Parse(entity.URL)
216}
217
218// PhotoSize contains information about photos.
219type PhotoSize struct {
220	FileID   string `json:"file_id"`
221	Width    int    `json:"width"`
222	Height   int    `json:"height"`
223	FileSize int    `json:"file_size"` // optional
224}
225
226// Audio contains information about audio.
227type Audio struct {
228	FileID    string `json:"file_id"`
229	Duration  int    `json:"duration"`
230	Performer string `json:"performer"` // optional
231	Title     string `json:"title"`     // optional
232	MimeType  string `json:"mime_type"` // optional
233	FileSize  int    `json:"file_size"` // optional
234}
235
236// Document contains information about a document.
237type Document struct {
238	FileID    string     `json:"file_id"`
239	Thumbnail *PhotoSize `json:"thumb"`     // optional
240	FileName  string     `json:"file_name"` // optional
241	MimeType  string     `json:"mime_type"` // optional
242	FileSize  int        `json:"file_size"` // optional
243}
244
245// Sticker contains information about a sticker.
246type Sticker struct {
247	FileID    string     `json:"file_id"`
248	Width     int        `json:"width"`
249	Height    int        `json:"height"`
250	Thumbnail *PhotoSize `json:"thumb"`     // optional
251	Emoji     string     `json:"emoji"`     // optional
252	FileSize  int        `json:"file_size"` // optional
253}
254
255// Video contains information about a video.
256type Video struct {
257	FileID    string     `json:"file_id"`
258	Width     int        `json:"width"`
259	Height    int        `json:"height"`
260	Duration  int        `json:"duration"`
261	Thumbnail *PhotoSize `json:"thumb"`     // optional
262	MimeType  string     `json:"mime_type"` // optional
263	FileSize  int        `json:"file_size"` // optional
264}
265
266// Voice contains information about a voice.
267type Voice struct {
268	FileID   string `json:"file_id"`
269	Duration int    `json:"duration"`
270	MimeType string `json:"mime_type"` // optional
271	FileSize int    `json:"file_size"` // optional
272}
273
274// Contact contains information about a contact.
275//
276// Note that LastName and UserID may be empty.
277type Contact struct {
278	PhoneNumber string `json:"phone_number"`
279	FirstName   string `json:"first_name"`
280	LastName    string `json:"last_name"` // optional
281	UserID      int    `json:"user_id"`   // optional
282}
283
284// Location contains information about a place.
285type Location struct {
286	Longitude float64 `json:"longitude"`
287	Latitude  float64 `json:"latitude"`
288}
289
290// Venue contains information about a venue, including its Location.
291type Venue struct {
292	Location     Location `json:"location"`
293	Title        string   `json:"title"`
294	Address      string   `json:"address"`
295	FoursquareID string   `json:"foursquare_id"` // optional
296}
297
298// UserProfilePhotos contains a set of user profile photos.
299type UserProfilePhotos struct {
300	TotalCount int           `json:"total_count"`
301	Photos     [][]PhotoSize `json:"photos"`
302}
303
304// File contains information about a file to download from Telegram.
305type File struct {
306	FileID   string `json:"file_id"`
307	FileSize int    `json:"file_size"` // optional
308	FilePath string `json:"file_path"` // optional
309}
310
311// Link returns a full path to the download URL for a File.
312//
313// It requires the Bot Token to create the link.
314func (f *File) Link(token string) string {
315	return fmt.Sprintf(FileEndpoint, token, f.FilePath)
316}
317
318// ReplyKeyboardMarkup allows the Bot to set a custom keyboard.
319type ReplyKeyboardMarkup struct {
320	Keyboard        [][]KeyboardButton `json:"keyboard"`
321	ResizeKeyboard  bool               `json:"resize_keyboard"`   // optional
322	OneTimeKeyboard bool               `json:"one_time_keyboard"` // optional
323	Selective       bool               `json:"selective"`         // optional
324}
325
326// KeyboardButton is a button within a custom keyboard.
327type KeyboardButton struct {
328	Text            string `json:"text"`
329	RequestContact  bool   `json:"request_contact"`
330	RequestLocation bool   `json:"request_location"`
331}
332
333// ReplyKeyboardHide allows the Bot to hide a custom keyboard.
334type ReplyKeyboardHide struct {
335	HideKeyboard bool `json:"hide_keyboard"`
336	Selective    bool `json:"selective"` // optional
337}
338
339// ReplyKeyboardRemove allows the Bot to hide a custom keyboard.
340type ReplyKeyboardRemove struct {
341	RemoveKeyboard bool `json:"remove_keyboard"`
342	Selective      bool `json:"selective"`
343}
344
345// InlineKeyboardMarkup is a custom keyboard presented for an inline bot.
346type InlineKeyboardMarkup struct {
347	InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"`
348}
349
350// InlineKeyboardButton is a button within a custom keyboard for
351// inline query responses.
352//
353// Note that some values are references as even an empty string
354// will change behavior.
355//
356// CallbackGame, if set, MUST be first button in first row.
357type InlineKeyboardButton struct {
358	Text                         string        `json:"text"`
359	URL                          *string       `json:"url,omitempty"`                              // optional
360	CallbackData                 *string       `json:"callback_data,omitempty"`                    // optional
361	SwitchInlineQuery            *string       `json:"switch_inline_query,omitempty"`              // optional
362	SwitchInlineQueryCurrentChat *string       `json:"switch_inline_query_current_chat,omitempty"` // optional
363	CallbackGame                 *CallbackGame `json:"callback_game,omitempty"`                    // optional
364}
365
366// CallbackQuery is data sent when a keyboard button with callback data
367// is clicked.
368type CallbackQuery struct {
369	ID              string   `json:"id"`
370	From            *User    `json:"from"`
371	Message         *Message `json:"message"`           // optional
372	InlineMessageID string   `json:"inline_message_id"` // optional
373	ChatInstance    string   `json:"chat_instance"`
374	Data            string   `json:"data"`            // optional
375	GameShortName   string   `json:"game_short_name"` // optional
376}
377
378// ForceReply allows the Bot to have users directly reply to it without
379// additional interaction.
380type ForceReply struct {
381	ForceReply bool `json:"force_reply"`
382	Selective  bool `json:"selective"` // optional
383}
384
385// ChatMember is information about a member in a chat.
386type ChatMember struct {
387	User   *User  `json:"user"`
388	Status string `json:"status"`
389}
390
391// IsCreator returns if the ChatMember was the creator of the chat.
392func (chat ChatMember) IsCreator() bool { return chat.Status == "creator" }
393
394// IsAdministrator returns if the ChatMember is a chat administrator.
395func (chat ChatMember) IsAdministrator() bool { return chat.Status == "administrator" }
396
397// IsMember returns if the ChatMember is a current member of the chat.
398func (chat ChatMember) IsMember() bool { return chat.Status == "member" }
399
400// HasLeft returns if the ChatMember left the chat.
401func (chat ChatMember) HasLeft() bool { return chat.Status == "left" }
402
403// WasKicked returns if the ChatMember was kicked from the chat.
404func (chat ChatMember) WasKicked() bool { return chat.Status == "kicked" }
405
406// Game is a game within Telegram.
407type Game struct {
408	Title        string          `json:"title"`
409	Description  string          `json:"description"`
410	Photo        []PhotoSize     `json:"photo"`
411	Text         string          `json:"text"`
412	TextEntities []MessageEntity `json:"text_entities"`
413	Animation    Animation       `json:"animation"`
414}
415
416// Animation is a GIF animation demonstrating the game.
417type Animation struct {
418	FileID   string    `json:"file_id"`
419	Thumb    PhotoSize `json:"thumb"`
420	FileName string    `json:"file_name"`
421	MimeType string    `json:"mime_type"`
422	FileSize int       `json:"file_size"`
423}
424
425// GameHighScore is a user's score and position on the leaderboard.
426type GameHighScore struct {
427	Position int  `json:"position"`
428	User     User `json:"user"`
429	Score    int  `json:"score"`
430}
431
432// CallbackGame is for starting a game in an inline keyboard button.
433type CallbackGame struct{}
434
435// WebhookInfo is information about a currently set webhook.
436type WebhookInfo struct {
437	URL                  string `json:"url"`
438	HasCustomCertificate bool   `json:"has_custom_certificate"`
439	PendingUpdateCount   int    `json:"pending_update_count"`
440	LastErrorDate        int    `json:"last_error_date"`    // optional
441	LastErrorMessage     string `json:"last_error_message"` // optional
442}
443
444// IsSet returns true if a webhook is currently set.
445func (info WebhookInfo) IsSet() bool {
446	return info.URL != ""
447}
448
449// InlineQuery is a Query from Telegram for an inline request.
450type InlineQuery struct {
451	ID       string    `json:"id"`
452	From     *User     `json:"from"`
453	Location *Location `json:"location"` // optional
454	Query    string    `json:"query"`
455	Offset   string    `json:"offset"`
456}
457
458// InlineQueryResultArticle is an inline query response article.
459type InlineQueryResultArticle struct {
460	Type                string                `json:"type"`                            // required
461	ID                  string                `json:"id"`                              // required
462	Title               string                `json:"title"`                           // required
463	InputMessageContent interface{}           `json:"input_message_content,omitempty"` // required
464	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
465	URL                 string                `json:"url"`
466	HideURL             bool                  `json:"hide_url"`
467	Description         string                `json:"description"`
468	ThumbURL            string                `json:"thumb_url"`
469	ThumbWidth          int                   `json:"thumb_width"`
470	ThumbHeight         int                   `json:"thumb_height"`
471}
472
473// InlineQueryResultPhoto is an inline query response photo.
474type InlineQueryResultPhoto struct {
475	Type                string                `json:"type"`      // required
476	ID                  string                `json:"id"`        // required
477	URL                 string                `json:"photo_url"` // required
478	MimeType            string                `json:"mime_type"`
479	Width               int                   `json:"photo_width"`
480	Height              int                   `json:"photo_height"`
481	ThumbURL            string                `json:"thumb_url"`
482	Title               string                `json:"title"`
483	Description         string                `json:"description"`
484	Caption             string                `json:"caption"`
485	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
486	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
487}
488
489// InlineQueryResultGIF is an inline query response GIF.
490type InlineQueryResultGIF struct {
491	Type                string                `json:"type"`    // required
492	ID                  string                `json:"id"`      // required
493	URL                 string                `json:"gif_url"` // required
494	Width               int                   `json:"gif_width"`
495	Height              int                   `json:"gif_height"`
496	ThumbURL            string                `json:"thumb_url"`
497	Title               string                `json:"title"`
498	Caption             string                `json:"caption"`
499	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
500	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
501}
502
503// InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF.
504type InlineQueryResultMPEG4GIF struct {
505	Type                string                `json:"type"`      // required
506	ID                  string                `json:"id"`        // required
507	URL                 string                `json:"mpeg4_url"` // required
508	Width               int                   `json:"mpeg4_width"`
509	Height              int                   `json:"mpeg4_height"`
510	ThumbURL            string                `json:"thumb_url"`
511	Title               string                `json:"title"`
512	Caption             string                `json:"caption"`
513	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
514	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
515}
516
517// InlineQueryResultVideo is an inline query response video.
518type InlineQueryResultVideo struct {
519	Type                string                `json:"type"`      // required
520	ID                  string                `json:"id"`        // required
521	URL                 string                `json:"video_url"` // required
522	MimeType            string                `json:"mime_type"` // required
523	ThumbURL            string                `json:"thumb_url"`
524	Title               string                `json:"title"`
525	Caption             string                `json:"caption"`
526	Width               int                   `json:"video_width"`
527	Height              int                   `json:"video_height"`
528	Duration            int                   `json:"video_duration"`
529	Description         string                `json:"description"`
530	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
531	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
532}
533
534// InlineQueryResultAudio is an inline query response audio.
535type InlineQueryResultAudio struct {
536	Type                string                `json:"type"`      // required
537	ID                  string                `json:"id"`        // required
538	URL                 string                `json:"audio_url"` // required
539	Title               string                `json:"title"`     // required
540	Caption             string                `json:"caption"`
541	Performer           string                `json:"performer"`
542	Duration            int                   `json:"audio_duration"`
543	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
544	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
545}
546
547// InlineQueryResultVoice is an inline query response voice.
548type InlineQueryResultVoice struct {
549	Type                string                `json:"type"`      // required
550	ID                  string                `json:"id"`        // required
551	URL                 string                `json:"voice_url"` // required
552	Title               string                `json:"title"`     // required
553	Caption             string                `json:"caption"`
554	Duration            int                   `json:"voice_duration"`
555	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
556	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
557}
558
559// InlineQueryResultDocument is an inline query response document.
560type InlineQueryResultDocument struct {
561	Type                string                `json:"type"`  // required
562	ID                  string                `json:"id"`    // required
563	Title               string                `json:"title"` // required
564	Caption             string                `json:"caption"`
565	URL                 string                `json:"document_url"` // required
566	MimeType            string                `json:"mime_type"`    // required
567	Description         string                `json:"description"`
568	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
569	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
570	ThumbURL            string                `json:"thumb_url"`
571	ThumbWidth          int                   `json:"thumb_width"`
572	ThumbHeight         int                   `json:"thumb_height"`
573}
574
575// InlineQueryResultLocation is an inline query response location.
576type InlineQueryResultLocation struct {
577	Type                string                `json:"type"`      // required
578	ID                  string                `json:"id"`        // required
579	Latitude            float64               `json:"latitude"`  // required
580	Longitude           float64               `json:"longitude"` // required
581	Title               string                `json:"title"`     // required
582	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
583	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
584	ThumbURL            string                `json:"thumb_url"`
585	ThumbWidth          int                   `json:"thumb_width"`
586	ThumbHeight         int                   `json:"thumb_height"`
587}
588
589// InlineQueryResultGame is an inline query response game.
590type InlineQueryResultGame struct {
591	Type          string                `json:"type"`
592	ID            string                `json:"id"`
593	GameShortName string                `json:"game_short_name"`
594	ReplyMarkup   *InlineKeyboardMarkup `json:"reply_markup"`
595}
596
597// ChosenInlineResult is an inline query result chosen by a User
598type ChosenInlineResult struct {
599	ResultID        string    `json:"result_id"`
600	From            *User     `json:"from"`
601	Location        *Location `json:"location"`
602	InlineMessageID string    `json:"inline_message_id"`
603	Query           string    `json:"query"`
604}
605
606// InputTextMessageContent contains text for displaying
607// as an inline query result.
608type InputTextMessageContent struct {
609	Text                  string `json:"message_text"`
610	ParseMode             string `json:"parse_mode"`
611	DisableWebPagePreview bool   `json:"disable_web_page_preview"`
612}
613
614// InputLocationMessageContent contains a location for displaying
615// as an inline query result.
616type InputLocationMessageContent struct {
617	Latitude  float64 `json:"latitude"`
618	Longitude float64 `json:"longitude"`
619}
620
621// InputVenueMessageContent contains a venue for displaying
622// as an inline query result.
623type InputVenueMessageContent struct {
624	Latitude     float64 `json:"latitude"`
625	Longitude    float64 `json:"longitude"`
626	Title        string  `json:"title"`
627	Address      string  `json:"address"`
628	FoursquareID string  `json:"foursquare_id"`
629}
630
631// InputContactMessageContent contains a contact for displaying
632// as an inline query result.
633type InputContactMessageContent struct {
634	PhoneNumber string `json:"phone_number"`
635	FirstName   string `json:"first_name"`
636	LastName    string `json:"last_name"`
637}