all repos — telegram-bot-api @ 30c412fbe58ee9e0353028213807b01090f9565c

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 is the update's unique identifier.
  31	// Update identifiers start from a certain positive number and increase sequentially.
  32	// This ID becomes especially handy if you're using Webhooks,
  33	// since it allows you to ignore repeated updates or to restore
  34	// the correct update sequence, should they get out of order.
  35	// If there are no new updates for at least a week, then identifier
  36	// of the next update will be chosen randomly instead of sequentially.
  37	UpdateID int `json:"update_id"`
  38	// Message new incoming message of any kind — text, photo, sticker, etc.
  39	// optional
  40	Message *Message `json:"message"`
  41	// EditedMessage
  42	// optional
  43	EditedMessage *Message `json:"edited_message"`
  44	// ChannelPost new version of a message that is known to the bot and was edited
  45	// optional
  46	ChannelPost *Message `json:"channel_post"`
  47	// EditedChannelPost new incoming channel post of any kind — text, photo, sticker, etc.
  48	// optional
  49	EditedChannelPost *Message `json:"edited_channel_post"`
  50	// InlineQuery new incoming inline query
  51	// optional
  52	InlineQuery *InlineQuery `json:"inline_query"`
  53	// ChosenInlineResult is the result of an inline query
  54	// that was chosen by a user and sent to their chat partner.
  55	// Please see our documentation on the feedback collecting
  56	// for details on how to enable these updates for your bot.
  57	// optional
  58	ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"`
  59	// CallbackQuery new incoming callback query
  60	// optional
  61	CallbackQuery *CallbackQuery `json:"callback_query"`
  62	// ShippingQuery new incoming shipping query. Only for invoices with flexible price
  63	// optional
  64	ShippingQuery *ShippingQuery `json:"shipping_query"`
  65	// PreCheckoutQuery new incoming pre-checkout query. Contains full information about checkout
  66	// optional
  67	PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query"`
  68}
  69
  70// UpdatesChannel is the channel for getting updates.
  71type UpdatesChannel <-chan Update
  72
  73// Clear discards all unprocessed incoming updates.
  74func (ch UpdatesChannel) Clear() {
  75	for len(ch) != 0 {
  76		<-ch
  77	}
  78}
  79
  80// User represents a Telegram user or bot.
  81type User struct {
  82	// ID is a unique identifier for this user or bot
  83	ID int `json:"id"`
  84	// FirstName user's or bot's first name
  85	FirstName string `json:"first_name"`
  86	// LastName user's or bot's last name
  87	// optional
  88	LastName string `json:"last_name"`
  89	// UserName user's or bot's username
  90	// optional
  91	UserName string `json:"username"`
  92	// LanguageCode IETF language tag of the user's language
  93	// more info: https://en.wikipedia.org/wiki/IETF_language_tag
  94	// optional
  95	LanguageCode string `json:"language_code"`
  96	// IsBot true, if this user is a bot
  97	// optional
  98	IsBot bool `json:"is_bot"`
  99}
 100
 101// String displays a simple text version of a user.
 102//
 103// It is normally a user's username, but falls back to a first/last
 104// name as available.
 105func (u *User) String() string {
 106	if u == nil {
 107		return ""
 108	}
 109	if u.UserName != "" {
 110		return u.UserName
 111	}
 112
 113	name := u.FirstName
 114	if u.LastName != "" {
 115		name += " " + u.LastName
 116	}
 117
 118	return name
 119}
 120
 121// GroupChat is a group chat.
 122type GroupChat struct {
 123	ID    int    `json:"id"`
 124	Title string `json:"title"`
 125}
 126
 127// ChatPhoto represents a chat photo.
 128type ChatPhoto struct {
 129	// SmallFileID is a file identifier of small (160x160) chat photo.
 130	// This file_id can be used only for photo download and
 131	// only for as long as the photo is not changed.
 132	SmallFileID string `json:"small_file_id"`
 133	// BigFileID is a file identifier of big (640x640) chat photo.
 134	// This file_id can be used only for photo download and
 135	// only for as long as the photo is not changed.
 136	BigFileID string `json:"big_file_id"`
 137}
 138
 139// Chat contains information about the place a message was sent.
 140type Chat struct {
 141	// ID is a unique identifier for this chat
 142	ID int64 `json:"id"`
 143	// Type of chat, can be either “private”, “group”, “supergroup” or “channel”
 144	Type string `json:"type"`
 145	// Title for supergroups, channels and group chats
 146	// optional
 147	Title string `json:"title"`
 148	// UserName for private chats, supergroups and channels if available
 149	// optional
 150	UserName string `json:"username"`
 151	// FirstName of the other party in a private chat
 152	// optional
 153	FirstName string `json:"first_name"`
 154	// LastName of the other party in a private chat
 155	// optional
 156	LastName string `json:"last_name"`
 157	// AllMembersAreAdmins
 158	// optional
 159	AllMembersAreAdmins bool `json:"all_members_are_administrators"`
 160	// Photo is a chat photo
 161	Photo *ChatPhoto `json:"photo"`
 162	// Description for groups, supergroups and channel chats
 163	// optional
 164	Description string `json:"description,omitempty"`
 165	// InviteLink is a chat invite link, for groups, supergroups and channel chats.
 166	// Each administrator in a chat generates their own invite links,
 167	// so the bot must first generate the link using exportChatInviteLink
 168	// optional
 169	InviteLink string `json:"invite_link,omitempty"`
 170	// PinnedMessage Pinned message, for groups, supergroups and channels
 171	// optional
 172	PinnedMessage *Message `json:"pinned_message"`
 173}
 174
 175// IsPrivate returns if the Chat is a private conversation.
 176func (c Chat) IsPrivate() bool {
 177	return c.Type == "private"
 178}
 179
 180// IsGroup returns if the Chat is a group.
 181func (c Chat) IsGroup() bool {
 182	return c.Type == "group"
 183}
 184
 185// IsSuperGroup returns if the Chat is a supergroup.
 186func (c Chat) IsSuperGroup() bool {
 187	return c.Type == "supergroup"
 188}
 189
 190// IsChannel returns if the Chat is a channel.
 191func (c Chat) IsChannel() bool {
 192	return c.Type == "channel"
 193}
 194
 195// ChatConfig returns a ChatConfig struct for chat related methods.
 196func (c Chat) ChatConfig() ChatConfig {
 197	return ChatConfig{ChatID: c.ID}
 198}
 199
 200// Message is returned by almost every request, and contains data about
 201// almost anything.
 202type Message struct {
 203	// MessageID is a unique message identifier inside this chat
 204	MessageID int `json:"message_id"`
 205	// From is a sender, empty for messages sent to channels;
 206	// optional
 207	From *User `json:"from"`
 208	// Date of the message was sent in Unix time
 209	Date int `json:"date"`
 210	// Chat is the conversation the message belongs to
 211	Chat *Chat `json:"chat"`
 212	// ForwardFrom for forwarded messages, sender of the original message;
 213	// optional
 214	ForwardFrom *User `json:"forward_from"`
 215	// ForwardFromChat for messages forwarded from channels,
 216	// information about the original channel;
 217	// optional
 218	ForwardFromChat *Chat `json:"forward_from_chat"`
 219	// ForwardFromMessageID for messages forwarded from channels,
 220	// identifier of the original message in the channel;
 221	// optional
 222	ForwardFromMessageID int `json:"forward_from_message_id"`
 223	// ForwardDate for forwarded messages, date the original message was sent in Unix time;
 224	// optional
 225	ForwardDate int `json:"forward_date"`
 226	// ReplyToMessage for replies, the original message.
 227	// Note that the Message object in this field will not contain further ReplyToMessage fields
 228	// even if it itself is a reply;
 229	// optional
 230	ReplyToMessage *Message `json:"reply_to_message"`
 231	// ViaBot through which the message was sent;
 232	// optional
 233	ViaBot *User `json:"via_bot"`
 234	// EditDate of the message was last edited in Unix time;
 235	// optional
 236	EditDate int `json:"edit_date"`
 237	// MediaGroupID is the unique identifier of a media message group this message belongs to;
 238	// optional
 239	MediaGroupID string `json:"media_group_id"`
 240	// AuthorSignature is the signature of the post author for messages in channels;
 241	// optional
 242	AuthorSignature string `json:"author_signature"`
 243	// Text is for text messages, the actual UTF-8 text of the message, 0-4096 characters;
 244	// optional
 245	Text string `json:"text"`
 246	// Entities is for text messages, special entities like usernames,
 247	// URLs, bot commands, etc. that appear in the text;
 248	// optional
 249	Entities *[]MessageEntity `json:"entities"`
 250	// CaptionEntities;
 251	// optional
 252	CaptionEntities *[]MessageEntity `json:"caption_entities"`
 253	// Audio message is an audio file, information about the file;
 254	// optional
 255	Audio *Audio `json:"audio"`
 256	// Document message is a general file, information about the file;
 257	// optional
 258	Document *Document `json:"document"`
 259	// Animation message is an animation, information about the animation.
 260	// For backward compatibility, when this field is set, the document field will also be set;
 261	// optional
 262	Animation *ChatAnimation `json:"animation"`
 263	// Game message is a game, information about the game;
 264	// optional
 265	Game *Game `json:"game"`
 266	// Photo message is a photo, available sizes of the photo;
 267	// optional
 268	Photo *[]PhotoSize `json:"photo"`
 269	// Sticker message is a sticker, information about the sticker;
 270	// optional
 271	Sticker *Sticker `json:"sticker"`
 272	// Video message is a video, information about the video;
 273	// optional
 274	Video *Video `json:"video"`
 275	// VideoNote message is a video note, information about the video message;
 276	// optional
 277	VideoNote *VideoNote `json:"video_note"`
 278	// Voice message is a voice message, information about the file;
 279	// optional
 280	Voice *Voice `json:"voice"`
 281	// Caption for the animation, audio, document, photo, video or voice, 0-1024 characters;
 282	// optional
 283	Caption string `json:"caption"`
 284	// Contact message is a shared contact, information about the contact;
 285	// optional
 286	Contact *Contact `json:"contact"`
 287	// Location message is a shared location, information about the location;
 288	// optional
 289	Location *Location `json:"location"`
 290	// Venue message is a venue, information about the venue.
 291	// For backward compatibility, when this field is set, the location field will also be set;
 292	// optional
 293	Venue *Venue `json:"venue"`
 294	// NewChatMembers that were added to the group or supergroup
 295	// and information about them (the bot itself may be one of these members);
 296	// optional
 297	NewChatMembers *[]User `json:"new_chat_members"`
 298	// LeftChatMember is a member was removed from the group,
 299	// information about them (this member may be the bot itself);
 300	// optional
 301	LeftChatMember *User `json:"left_chat_member"`
 302	// NewChatTitle is a chat title was changed to this value;
 303	// optional
 304	NewChatTitle string `json:"new_chat_title"`
 305	// NewChatPhoto is a chat photo was change to this value;
 306	// optional
 307	NewChatPhoto *[]PhotoSize `json:"new_chat_photo"`
 308	// DeleteChatPhoto is a service message: the chat photo was deleted;
 309	// optional
 310	DeleteChatPhoto bool `json:"delete_chat_photo"`
 311	// GroupChatCreated is a service message: the group has been created;
 312	// optional
 313	GroupChatCreated bool `json:"group_chat_created"`
 314	// SuperGroupChatCreated is a service message: the supergroup has been created.
 315	// This field can't be received in a message coming through updates,
 316	// because bot can't be a member of a supergroup when it is created.
 317	// It can only be found in ReplyToMessage if someone replies to a very first message
 318	// in a directly created supergroup;
 319	// optional
 320	SuperGroupChatCreated bool `json:"supergroup_chat_created"`
 321	// ChannelChatCreated is a service message: the channel has been created.
 322	// This field can't be received in a message coming through updates,
 323	// because bot can't be a member of a channel when it is created.
 324	// It can only be found in ReplyToMessage
 325	// if someone replies to a very first message in a channel;
 326	// optional
 327	ChannelChatCreated bool `json:"channel_chat_created"`
 328	// MigrateToChatID is the group has been migrated to a supergroup with the specified identifier.
 329	// This number may be greater than 32 bits and some programming languages
 330	// may have difficulty/silent defects in interpreting it.
 331	// But it is smaller than 52 bits, so a signed 64 bit integer
 332	// or double-precision float type are safe for storing this identifier;
 333	// optional
 334	MigrateToChatID int64 `json:"migrate_to_chat_id"`
 335	// MigrateFromChatID is the supergroup has been migrated from a group with the specified identifier.
 336	// This number may be greater than 32 bits and some programming languages
 337	// may have difficulty/silent defects in interpreting it.
 338	// But it is smaller than 52 bits, so a signed 64 bit integer
 339	// or double-precision float type are safe for storing this identifier;
 340	// optional
 341	MigrateFromChatID int64 `json:"migrate_from_chat_id"`
 342	// PinnedMessage is a specified message was pinned.
 343	// Note that the Message object in this field will not contain further ReplyToMessage
 344	// fields even if it is itself a reply;
 345	// optional
 346	PinnedMessage *Message `json:"pinned_message"`
 347	// Invoice message is an invoice for a payment;
 348	// optional
 349	Invoice *Invoice `json:"invoice"`
 350	// SuccessfulPayment message is a service message about a successful payment,
 351	// information about the payment;
 352	// optional
 353	SuccessfulPayment *SuccessfulPayment `json:"successful_payment"`
 354	// PassportData is a Telegram Passport data;
 355	// optional
 356	PassportData *PassportData `json:"passport_data,omitempty"`
 357}
 358
 359// Time converts the message timestamp into a Time.
 360func (m *Message) Time() time.Time {
 361	return time.Unix(int64(m.Date), 0)
 362}
 363
 364// IsCommand returns true if message starts with a "bot_command" entity.
 365func (m *Message) IsCommand() bool {
 366	if m.Entities == nil || len(*m.Entities) == 0 {
 367		return false
 368	}
 369
 370	entity := (*m.Entities)[0]
 371	return entity.Offset == 0 && entity.IsCommand()
 372}
 373
 374// Command checks if the message was a command and if it was, returns the
 375// command. If the Message was not a command, it returns an empty string.
 376//
 377// If the command contains the at name syntax, it is removed. Use
 378// CommandWithAt() if you do not want that.
 379func (m *Message) Command() string {
 380	command := m.CommandWithAt()
 381
 382	if i := strings.Index(command, "@"); i != -1 {
 383		command = command[:i]
 384	}
 385
 386	return command
 387}
 388
 389// CommandWithAt checks if the message was a command and if it was, returns the
 390// command. If the Message was not a command, it returns an empty string.
 391//
 392// If the command contains the at name syntax, it is not removed. Use Command()
 393// if you want that.
 394func (m *Message) CommandWithAt() string {
 395	if !m.IsCommand() {
 396		return ""
 397	}
 398
 399	// IsCommand() checks that the message begins with a bot_command entity
 400	entity := (*m.Entities)[0]
 401	return m.Text[1:entity.Length]
 402}
 403
 404// CommandArguments checks if the message was a command and if it was,
 405// returns all text after the command name. If the Message was not a
 406// command, it returns an empty string.
 407//
 408// Note: The first character after the command name is omitted:
 409// - "/foo bar baz" yields "bar baz", not " bar baz"
 410// - "/foo-bar baz" yields "bar baz", too
 411// Even though the latter is not a command conforming to the spec, the API
 412// marks "/foo" as command entity.
 413func (m *Message) CommandArguments() string {
 414	if !m.IsCommand() {
 415		return ""
 416	}
 417
 418	// IsCommand() checks that the message begins with a bot_command entity
 419	entity := (*m.Entities)[0]
 420	if len(m.Text) == entity.Length {
 421		return "" // The command makes up the whole message
 422	}
 423
 424	return m.Text[entity.Length+1:]
 425}
 426
 427// MessageEntity contains information about data in a Message.
 428type MessageEntity struct {
 429	// Type of the entity.
 430	// Can be:
 431	//  “mention” (@username),
 432	//  “hashtag” (#hashtag),
 433	//  “cashtag” ($USD),
 434	//  “bot_command” (/start@jobs_bot),
 435	//  “url” (https://telegram.org),
 436	//  “email” (do-not-reply@telegram.org),
 437	//  “phone_number” (+1-212-555-0123),
 438	//  “bold” (bold text),
 439	//  “italic” (italic text),
 440	//  “underline” (underlined text),
 441	//  “strikethrough” (strikethrough text),
 442	//  “code” (monowidth string),
 443	//  “pre” (monowidth block),
 444	//  “text_link” (for clickable text URLs),
 445	//  “text_mention” (for users without usernames)
 446	Type string `json:"type"`
 447	// Offset in UTF-16 code units to the start of the entity
 448	Offset int `json:"offset"`
 449	// Length
 450	Length int `json:"length"`
 451	// URL for “text_link” only, url that will be opened after user taps on the text
 452	// optional
 453	URL string `json:"url"`
 454	// User for “text_mention” only, the mentioned user
 455	// optional
 456	User *User `json:"user"`
 457}
 458
 459// ParseURL attempts to parse a URL contained within a MessageEntity.
 460func (e MessageEntity) ParseURL() (*url.URL, error) {
 461	if e.URL == "" {
 462		return nil, errors.New(ErrBadURL)
 463	}
 464
 465	return url.Parse(e.URL)
 466}
 467
 468// IsMention returns true if the type of the message entity is "mention" (@username).
 469func (e MessageEntity) IsMention() bool {
 470	return e.Type == "mention"
 471}
 472
 473// IsHashtag returns true if the type of the message entity is "hashtag".
 474func (e MessageEntity) IsHashtag() bool {
 475	return e.Type == "hashtag"
 476}
 477
 478// IsCommand returns true if the type of the message entity is "bot_command".
 479func (e MessageEntity) IsCommand() bool {
 480	return e.Type == "bot_command"
 481}
 482
 483// IsUrl returns true if the type of the message entity is "url".
 484func (e MessageEntity) IsUrl() bool {
 485	return e.Type == "url"
 486}
 487
 488// IsEmail returns true if the type of the message entity is "email".
 489func (e MessageEntity) IsEmail() bool {
 490	return e.Type == "email"
 491}
 492
 493// IsBold returns true if the type of the message entity is "bold" (bold text).
 494func (e MessageEntity) IsBold() bool {
 495	return e.Type == "bold"
 496}
 497
 498// IsItalic returns true if the type of the message entity is "italic" (italic text).
 499func (e MessageEntity) IsItalic() bool {
 500	return e.Type == "italic"
 501}
 502
 503// IsCode returns true if the type of the message entity is "code" (monowidth string).
 504func (e MessageEntity) IsCode() bool {
 505	return e.Type == "code"
 506}
 507
 508// IsPre returns true if the type of the message entity is "pre" (monowidth block).
 509func (e MessageEntity) IsPre() bool {
 510	return e.Type == "pre"
 511}
 512
 513// IsTextLink returns true if the type of the message entity is "text_link" (clickable text URL).
 514func (e MessageEntity) IsTextLink() bool {
 515	return e.Type == "text_link"
 516}
 517
 518// PhotoSize contains information about photos.
 519type PhotoSize struct {
 520	FileID   string `json:"file_id"`
 521	Width    int    `json:"width"`
 522	Height   int    `json:"height"`
 523	FileSize int    `json:"file_size"` // optional
 524}
 525
 526// Audio contains information about audio.
 527type Audio struct {
 528	FileID    string `json:"file_id"`
 529	Duration  int    `json:"duration"`
 530	Performer string `json:"performer"` // optional
 531	Title     string `json:"title"`     // optional
 532	MimeType  string `json:"mime_type"` // optional
 533	FileSize  int    `json:"file_size"` // optional
 534}
 535
 536// Document contains information about a document.
 537type Document struct {
 538	FileID    string     `json:"file_id"`
 539	Thumbnail *PhotoSize `json:"thumb"`     // optional
 540	FileName  string     `json:"file_name"` // optional
 541	MimeType  string     `json:"mime_type"` // optional
 542	FileSize  int        `json:"file_size"` // optional
 543}
 544
 545// Sticker contains information about a sticker.
 546type Sticker struct {
 547	FileUniqueID string     `json:"file_unique_id"`
 548	FileID       string     `json:"file_id"`
 549	Width        int        `json:"width"`
 550	Height       int        `json:"height"`
 551	Thumbnail    *PhotoSize `json:"thumb"`       // optional
 552	Emoji        string     `json:"emoji"`       // optional
 553	FileSize     int        `json:"file_size"`   // optional
 554	SetName      string     `json:"set_name"`    // optional
 555	IsAnimated   bool       `json:"is_animated"` // optional
 556}
 557
 558// StickerSet contains information about an sticker set.
 559type StickerSet struct {
 560	Name          string    `json:"name"`
 561	Title         string    `json:"title"`
 562	IsAnimated    bool      `json:"is_animated"`
 563	ContainsMasks bool      `json:"contains_masks"`
 564	Stickers      []Sticker `json:"stickers"`
 565}
 566
 567// ChatAnimation contains information about an animation.
 568type ChatAnimation struct {
 569	FileID    string     `json:"file_id"`
 570	Width     int        `json:"width"`
 571	Height    int        `json:"height"`
 572	Duration  int        `json:"duration"`
 573	Thumbnail *PhotoSize `json:"thumb"`     // optional
 574	FileName  string     `json:"file_name"` // optional
 575	MimeType  string     `json:"mime_type"` // optional
 576	FileSize  int        `json:"file_size"` // optional
 577}
 578
 579// Video contains information about a video.
 580type Video struct {
 581	FileID    string     `json:"file_id"`
 582	Width     int        `json:"width"`
 583	Height    int        `json:"height"`
 584	Duration  int        `json:"duration"`
 585	Thumbnail *PhotoSize `json:"thumb"`     // optional
 586	MimeType  string     `json:"mime_type"` // optional
 587	FileSize  int        `json:"file_size"` // optional
 588}
 589
 590// VideoNote contains information about a video.
 591type VideoNote struct {
 592	FileID    string     `json:"file_id"`
 593	Length    int        `json:"length"`
 594	Duration  int        `json:"duration"`
 595	Thumbnail *PhotoSize `json:"thumb"`     // optional
 596	FileSize  int        `json:"file_size"` // optional
 597}
 598
 599// Voice contains information about a voice.
 600type Voice struct {
 601	FileID   string `json:"file_id"`
 602	Duration int    `json:"duration"`
 603	MimeType string `json:"mime_type"` // optional
 604	FileSize int    `json:"file_size"` // optional
 605}
 606
 607// Contact contains information about a contact.
 608//
 609// Note that LastName and UserID may be empty.
 610type Contact struct {
 611	PhoneNumber string `json:"phone_number"`
 612	FirstName   string `json:"first_name"`
 613	LastName    string `json:"last_name"` // optional
 614	UserID      int    `json:"user_id"`   // optional
 615}
 616
 617// Location contains information about a place.
 618type Location struct {
 619	Longitude float64 `json:"longitude"`
 620	Latitude  float64 `json:"latitude"`
 621}
 622
 623// Venue contains information about a venue, including its Location.
 624type Venue struct {
 625	Location     Location `json:"location"`
 626	Title        string   `json:"title"`
 627	Address      string   `json:"address"`
 628	FoursquareID string   `json:"foursquare_id"` // optional
 629}
 630
 631// UserProfilePhotos contains a set of user profile photos.
 632type UserProfilePhotos struct {
 633	TotalCount int           `json:"total_count"`
 634	Photos     [][]PhotoSize `json:"photos"`
 635}
 636
 637// File contains information about a file to download from Telegram.
 638type File struct {
 639	FileID   string `json:"file_id"`
 640	FileSize int    `json:"file_size"` // optional
 641	FilePath string `json:"file_path"` // optional
 642}
 643
 644// Link returns a full path to the download URL for a File.
 645//
 646// It requires the Bot Token to create the link.
 647func (f *File) Link(token string) string {
 648	return fmt.Sprintf(FileEndpoint, token, f.FilePath)
 649}
 650
 651// ReplyKeyboardMarkup allows the Bot to set a custom keyboard.
 652type ReplyKeyboardMarkup struct {
 653	Keyboard        [][]KeyboardButton `json:"keyboard"`
 654	ResizeKeyboard  bool               `json:"resize_keyboard"`   // optional
 655	OneTimeKeyboard bool               `json:"one_time_keyboard"` // optional
 656	Selective       bool               `json:"selective"`         // optional
 657}
 658
 659// KeyboardButton is a button within a custom keyboard.
 660type KeyboardButton struct {
 661	Text            string `json:"text"`
 662	RequestContact  bool   `json:"request_contact"`
 663	RequestLocation bool   `json:"request_location"`
 664}
 665
 666// ReplyKeyboardHide allows the Bot to hide a custom keyboard.
 667type ReplyKeyboardHide struct {
 668	HideKeyboard bool `json:"hide_keyboard"`
 669	Selective    bool `json:"selective"` // optional
 670}
 671
 672// ReplyKeyboardRemove allows the Bot to hide a custom keyboard.
 673type ReplyKeyboardRemove struct {
 674	RemoveKeyboard bool `json:"remove_keyboard"`
 675	Selective      bool `json:"selective"`
 676}
 677
 678// InlineKeyboardMarkup is a custom keyboard presented for an inline bot.
 679type InlineKeyboardMarkup struct {
 680	InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"`
 681}
 682
 683// InlineKeyboardButton is a button within a custom keyboard for
 684// inline query responses.
 685//
 686// Note that some values are references as even an empty string
 687// will change behavior.
 688//
 689// CallbackGame, if set, MUST be first button in first row.
 690type InlineKeyboardButton struct {
 691	Text                         string        `json:"text"`
 692	URL                          *string       `json:"url,omitempty"`                              // optional
 693	CallbackData                 *string       `json:"callback_data,omitempty"`                    // optional
 694	SwitchInlineQuery            *string       `json:"switch_inline_query,omitempty"`              // optional
 695	SwitchInlineQueryCurrentChat *string       `json:"switch_inline_query_current_chat,omitempty"` // optional
 696	CallbackGame                 *CallbackGame `json:"callback_game,omitempty"`                    // optional
 697	Pay                          bool          `json:"pay,omitempty"`                              // optional
 698}
 699
 700// CallbackQuery is data sent when a keyboard button with callback data
 701// is clicked.
 702type CallbackQuery struct {
 703	ID              string   `json:"id"`
 704	From            *User    `json:"from"`
 705	Message         *Message `json:"message"`           // optional
 706	InlineMessageID string   `json:"inline_message_id"` // optional
 707	ChatInstance    string   `json:"chat_instance"`
 708	Data            string   `json:"data"`            // optional
 709	GameShortName   string   `json:"game_short_name"` // optional
 710}
 711
 712// ForceReply allows the Bot to have users directly reply to it without
 713// additional interaction.
 714type ForceReply struct {
 715	ForceReply bool `json:"force_reply"`
 716	Selective  bool `json:"selective"` // optional
 717}
 718
 719// ChatMember is information about a member in a chat.
 720type ChatMember struct {
 721	User                  *User  `json:"user"`
 722	Status                string `json:"status"`
 723	CustomTitle           string `json:"custom_title,omitempty"`              // optional
 724	UntilDate             int64  `json:"until_date,omitempty"`                // optional
 725	CanBeEdited           bool   `json:"can_be_edited,omitempty"`             // optional
 726	CanChangeInfo         bool   `json:"can_change_info,omitempty"`           // optional
 727	CanPostMessages       bool   `json:"can_post_messages,omitempty"`         // optional
 728	CanEditMessages       bool   `json:"can_edit_messages,omitempty"`         // optional
 729	CanDeleteMessages     bool   `json:"can_delete_messages,omitempty"`       // optional
 730	CanInviteUsers        bool   `json:"can_invite_users,omitempty"`          // optional
 731	CanRestrictMembers    bool   `json:"can_restrict_members,omitempty"`      // optional
 732	CanPinMessages        bool   `json:"can_pin_messages,omitempty"`          // optional
 733	CanPromoteMembers     bool   `json:"can_promote_members,omitempty"`       // optional
 734	CanSendMessages       bool   `json:"can_send_messages,omitempty"`         // optional
 735	CanSendMediaMessages  bool   `json:"can_send_media_messages,omitempty"`   // optional
 736	CanSendOtherMessages  bool   `json:"can_send_other_messages,omitempty"`   // optional
 737	CanAddWebPagePreviews bool   `json:"can_add_web_page_previews,omitempty"` // optional
 738}
 739
 740// IsCreator returns if the ChatMember was the creator of the chat.
 741func (chat ChatMember) IsCreator() bool { return chat.Status == "creator" }
 742
 743// IsAdministrator returns if the ChatMember is a chat administrator.
 744func (chat ChatMember) IsAdministrator() bool { return chat.Status == "administrator" }
 745
 746// IsMember returns if the ChatMember is a current member of the chat.
 747func (chat ChatMember) IsMember() bool { return chat.Status == "member" }
 748
 749// HasLeft returns if the ChatMember left the chat.
 750func (chat ChatMember) HasLeft() bool { return chat.Status == "left" }
 751
 752// WasKicked returns if the ChatMember was kicked from the chat.
 753func (chat ChatMember) WasKicked() bool { return chat.Status == "kicked" }
 754
 755// Game is a game within Telegram.
 756type Game struct {
 757	Title        string          `json:"title"`
 758	Description  string          `json:"description"`
 759	Photo        []PhotoSize     `json:"photo"`
 760	Text         string          `json:"text"`
 761	TextEntities []MessageEntity `json:"text_entities"`
 762	Animation    Animation       `json:"animation"`
 763}
 764
 765// Animation is a GIF animation demonstrating the game.
 766type Animation struct {
 767	FileID   string    `json:"file_id"`
 768	Thumb    PhotoSize `json:"thumb"`
 769	FileName string    `json:"file_name"`
 770	MimeType string    `json:"mime_type"`
 771	FileSize int       `json:"file_size"`
 772}
 773
 774// GameHighScore is a user's score and position on the leaderboard.
 775type GameHighScore struct {
 776	Position int  `json:"position"`
 777	User     User `json:"user"`
 778	Score    int  `json:"score"`
 779}
 780
 781// CallbackGame is for starting a game in an inline keyboard button.
 782type CallbackGame struct{}
 783
 784// WebhookInfo is information about a currently set webhook.
 785type WebhookInfo struct {
 786	URL                  string `json:"url"`
 787	HasCustomCertificate bool   `json:"has_custom_certificate"`
 788	PendingUpdateCount   int    `json:"pending_update_count"`
 789	LastErrorDate        int    `json:"last_error_date"`    // optional
 790	LastErrorMessage     string `json:"last_error_message"` // optional
 791	MaxConnections       int    `json:"max_connections"`    // optional
 792}
 793
 794// IsSet returns true if a webhook is currently set.
 795func (info WebhookInfo) IsSet() bool {
 796	return info.URL != ""
 797}
 798
 799// InputMediaPhoto contains a photo for displaying as part of a media group.
 800type InputMediaPhoto struct {
 801	Type      string `json:"type"`
 802	Media     string `json:"media"`
 803	Caption   string `json:"caption"`
 804	ParseMode string `json:"parse_mode"`
 805}
 806
 807// InputMediaVideo contains a video for displaying as part of a media group.
 808type InputMediaVideo struct {
 809	Type  string `json:"type"`
 810	Media string `json:"media"`
 811	// thumb intentionally missing as it is not currently compatible
 812	Caption           string `json:"caption"`
 813	ParseMode         string `json:"parse_mode"`
 814	Width             int    `json:"width"`
 815	Height            int    `json:"height"`
 816	Duration          int    `json:"duration"`
 817	SupportsStreaming bool   `json:"supports_streaming"`
 818}
 819
 820// InlineQuery is a Query from Telegram for an inline request.
 821type InlineQuery struct {
 822	ID       string    `json:"id"`
 823	From     *User     `json:"from"`
 824	Location *Location `json:"location"` // optional
 825	Query    string    `json:"query"`
 826	Offset   string    `json:"offset"`
 827}
 828
 829// InlineQueryResultArticle is an inline query response article.
 830type InlineQueryResultArticle struct {
 831	Type                string                `json:"type"`                            // required
 832	ID                  string                `json:"id"`                              // required
 833	Title               string                `json:"title"`                           // required
 834	InputMessageContent interface{}           `json:"input_message_content,omitempty"` // required
 835	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 836	URL                 string                `json:"url"`
 837	HideURL             bool                  `json:"hide_url"`
 838	Description         string                `json:"description"`
 839	ThumbURL            string                `json:"thumb_url"`
 840	ThumbWidth          int                   `json:"thumb_width"`
 841	ThumbHeight         int                   `json:"thumb_height"`
 842}
 843
 844// InlineQueryResultPhoto is an inline query response photo.
 845type InlineQueryResultPhoto struct {
 846	Type                string                `json:"type"`      // required
 847	ID                  string                `json:"id"`        // required
 848	URL                 string                `json:"photo_url"` // required
 849	MimeType            string                `json:"mime_type"`
 850	Width               int                   `json:"photo_width"`
 851	Height              int                   `json:"photo_height"`
 852	ThumbURL            string                `json:"thumb_url"`
 853	Title               string                `json:"title"`
 854	Description         string                `json:"description"`
 855	Caption             string                `json:"caption"`
 856	ParseMode           string                `json:"parse_mode"`
 857	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 858	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 859}
 860
 861// InlineQueryResultCachedPhoto is an inline query response with cached photo.
 862type InlineQueryResultCachedPhoto struct {
 863	Type                string                `json:"type"`          // required
 864	ID                  string                `json:"id"`            // required
 865	PhotoID             string                `json:"photo_file_id"` // required
 866	Title               string                `json:"title"`
 867	Description         string                `json:"description"`
 868	Caption             string                `json:"caption"`
 869	ParseMode           string                `json:"parse_mode"`
 870	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 871	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 872}
 873
 874// InlineQueryResultGIF is an inline query response GIF.
 875type InlineQueryResultGIF struct {
 876	Type                string                `json:"type"`      // required
 877	ID                  string                `json:"id"`        // required
 878	URL                 string                `json:"gif_url"`   // required
 879	ThumbURL            string                `json:"thumb_url"` // required
 880	Width               int                   `json:"gif_width,omitempty"`
 881	Height              int                   `json:"gif_height,omitempty"`
 882	Duration            int                   `json:"gif_duration,omitempty"`
 883	Title               string                `json:"title,omitempty"`
 884	Caption             string                `json:"caption,omitempty"`
 885	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 886	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 887}
 888
 889// InlineQueryResultCachedGIF is an inline query response with cached gif.
 890type InlineQueryResultCachedGIF struct {
 891	Type                string                `json:"type"`        // required
 892	ID                  string                `json:"id"`          // required
 893	GifID               string                `json:"gif_file_id"` // required
 894	Title               string                `json:"title"`
 895	Caption             string                `json:"caption"`
 896	ParseMode           string                `json:"parse_mode"`
 897	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 898	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 899}
 900
 901// InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF.
 902type InlineQueryResultMPEG4GIF struct {
 903	Type                string                `json:"type"`      // required
 904	ID                  string                `json:"id"`        // required
 905	URL                 string                `json:"mpeg4_url"` // required
 906	Width               int                   `json:"mpeg4_width"`
 907	Height              int                   `json:"mpeg4_height"`
 908	Duration            int                   `json:"mpeg4_duration"`
 909	ThumbURL            string                `json:"thumb_url"`
 910	Title               string                `json:"title"`
 911	Caption             string                `json:"caption"`
 912	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 913	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 914}
 915
 916// InlineQueryResultCachedMpeg4Gif is an inline query response with cached
 917// H.264/MPEG-4 AVC video without sound gif.
 918type InlineQueryResultCachedMpeg4Gif struct {
 919	Type                string                `json:"type"`          // required
 920	ID                  string                `json:"id"`            // required
 921	MGifID              string                `json:"mpeg4_file_id"` // required
 922	Title               string                `json:"title"`
 923	Caption             string                `json:"caption"`
 924	ParseMode           string                `json:"parse_mode"`
 925	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 926	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 927}
 928
 929// InlineQueryResultVideo is an inline query response video.
 930type InlineQueryResultVideo struct {
 931	Type                string                `json:"type"`      // required
 932	ID                  string                `json:"id"`        // required
 933	URL                 string                `json:"video_url"` // required
 934	MimeType            string                `json:"mime_type"` // required
 935	ThumbURL            string                `json:"thumb_url"`
 936	Title               string                `json:"title"`
 937	Caption             string                `json:"caption"`
 938	Width               int                   `json:"video_width"`
 939	Height              int                   `json:"video_height"`
 940	Duration            int                   `json:"video_duration"`
 941	Description         string                `json:"description"`
 942	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 943	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 944}
 945
 946// InlineQueryResultCachedVideo is an inline query response with cached video.
 947type InlineQueryResultCachedVideo struct {
 948	Type                string                `json:"type"`          // required
 949	ID                  string                `json:"id"`            // required
 950	VideoID             string                `json:"video_file_id"` // required
 951	Title               string                `json:"title"`         // required
 952	Description         string                `json:"description"`
 953	Caption             string                `json:"caption"`
 954	ParseMode           string                `json:"parse_mode"`
 955	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 956	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 957}
 958
 959// InlineQueryResultCachedSticker is an inline query response with cached sticker.
 960type InlineQueryResultCachedSticker struct {
 961	Type                string                `json:"type"`            // required
 962	ID                  string                `json:"id"`              // required
 963	StickerID           string                `json:"sticker_file_id"` // required
 964	Title               string                `json:"title"`           // required
 965	ParseMode           string                `json:"parse_mode"`
 966	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 967	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 968}
 969
 970// InlineQueryResultAudio is an inline query response audio.
 971type InlineQueryResultAudio struct {
 972	Type                string                `json:"type"`      // required
 973	ID                  string                `json:"id"`        // required
 974	URL                 string                `json:"audio_url"` // required
 975	Title               string                `json:"title"`     // required
 976	Caption             string                `json:"caption"`
 977	Performer           string                `json:"performer"`
 978	Duration            int                   `json:"audio_duration"`
 979	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 980	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 981}
 982
 983// InlineQueryResultCachedAudio is an inline query response with cached audio.
 984type InlineQueryResultCachedAudio struct {
 985	Type                string                `json:"type"`          // required
 986	ID                  string                `json:"id"`            // required
 987	AudioID             string                `json:"audio_file_id"` // required
 988	Caption             string                `json:"caption"`
 989	ParseMode           string                `json:"parse_mode"`
 990	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
 991	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
 992}
 993
 994// InlineQueryResultVoice is an inline query response voice.
 995type InlineQueryResultVoice struct {
 996	Type                string                `json:"type"`      // required
 997	ID                  string                `json:"id"`        // required
 998	URL                 string                `json:"voice_url"` // required
 999	Title               string                `json:"title"`     // required
1000	Caption             string                `json:"caption"`
1001	Duration            int                   `json:"voice_duration"`
1002	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
1003	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
1004}
1005
1006// InlineQueryResultCachedVoice is an inline query response with cached voice.
1007type InlineQueryResultCachedVoice struct {
1008	Type                string                `json:"type"`          // required
1009	ID                  string                `json:"id"`            // required
1010	VoiceID             string                `json:"voice_file_id"` // required
1011	Title               string                `json:"title"`         // required
1012	Caption             string                `json:"caption"`
1013	ParseMode           string                `json:"parse_mode"`
1014	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
1015	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
1016}
1017
1018// InlineQueryResultDocument is an inline query response document.
1019type InlineQueryResultDocument struct {
1020	Type                string                `json:"type"`  // required
1021	ID                  string                `json:"id"`    // required
1022	Title               string                `json:"title"` // required
1023	Caption             string                `json:"caption"`
1024	URL                 string                `json:"document_url"` // required
1025	MimeType            string                `json:"mime_type"`    // required
1026	Description         string                `json:"description"`
1027	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
1028	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
1029	ThumbURL            string                `json:"thumb_url"`
1030	ThumbWidth          int                   `json:"thumb_width"`
1031	ThumbHeight         int                   `json:"thumb_height"`
1032}
1033
1034// InlineQueryResultCachedDocument is an inline query response with cached document.
1035type InlineQueryResultCachedDocument struct {
1036	Type                string                `json:"type"`             // required
1037	ID                  string                `json:"id"`               // required
1038	DocumentID          string                `json:"document_file_id"` // required
1039	Title               string                `json:"title"`            // required
1040	Caption             string                `json:"caption"`
1041	Description         string                `json:"description"`
1042	ParseMode           string                `json:"parse_mode"`
1043	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
1044	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
1045}
1046
1047// InlineQueryResultLocation is an inline query response location.
1048type InlineQueryResultLocation struct {
1049	Type                string                `json:"type"`      // required
1050	ID                  string                `json:"id"`        // required
1051	Latitude            float64               `json:"latitude"`  // required
1052	Longitude           float64               `json:"longitude"` // required
1053	Title               string                `json:"title"`     // required
1054	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
1055	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
1056	ThumbURL            string                `json:"thumb_url"`
1057	ThumbWidth          int                   `json:"thumb_width"`
1058	ThumbHeight         int                   `json:"thumb_height"`
1059}
1060
1061// InlineQueryResultVenue is an inline query response venue.
1062type InlineQueryResultVenue struct {
1063	Type                string                `json:"type"`      // required
1064	ID                  string                `json:"id"`        // required
1065	Latitude            float64               `json:"latitude"`  // required
1066	Longitude           float64               `json:"longitude"` // required
1067	Title               string                `json:"title"`     // required
1068	Address             string                `json:"address"`   // required
1069	FoursquareID        string                `json:"foursquare_id"`
1070	FoursquareType      string                `json:"foursquare_type"`
1071	ReplyMarkup         *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
1072	InputMessageContent interface{}           `json:"input_message_content,omitempty"`
1073	ThumbURL            string                `json:"thumb_url"`
1074	ThumbWidth          int                   `json:"thumb_width"`
1075	ThumbHeight         int                   `json:"thumb_height"`
1076}
1077
1078// InlineQueryResultGame is an inline query response game.
1079type InlineQueryResultGame struct {
1080	Type          string                `json:"type"`
1081	ID            string                `json:"id"`
1082	GameShortName string                `json:"game_short_name"`
1083	ReplyMarkup   *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
1084}
1085
1086// ChosenInlineResult is an inline query result chosen by a User
1087type ChosenInlineResult struct {
1088	ResultID        string    `json:"result_id"`
1089	From            *User     `json:"from"`
1090	Location        *Location `json:"location"`
1091	InlineMessageID string    `json:"inline_message_id"`
1092	Query           string    `json:"query"`
1093}
1094
1095// InputTextMessageContent contains text for displaying
1096// as an inline query result.
1097type InputTextMessageContent struct {
1098	Text                  string `json:"message_text"`
1099	ParseMode             string `json:"parse_mode"`
1100	DisableWebPagePreview bool   `json:"disable_web_page_preview"`
1101}
1102
1103// InputLocationMessageContent contains a location for displaying
1104// as an inline query result.
1105type InputLocationMessageContent struct {
1106	Latitude  float64 `json:"latitude"`
1107	Longitude float64 `json:"longitude"`
1108}
1109
1110// InputVenueMessageContent contains a venue for displaying
1111// as an inline query result.
1112type InputVenueMessageContent struct {
1113	Latitude     float64 `json:"latitude"`
1114	Longitude    float64 `json:"longitude"`
1115	Title        string  `json:"title"`
1116	Address      string  `json:"address"`
1117	FoursquareID string  `json:"foursquare_id"`
1118}
1119
1120// InputContactMessageContent contains a contact for displaying
1121// as an inline query result.
1122type InputContactMessageContent struct {
1123	PhoneNumber string `json:"phone_number"`
1124	FirstName   string `json:"first_name"`
1125	LastName    string `json:"last_name"`
1126}
1127
1128// Invoice contains basic information about an invoice.
1129type Invoice struct {
1130	Title          string `json:"title"`
1131	Description    string `json:"description"`
1132	StartParameter string `json:"start_parameter"`
1133	Currency       string `json:"currency"`
1134	TotalAmount    int    `json:"total_amount"`
1135}
1136
1137// LabeledPrice represents a portion of the price for goods or services.
1138type LabeledPrice struct {
1139	Label  string `json:"label"`
1140	Amount int    `json:"amount"`
1141}
1142
1143// ShippingAddress represents a shipping address.
1144type ShippingAddress struct {
1145	CountryCode string `json:"country_code"`
1146	State       string `json:"state"`
1147	City        string `json:"city"`
1148	StreetLine1 string `json:"street_line1"`
1149	StreetLine2 string `json:"street_line2"`
1150	PostCode    string `json:"post_code"`
1151}
1152
1153// OrderInfo represents information about an order.
1154type OrderInfo struct {
1155	Name            string           `json:"name,omitempty"`
1156	PhoneNumber     string           `json:"phone_number,omitempty"`
1157	Email           string           `json:"email,omitempty"`
1158	ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"`
1159}
1160
1161// ShippingOption represents one shipping option.
1162type ShippingOption struct {
1163	ID     string          `json:"id"`
1164	Title  string          `json:"title"`
1165	Prices *[]LabeledPrice `json:"prices"`
1166}
1167
1168// SuccessfulPayment contains basic information about a successful payment.
1169type SuccessfulPayment struct {
1170	Currency                string     `json:"currency"`
1171	TotalAmount             int        `json:"total_amount"`
1172	InvoicePayload          string     `json:"invoice_payload"`
1173	ShippingOptionID        string     `json:"shipping_option_id,omitempty"`
1174	OrderInfo               *OrderInfo `json:"order_info,omitempty"`
1175	TelegramPaymentChargeID string     `json:"telegram_payment_charge_id"`
1176	ProviderPaymentChargeID string     `json:"provider_payment_charge_id"`
1177}
1178
1179// ShippingQuery contains information about an incoming shipping query.
1180type ShippingQuery struct {
1181	ID              string           `json:"id"`
1182	From            *User            `json:"from"`
1183	InvoicePayload  string           `json:"invoice_payload"`
1184	ShippingAddress *ShippingAddress `json:"shipping_address"`
1185}
1186
1187// PreCheckoutQuery contains information about an incoming pre-checkout query.
1188type PreCheckoutQuery struct {
1189	ID               string     `json:"id"`
1190	From             *User      `json:"from"`
1191	Currency         string     `json:"currency"`
1192	TotalAmount      int        `json:"total_amount"`
1193	InvoicePayload   string     `json:"invoice_payload"`
1194	ShippingOptionID string     `json:"shipping_option_id,omitempty"`
1195	OrderInfo        *OrderInfo `json:"order_info,omitempty"`
1196}
1197
1198// Error is an error containing extra information returned by the Telegram API.
1199type Error struct {
1200	Code    int
1201	Message string
1202	ResponseParameters
1203}
1204
1205func (e Error) Error() string {
1206	return e.Message
1207}
1208
1209// BotCommand represents a bot command.
1210type BotCommand struct {
1211	Command     string `json:"command"`
1212	Description string `json:"description"`
1213}