all repos — telegram-bot-api @ 67d51b9a52e70efad59e83db5682067754ca90c6

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