all repos — telegram-bot-api @ f1ed87c281bce26d44a3143f9bff10f3ddc8b19c

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