all repos — telegram-bot-api @ bot-api-6.1

Golang bindings for the Telegram Bot API

configs.go (view raw)

   1package tgbotapi
   2
   3import (
   4	"bytes"
   5	"fmt"
   6	"io"
   7	"net/url"
   8	"os"
   9	"strconv"
  10)
  11
  12// Telegram constants
  13const (
  14	// APIEndpoint is the endpoint for all API methods,
  15	// with formatting for Sprintf.
  16	APIEndpoint = "https://api.telegram.org/bot%s/%s"
  17	// FileEndpoint is the endpoint for downloading a file from Telegram.
  18	FileEndpoint = "https://api.telegram.org/file/bot%s/%s"
  19)
  20
  21// Constant values for ChatActions
  22const (
  23	ChatTyping          = "typing"
  24	ChatUploadPhoto     = "upload_photo"
  25	ChatRecordVideo     = "record_video"
  26	ChatUploadVideo     = "upload_video"
  27	ChatRecordVoice     = "record_voice"
  28	ChatUploadVoice     = "upload_voice"
  29	ChatUploadDocument  = "upload_document"
  30	ChatChooseSticker   = "choose_sticker"
  31	ChatFindLocation    = "find_location"
  32	ChatRecordVideoNote = "record_video_note"
  33	ChatUploadVideoNote = "upload_video_note"
  34)
  35
  36// API errors
  37const (
  38	// ErrAPIForbidden happens when a token is bad
  39	ErrAPIForbidden = "forbidden"
  40)
  41
  42// Constant values for ParseMode in MessageConfig
  43const (
  44	ModeMarkdown   = "Markdown"
  45	ModeMarkdownV2 = "MarkdownV2"
  46	ModeHTML       = "HTML"
  47)
  48
  49// Constant values for update types
  50const (
  51	// UpdateTypeMessage is new incoming message of any kind — text, photo, sticker, etc.
  52	UpdateTypeMessage = "message"
  53
  54	// UpdateTypeEditedMessage is new version of a message that is known to the bot and was edited
  55	UpdateTypeEditedMessage = "edited_message"
  56
  57	// UpdateTypeChannelPost is new incoming channel post of any kind — text, photo, sticker, etc.
  58	UpdateTypeChannelPost = "channel_post"
  59
  60	// UpdateTypeEditedChannelPost is new version of a channel post that is known to the bot and was edited
  61	UpdateTypeEditedChannelPost = "edited_channel_post"
  62
  63	// UpdateTypeInlineQuery is new incoming inline query
  64	UpdateTypeInlineQuery = "inline_query"
  65
  66	// UpdateTypeChosenInlineResult i the result of an inline query that was chosen by a user and sent to their
  67	// chat partner. Please see the documentation on the feedback collecting for
  68	// details on how to enable these updates for your bot.
  69	UpdateTypeChosenInlineResult = "chosen_inline_result"
  70
  71	// UpdateTypeCallbackQuery is new incoming callback query
  72	UpdateTypeCallbackQuery = "callback_query"
  73
  74	// UpdateTypeShippingQuery is new incoming shipping query. Only for invoices with flexible price
  75	UpdateTypeShippingQuery = "shipping_query"
  76
  77	// UpdateTypePreCheckoutQuery is new incoming pre-checkout query. Contains full information about checkout
  78	UpdateTypePreCheckoutQuery = "pre_checkout_query"
  79
  80	// UpdateTypePoll is new poll state. Bots receive only updates about stopped polls and polls
  81	// which are sent by the bot
  82	UpdateTypePoll = "poll"
  83
  84	// UpdateTypePollAnswer is when user changed their answer in a non-anonymous poll. Bots receive new votes
  85	// only in polls that were sent by the bot itself.
  86	UpdateTypePollAnswer = "poll_answer"
  87
  88	// UpdateTypeMyChatMember is when the bot's chat member status was updated in a chat. For private chats, this
  89	// update is received only when the bot is blocked or unblocked by the user.
  90	UpdateTypeMyChatMember = "my_chat_member"
  91
  92	// UpdateTypeChatMember is when the bot must be an administrator in the chat and must explicitly specify
  93	// this update in the list of allowed_updates to receive these updates.
  94	UpdateTypeChatMember = "chat_member"
  95)
  96
  97// Library errors
  98const (
  99	ErrBadURL = "bad or empty url"
 100)
 101
 102// Chattable is any config type that can be sent.
 103type Chattable interface {
 104	params() (Params, error)
 105	method() string
 106}
 107
 108// Fileable is any config type that can be sent that includes a file.
 109type Fileable interface {
 110	Chattable
 111	files() []RequestFile
 112}
 113
 114// RequestFile represents a file associated with a field name.
 115type RequestFile struct {
 116	// The file field name.
 117	Name string
 118	// The file data to include.
 119	Data RequestFileData
 120}
 121
 122// RequestFileData represents the data to be used for a file.
 123type RequestFileData interface {
 124	// NeedsUpload shows if the file needs to be uploaded.
 125	NeedsUpload() bool
 126
 127	// UploadData gets the file name and an `io.Reader` for the file to be uploaded. This
 128	// must only be called when the file needs to be uploaded.
 129	UploadData() (string, io.Reader, error)
 130	// SendData gets the file data to send when a file does not need to be uploaded. This
 131	// must only be called when the file does not need to be uploaded.
 132	SendData() string
 133}
 134
 135// FileBytes contains information about a set of bytes to upload
 136// as a File.
 137type FileBytes struct {
 138	Name  string
 139	Bytes []byte
 140}
 141
 142func (fb FileBytes) NeedsUpload() bool {
 143	return true
 144}
 145
 146func (fb FileBytes) UploadData() (string, io.Reader, error) {
 147	return fb.Name, bytes.NewReader(fb.Bytes), nil
 148}
 149
 150func (fb FileBytes) SendData() string {
 151	panic("FileBytes must be uploaded")
 152}
 153
 154// FileReader contains information about a reader to upload as a File.
 155type FileReader struct {
 156	Name   string
 157	Reader io.Reader
 158}
 159
 160func (fr FileReader) NeedsUpload() bool {
 161	return true
 162}
 163
 164func (fr FileReader) UploadData() (string, io.Reader, error) {
 165	return fr.Name, fr.Reader, nil
 166}
 167
 168func (fr FileReader) SendData() string {
 169	panic("FileReader must be uploaded")
 170}
 171
 172// FilePath is a path to a local file.
 173type FilePath string
 174
 175func (fp FilePath) NeedsUpload() bool {
 176	return true
 177}
 178
 179func (fp FilePath) UploadData() (string, io.Reader, error) {
 180	fileHandle, err := os.Open(string(fp))
 181	if err != nil {
 182		return "", nil, err
 183	}
 184
 185	name := fileHandle.Name()
 186	return name, fileHandle, err
 187}
 188
 189func (fp FilePath) SendData() string {
 190	panic("FilePath must be uploaded")
 191}
 192
 193// FileURL is a URL to use as a file for a request.
 194type FileURL string
 195
 196func (fu FileURL) NeedsUpload() bool {
 197	return false
 198}
 199
 200func (fu FileURL) UploadData() (string, io.Reader, error) {
 201	panic("FileURL cannot be uploaded")
 202}
 203
 204func (fu FileURL) SendData() string {
 205	return string(fu)
 206}
 207
 208// FileID is an ID of a file already uploaded to Telegram.
 209type FileID string
 210
 211func (fi FileID) NeedsUpload() bool {
 212	return false
 213}
 214
 215func (fi FileID) UploadData() (string, io.Reader, error) {
 216	panic("FileID cannot be uploaded")
 217}
 218
 219func (fi FileID) SendData() string {
 220	return string(fi)
 221}
 222
 223// fileAttach is an internal file type used for processed media groups.
 224type fileAttach string
 225
 226func (fa fileAttach) NeedsUpload() bool {
 227	return false
 228}
 229
 230func (fa fileAttach) UploadData() (string, io.Reader, error) {
 231	panic("fileAttach cannot be uploaded")
 232}
 233
 234func (fa fileAttach) SendData() string {
 235	return string(fa)
 236}
 237
 238// LogOutConfig is a request to log out of the cloud Bot API server.
 239//
 240// Note that you may not log back in for at least 10 minutes.
 241type LogOutConfig struct{}
 242
 243func (LogOutConfig) method() string {
 244	return "logOut"
 245}
 246
 247func (LogOutConfig) params() (Params, error) {
 248	return nil, nil
 249}
 250
 251// CloseConfig is a request to close the bot instance on a local server.
 252//
 253// Note that you may not close an instance for the first 10 minutes after the
 254// bot has started.
 255type CloseConfig struct{}
 256
 257func (CloseConfig) method() string {
 258	return "close"
 259}
 260
 261func (CloseConfig) params() (Params, error) {
 262	return nil, nil
 263}
 264
 265// BaseChat is base type for all chat config types.
 266type BaseChat struct {
 267	ChatID                   int64 // required
 268	ChannelUsername          string
 269	ProtectContent           bool
 270	ReplyToMessageID         int
 271	ReplyMarkup              interface{}
 272	DisableNotification      bool
 273	AllowSendingWithoutReply bool
 274}
 275
 276func (chat *BaseChat) params() (Params, error) {
 277	params := make(Params)
 278
 279	params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername)
 280	params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID)
 281	params.AddBool("disable_notification", chat.DisableNotification)
 282	params.AddBool("allow_sending_without_reply", chat.AllowSendingWithoutReply)
 283	params.AddBool("protect_content", chat.ProtectContent)
 284
 285	err := params.AddInterface("reply_markup", chat.ReplyMarkup)
 286
 287	return params, err
 288}
 289
 290// BaseFile is a base type for all file config types.
 291type BaseFile struct {
 292	BaseChat
 293	File RequestFileData
 294}
 295
 296func (file BaseFile) params() (Params, error) {
 297	return file.BaseChat.params()
 298}
 299
 300// BaseEdit is base type of all chat edits.
 301type BaseEdit struct {
 302	ChatID          int64
 303	ChannelUsername string
 304	MessageID       int
 305	InlineMessageID string
 306	ReplyMarkup     *InlineKeyboardMarkup
 307}
 308
 309func (edit BaseEdit) params() (Params, error) {
 310	params := make(Params)
 311
 312	if edit.InlineMessageID != "" {
 313		params["inline_message_id"] = edit.InlineMessageID
 314	} else {
 315		params.AddFirstValid("chat_id", edit.ChatID, edit.ChannelUsername)
 316		params.AddNonZero("message_id", edit.MessageID)
 317	}
 318
 319	err := params.AddInterface("reply_markup", edit.ReplyMarkup)
 320
 321	return params, err
 322}
 323
 324// MessageConfig contains information about a SendMessage request.
 325type MessageConfig struct {
 326	BaseChat
 327	Text                  string
 328	ParseMode             string
 329	Entities              []MessageEntity
 330	DisableWebPagePreview bool
 331}
 332
 333func (config MessageConfig) params() (Params, error) {
 334	params, err := config.BaseChat.params()
 335	if err != nil {
 336		return params, err
 337	}
 338
 339	params.AddNonEmpty("text", config.Text)
 340	params.AddBool("disable_web_page_preview", config.DisableWebPagePreview)
 341	params.AddNonEmpty("parse_mode", config.ParseMode)
 342	err = params.AddInterface("entities", config.Entities)
 343
 344	return params, err
 345}
 346
 347func (config MessageConfig) method() string {
 348	return "sendMessage"
 349}
 350
 351// ForwardConfig contains information about a ForwardMessage request.
 352type ForwardConfig struct {
 353	BaseChat
 354	FromChatID          int64 // required
 355	FromChannelUsername string
 356	MessageID           int // required
 357}
 358
 359func (config ForwardConfig) params() (Params, error) {
 360	params, err := config.BaseChat.params()
 361	if err != nil {
 362		return params, err
 363	}
 364
 365	params.AddNonZero64("from_chat_id", config.FromChatID)
 366	params.AddNonZero("message_id", config.MessageID)
 367
 368	return params, nil
 369}
 370
 371func (config ForwardConfig) method() string {
 372	return "forwardMessage"
 373}
 374
 375// CopyMessageConfig contains information about a copyMessage request.
 376type CopyMessageConfig struct {
 377	BaseChat
 378	FromChatID          int64
 379	FromChannelUsername string
 380	MessageID           int
 381	Caption             string
 382	ParseMode           string
 383	CaptionEntities     []MessageEntity
 384}
 385
 386func (config CopyMessageConfig) params() (Params, error) {
 387	params, err := config.BaseChat.params()
 388	if err != nil {
 389		return params, err
 390	}
 391
 392	params.AddFirstValid("from_chat_id", config.FromChatID, config.FromChannelUsername)
 393	params.AddNonZero("message_id", config.MessageID)
 394	params.AddNonEmpty("caption", config.Caption)
 395	params.AddNonEmpty("parse_mode", config.ParseMode)
 396	err = params.AddInterface("caption_entities", config.CaptionEntities)
 397
 398	return params, err
 399}
 400
 401func (config CopyMessageConfig) method() string {
 402	return "copyMessage"
 403}
 404
 405// PhotoConfig contains information about a SendPhoto request.
 406type PhotoConfig struct {
 407	BaseFile
 408	Thumb           RequestFileData
 409	Caption         string
 410	ParseMode       string
 411	CaptionEntities []MessageEntity
 412}
 413
 414func (config PhotoConfig) params() (Params, error) {
 415	params, err := config.BaseFile.params()
 416	if err != nil {
 417		return params, err
 418	}
 419
 420	params.AddNonEmpty("caption", config.Caption)
 421	params.AddNonEmpty("parse_mode", config.ParseMode)
 422	err = params.AddInterface("caption_entities", config.CaptionEntities)
 423
 424	return params, err
 425}
 426
 427func (config PhotoConfig) method() string {
 428	return "sendPhoto"
 429}
 430
 431func (config PhotoConfig) files() []RequestFile {
 432	files := []RequestFile{{
 433		Name: "photo",
 434		Data: config.File,
 435	}}
 436
 437	if config.Thumb != nil {
 438		files = append(files, RequestFile{
 439			Name: "thumb",
 440			Data: config.Thumb,
 441		})
 442	}
 443
 444	return files
 445}
 446
 447// AudioConfig contains information about a SendAudio request.
 448type AudioConfig struct {
 449	BaseFile
 450	Thumb           RequestFileData
 451	Caption         string
 452	ParseMode       string
 453	CaptionEntities []MessageEntity
 454	Duration        int
 455	Performer       string
 456	Title           string
 457}
 458
 459func (config AudioConfig) params() (Params, error) {
 460	params, err := config.BaseChat.params()
 461	if err != nil {
 462		return params, err
 463	}
 464
 465	params.AddNonZero("duration", config.Duration)
 466	params.AddNonEmpty("performer", config.Performer)
 467	params.AddNonEmpty("title", config.Title)
 468	params.AddNonEmpty("caption", config.Caption)
 469	params.AddNonEmpty("parse_mode", config.ParseMode)
 470	err = params.AddInterface("caption_entities", config.CaptionEntities)
 471
 472	return params, err
 473}
 474
 475func (config AudioConfig) method() string {
 476	return "sendAudio"
 477}
 478
 479func (config AudioConfig) files() []RequestFile {
 480	files := []RequestFile{{
 481		Name: "audio",
 482		Data: config.File,
 483	}}
 484
 485	if config.Thumb != nil {
 486		files = append(files, RequestFile{
 487			Name: "thumb",
 488			Data: config.Thumb,
 489		})
 490	}
 491
 492	return files
 493}
 494
 495// DocumentConfig contains information about a SendDocument request.
 496type DocumentConfig struct {
 497	BaseFile
 498	Thumb                       RequestFileData
 499	Caption                     string
 500	ParseMode                   string
 501	CaptionEntities             []MessageEntity
 502	DisableContentTypeDetection bool
 503}
 504
 505func (config DocumentConfig) params() (Params, error) {
 506	params, err := config.BaseFile.params()
 507
 508	params.AddNonEmpty("caption", config.Caption)
 509	params.AddNonEmpty("parse_mode", config.ParseMode)
 510	params.AddBool("disable_content_type_detection", config.DisableContentTypeDetection)
 511
 512	return params, err
 513}
 514
 515func (config DocumentConfig) method() string {
 516	return "sendDocument"
 517}
 518
 519func (config DocumentConfig) files() []RequestFile {
 520	files := []RequestFile{{
 521		Name: "document",
 522		Data: config.File,
 523	}}
 524
 525	if config.Thumb != nil {
 526		files = append(files, RequestFile{
 527			Name: "thumb",
 528			Data: config.Thumb,
 529		})
 530	}
 531
 532	return files
 533}
 534
 535// StickerConfig contains information about a SendSticker request.
 536type StickerConfig struct {
 537	BaseFile
 538}
 539
 540func (config StickerConfig) params() (Params, error) {
 541	return config.BaseChat.params()
 542}
 543
 544func (config StickerConfig) method() string {
 545	return "sendSticker"
 546}
 547
 548func (config StickerConfig) files() []RequestFile {
 549	return []RequestFile{{
 550		Name: "sticker",
 551		Data: config.File,
 552	}}
 553}
 554
 555// VideoConfig contains information about a SendVideo request.
 556type VideoConfig struct {
 557	BaseFile
 558	Thumb             RequestFileData
 559	Duration          int
 560	Caption           string
 561	ParseMode         string
 562	CaptionEntities   []MessageEntity
 563	SupportsStreaming bool
 564}
 565
 566func (config VideoConfig) params() (Params, error) {
 567	params, err := config.BaseChat.params()
 568	if err != nil {
 569		return params, err
 570	}
 571
 572	params.AddNonZero("duration", config.Duration)
 573	params.AddNonEmpty("caption", config.Caption)
 574	params.AddNonEmpty("parse_mode", config.ParseMode)
 575	params.AddBool("supports_streaming", config.SupportsStreaming)
 576	err = params.AddInterface("caption_entities", config.CaptionEntities)
 577
 578	return params, err
 579}
 580
 581func (config VideoConfig) method() string {
 582	return "sendVideo"
 583}
 584
 585func (config VideoConfig) files() []RequestFile {
 586	files := []RequestFile{{
 587		Name: "video",
 588		Data: config.File,
 589	}}
 590
 591	if config.Thumb != nil {
 592		files = append(files, RequestFile{
 593			Name: "thumb",
 594			Data: config.Thumb,
 595		})
 596	}
 597
 598	return files
 599}
 600
 601// AnimationConfig contains information about a SendAnimation request.
 602type AnimationConfig struct {
 603	BaseFile
 604	Duration        int
 605	Thumb           RequestFileData
 606	Caption         string
 607	ParseMode       string
 608	CaptionEntities []MessageEntity
 609}
 610
 611func (config AnimationConfig) params() (Params, error) {
 612	params, err := config.BaseChat.params()
 613	if err != nil {
 614		return params, err
 615	}
 616
 617	params.AddNonZero("duration", config.Duration)
 618	params.AddNonEmpty("caption", config.Caption)
 619	params.AddNonEmpty("parse_mode", config.ParseMode)
 620	err = params.AddInterface("caption_entities", config.CaptionEntities)
 621
 622	return params, err
 623}
 624
 625func (config AnimationConfig) method() string {
 626	return "sendAnimation"
 627}
 628
 629func (config AnimationConfig) files() []RequestFile {
 630	files := []RequestFile{{
 631		Name: "animation",
 632		Data: config.File,
 633	}}
 634
 635	if config.Thumb != nil {
 636		files = append(files, RequestFile{
 637			Name: "thumb",
 638			Data: config.Thumb,
 639		})
 640	}
 641
 642	return files
 643}
 644
 645// VideoNoteConfig contains information about a SendVideoNote request.
 646type VideoNoteConfig struct {
 647	BaseFile
 648	Thumb    RequestFileData
 649	Duration int
 650	Length   int
 651}
 652
 653func (config VideoNoteConfig) params() (Params, error) {
 654	params, err := config.BaseChat.params()
 655
 656	params.AddNonZero("duration", config.Duration)
 657	params.AddNonZero("length", config.Length)
 658
 659	return params, err
 660}
 661
 662func (config VideoNoteConfig) method() string {
 663	return "sendVideoNote"
 664}
 665
 666func (config VideoNoteConfig) files() []RequestFile {
 667	files := []RequestFile{{
 668		Name: "video_note",
 669		Data: config.File,
 670	}}
 671
 672	if config.Thumb != nil {
 673		files = append(files, RequestFile{
 674			Name: "thumb",
 675			Data: config.Thumb,
 676		})
 677	}
 678
 679	return files
 680}
 681
 682// VoiceConfig contains information about a SendVoice request.
 683type VoiceConfig struct {
 684	BaseFile
 685	Thumb           RequestFileData
 686	Caption         string
 687	ParseMode       string
 688	CaptionEntities []MessageEntity
 689	Duration        int
 690}
 691
 692func (config VoiceConfig) params() (Params, error) {
 693	params, err := config.BaseChat.params()
 694	if err != nil {
 695		return params, err
 696	}
 697
 698	params.AddNonZero("duration", config.Duration)
 699	params.AddNonEmpty("caption", config.Caption)
 700	params.AddNonEmpty("parse_mode", config.ParseMode)
 701	err = params.AddInterface("caption_entities", config.CaptionEntities)
 702
 703	return params, err
 704}
 705
 706func (config VoiceConfig) method() string {
 707	return "sendVoice"
 708}
 709
 710func (config VoiceConfig) files() []RequestFile {
 711	files := []RequestFile{{
 712		Name: "voice",
 713		Data: config.File,
 714	}}
 715
 716	if config.Thumb != nil {
 717		files = append(files, RequestFile{
 718			Name: "thumb",
 719			Data: config.Thumb,
 720		})
 721	}
 722
 723	return files
 724}
 725
 726// LocationConfig contains information about a SendLocation request.
 727type LocationConfig struct {
 728	BaseChat
 729	Latitude             float64 // required
 730	Longitude            float64 // required
 731	HorizontalAccuracy   float64 // optional
 732	LivePeriod           int     // optional
 733	Heading              int     // optional
 734	ProximityAlertRadius int     // optional
 735}
 736
 737func (config LocationConfig) params() (Params, error) {
 738	params, err := config.BaseChat.params()
 739
 740	params.AddNonZeroFloat("latitude", config.Latitude)
 741	params.AddNonZeroFloat("longitude", config.Longitude)
 742	params.AddNonZeroFloat("horizontal_accuracy", config.HorizontalAccuracy)
 743	params.AddNonZero("live_period", config.LivePeriod)
 744	params.AddNonZero("heading", config.Heading)
 745	params.AddNonZero("proximity_alert_radius", config.ProximityAlertRadius)
 746
 747	return params, err
 748}
 749
 750func (config LocationConfig) method() string {
 751	return "sendLocation"
 752}
 753
 754// EditMessageLiveLocationConfig allows you to update a live location.
 755type EditMessageLiveLocationConfig struct {
 756	BaseEdit
 757	Latitude             float64 // required
 758	Longitude            float64 // required
 759	HorizontalAccuracy   float64 // optional
 760	Heading              int     // optional
 761	ProximityAlertRadius int     // optional
 762}
 763
 764func (config EditMessageLiveLocationConfig) params() (Params, error) {
 765	params, err := config.BaseEdit.params()
 766
 767	params.AddNonZeroFloat("latitude", config.Latitude)
 768	params.AddNonZeroFloat("longitude", config.Longitude)
 769	params.AddNonZeroFloat("horizontal_accuracy", config.HorizontalAccuracy)
 770	params.AddNonZero("heading", config.Heading)
 771	params.AddNonZero("proximity_alert_radius", config.ProximityAlertRadius)
 772
 773	return params, err
 774}
 775
 776func (config EditMessageLiveLocationConfig) method() string {
 777	return "editMessageLiveLocation"
 778}
 779
 780// StopMessageLiveLocationConfig stops updating a live location.
 781type StopMessageLiveLocationConfig struct {
 782	BaseEdit
 783}
 784
 785func (config StopMessageLiveLocationConfig) params() (Params, error) {
 786	return config.BaseEdit.params()
 787}
 788
 789func (config StopMessageLiveLocationConfig) method() string {
 790	return "stopMessageLiveLocation"
 791}
 792
 793// VenueConfig contains information about a SendVenue request.
 794type VenueConfig struct {
 795	BaseChat
 796	Latitude        float64 // required
 797	Longitude       float64 // required
 798	Title           string  // required
 799	Address         string  // required
 800	FoursquareID    string
 801	FoursquareType  string
 802	GooglePlaceID   string
 803	GooglePlaceType string
 804}
 805
 806func (config VenueConfig) params() (Params, error) {
 807	params, err := config.BaseChat.params()
 808
 809	params.AddNonZeroFloat("latitude", config.Latitude)
 810	params.AddNonZeroFloat("longitude", config.Longitude)
 811	params["title"] = config.Title
 812	params["address"] = config.Address
 813	params.AddNonEmpty("foursquare_id", config.FoursquareID)
 814	params.AddNonEmpty("foursquare_type", config.FoursquareType)
 815	params.AddNonEmpty("google_place_id", config.GooglePlaceID)
 816	params.AddNonEmpty("google_place_type", config.GooglePlaceType)
 817
 818	return params, err
 819}
 820
 821func (config VenueConfig) method() string {
 822	return "sendVenue"
 823}
 824
 825// ContactConfig allows you to send a contact.
 826type ContactConfig struct {
 827	BaseChat
 828	PhoneNumber string
 829	FirstName   string
 830	LastName    string
 831	VCard       string
 832}
 833
 834func (config ContactConfig) params() (Params, error) {
 835	params, err := config.BaseChat.params()
 836
 837	params["phone_number"] = config.PhoneNumber
 838	params["first_name"] = config.FirstName
 839
 840	params.AddNonEmpty("last_name", config.LastName)
 841	params.AddNonEmpty("vcard", config.VCard)
 842
 843	return params, err
 844}
 845
 846func (config ContactConfig) method() string {
 847	return "sendContact"
 848}
 849
 850// SendPollConfig allows you to send a poll.
 851type SendPollConfig struct {
 852	BaseChat
 853	Question              string
 854	Options               []string
 855	IsAnonymous           bool
 856	Type                  string
 857	AllowsMultipleAnswers bool
 858	CorrectOptionID       int64
 859	Explanation           string
 860	ExplanationParseMode  string
 861	ExplanationEntities   []MessageEntity
 862	OpenPeriod            int
 863	CloseDate             int
 864	IsClosed              bool
 865}
 866
 867func (config SendPollConfig) params() (Params, error) {
 868	params, err := config.BaseChat.params()
 869	if err != nil {
 870		return params, err
 871	}
 872
 873	params["question"] = config.Question
 874	if err = params.AddInterface("options", config.Options); err != nil {
 875		return params, err
 876	}
 877	params["is_anonymous"] = strconv.FormatBool(config.IsAnonymous)
 878	params.AddNonEmpty("type", config.Type)
 879	params["allows_multiple_answers"] = strconv.FormatBool(config.AllowsMultipleAnswers)
 880	params["correct_option_id"] = strconv.FormatInt(config.CorrectOptionID, 10)
 881	params.AddBool("is_closed", config.IsClosed)
 882	params.AddNonEmpty("explanation", config.Explanation)
 883	params.AddNonEmpty("explanation_parse_mode", config.ExplanationParseMode)
 884	params.AddNonZero("open_period", config.OpenPeriod)
 885	params.AddNonZero("close_date", config.CloseDate)
 886	err = params.AddInterface("explanation_entities", config.ExplanationEntities)
 887
 888	return params, err
 889}
 890
 891func (SendPollConfig) method() string {
 892	return "sendPoll"
 893}
 894
 895// GameConfig allows you to send a game.
 896type GameConfig struct {
 897	BaseChat
 898	GameShortName string
 899}
 900
 901func (config GameConfig) params() (Params, error) {
 902	params, err := config.BaseChat.params()
 903
 904	params["game_short_name"] = config.GameShortName
 905
 906	return params, err
 907}
 908
 909func (config GameConfig) method() string {
 910	return "sendGame"
 911}
 912
 913// SetGameScoreConfig allows you to update the game score in a chat.
 914type SetGameScoreConfig struct {
 915	UserID             int64
 916	Score              int
 917	Force              bool
 918	DisableEditMessage bool
 919	ChatID             int64
 920	ChannelUsername    string
 921	MessageID          int
 922	InlineMessageID    string
 923}
 924
 925func (config SetGameScoreConfig) params() (Params, error) {
 926	params := make(Params)
 927
 928	params.AddNonZero64("user_id", config.UserID)
 929	params.AddNonZero("scrore", config.Score)
 930	params.AddBool("disable_edit_message", config.DisableEditMessage)
 931
 932	if config.InlineMessageID != "" {
 933		params["inline_message_id"] = config.InlineMessageID
 934	} else {
 935		params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
 936		params.AddNonZero("message_id", config.MessageID)
 937	}
 938
 939	return params, nil
 940}
 941
 942func (config SetGameScoreConfig) method() string {
 943	return "setGameScore"
 944}
 945
 946// GetGameHighScoresConfig allows you to fetch the high scores for a game.
 947type GetGameHighScoresConfig struct {
 948	UserID          int64
 949	ChatID          int64
 950	ChannelUsername string
 951	MessageID       int
 952	InlineMessageID string
 953}
 954
 955func (config GetGameHighScoresConfig) params() (Params, error) {
 956	params := make(Params)
 957
 958	params.AddNonZero64("user_id", config.UserID)
 959
 960	if config.InlineMessageID != "" {
 961		params["inline_message_id"] = config.InlineMessageID
 962	} else {
 963		params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
 964		params.AddNonZero("message_id", config.MessageID)
 965	}
 966
 967	return params, nil
 968}
 969
 970func (config GetGameHighScoresConfig) method() string {
 971	return "getGameHighScores"
 972}
 973
 974// ChatActionConfig contains information about a SendChatAction request.
 975type ChatActionConfig struct {
 976	BaseChat
 977	Action string // required
 978}
 979
 980func (config ChatActionConfig) params() (Params, error) {
 981	params, err := config.BaseChat.params()
 982
 983	params["action"] = config.Action
 984
 985	return params, err
 986}
 987
 988func (config ChatActionConfig) method() string {
 989	return "sendChatAction"
 990}
 991
 992// EditMessageTextConfig allows you to modify the text in a message.
 993type EditMessageTextConfig struct {
 994	BaseEdit
 995	Text                  string
 996	ParseMode             string
 997	Entities              []MessageEntity
 998	DisableWebPagePreview bool
 999}
1000
1001func (config EditMessageTextConfig) params() (Params, error) {
1002	params, err := config.BaseEdit.params()
1003	if err != nil {
1004		return params, err
1005	}
1006
1007	params["text"] = config.Text
1008	params.AddNonEmpty("parse_mode", config.ParseMode)
1009	params.AddBool("disable_web_page_preview", config.DisableWebPagePreview)
1010	err = params.AddInterface("entities", config.Entities)
1011
1012	return params, err
1013}
1014
1015func (config EditMessageTextConfig) method() string {
1016	return "editMessageText"
1017}
1018
1019// EditMessageCaptionConfig allows you to modify the caption of a message.
1020type EditMessageCaptionConfig struct {
1021	BaseEdit
1022	Caption         string
1023	ParseMode       string
1024	CaptionEntities []MessageEntity
1025}
1026
1027func (config EditMessageCaptionConfig) params() (Params, error) {
1028	params, err := config.BaseEdit.params()
1029	if err != nil {
1030		return params, err
1031	}
1032
1033	params["caption"] = config.Caption
1034	params.AddNonEmpty("parse_mode", config.ParseMode)
1035	err = params.AddInterface("caption_entities", config.CaptionEntities)
1036
1037	return params, err
1038}
1039
1040func (config EditMessageCaptionConfig) method() string {
1041	return "editMessageCaption"
1042}
1043
1044// EditMessageMediaConfig allows you to make an editMessageMedia request.
1045type EditMessageMediaConfig struct {
1046	BaseEdit
1047
1048	Media interface{}
1049}
1050
1051func (EditMessageMediaConfig) method() string {
1052	return "editMessageMedia"
1053}
1054
1055func (config EditMessageMediaConfig) params() (Params, error) {
1056	params, err := config.BaseEdit.params()
1057	if err != nil {
1058		return params, err
1059	}
1060
1061	err = params.AddInterface("media", prepareInputMediaParam(config.Media, 0))
1062
1063	return params, err
1064}
1065
1066func (config EditMessageMediaConfig) files() []RequestFile {
1067	return prepareInputMediaFile(config.Media, 0)
1068}
1069
1070// EditMessageReplyMarkupConfig allows you to modify the reply markup
1071// of a message.
1072type EditMessageReplyMarkupConfig struct {
1073	BaseEdit
1074}
1075
1076func (config EditMessageReplyMarkupConfig) params() (Params, error) {
1077	return config.BaseEdit.params()
1078}
1079
1080func (config EditMessageReplyMarkupConfig) method() string {
1081	return "editMessageReplyMarkup"
1082}
1083
1084// StopPollConfig allows you to stop a poll sent by the bot.
1085type StopPollConfig struct {
1086	BaseEdit
1087}
1088
1089func (config StopPollConfig) params() (Params, error) {
1090	return config.BaseEdit.params()
1091}
1092
1093func (StopPollConfig) method() string {
1094	return "stopPoll"
1095}
1096
1097// UserProfilePhotosConfig contains information about a
1098// GetUserProfilePhotos request.
1099type UserProfilePhotosConfig struct {
1100	UserID int64
1101	Offset int
1102	Limit  int
1103}
1104
1105func (UserProfilePhotosConfig) method() string {
1106	return "getUserProfilePhotos"
1107}
1108
1109func (config UserProfilePhotosConfig) params() (Params, error) {
1110	params := make(Params)
1111
1112	params.AddNonZero64("user_id", config.UserID)
1113	params.AddNonZero("offset", config.Offset)
1114	params.AddNonZero("limit", config.Limit)
1115
1116	return params, nil
1117}
1118
1119// FileConfig has information about a file hosted on Telegram.
1120type FileConfig struct {
1121	FileID string
1122}
1123
1124func (FileConfig) method() string {
1125	return "getFile"
1126}
1127
1128func (config FileConfig) params() (Params, error) {
1129	params := make(Params)
1130
1131	params["file_id"] = config.FileID
1132
1133	return params, nil
1134}
1135
1136// UpdateConfig contains information about a GetUpdates request.
1137type UpdateConfig struct {
1138	Offset         int
1139	Limit          int
1140	Timeout        int
1141	AllowedUpdates []string
1142}
1143
1144func (UpdateConfig) method() string {
1145	return "getUpdates"
1146}
1147
1148func (config UpdateConfig) params() (Params, error) {
1149	params := make(Params)
1150
1151	params.AddNonZero("offset", config.Offset)
1152	params.AddNonZero("limit", config.Limit)
1153	params.AddNonZero("timeout", config.Timeout)
1154	params.AddInterface("allowed_updates", config.AllowedUpdates)
1155
1156	return params, nil
1157}
1158
1159// WebhookConfig contains information about a SetWebhook request.
1160type WebhookConfig struct {
1161	URL                *url.URL
1162	Certificate        RequestFileData
1163	IPAddress          string
1164	MaxConnections     int
1165	AllowedUpdates     []string
1166	DropPendingUpdates bool
1167	SecretToken        string
1168}
1169
1170func (config WebhookConfig) method() string {
1171	return "setWebhook"
1172}
1173
1174func (config WebhookConfig) params() (Params, error) {
1175	params := make(Params)
1176
1177	if config.URL != nil {
1178		params["url"] = config.URL.String()
1179	}
1180
1181	params.AddNonEmpty("ip_address", config.IPAddress)
1182	params.AddNonZero("max_connections", config.MaxConnections)
1183	err := params.AddInterface("allowed_updates", config.AllowedUpdates)
1184	params.AddBool("drop_pending_updates", config.DropPendingUpdates)
1185	params.AddNonEmpty("secret_token", config.SecretToken)
1186
1187	return params, err
1188}
1189
1190func (config WebhookConfig) files() []RequestFile {
1191	if config.Certificate != nil {
1192		return []RequestFile{{
1193			Name: "certificate",
1194			Data: config.Certificate,
1195		}}
1196	}
1197
1198	return nil
1199}
1200
1201// DeleteWebhookConfig is a helper to delete a webhook.
1202type DeleteWebhookConfig struct {
1203	DropPendingUpdates bool
1204}
1205
1206func (config DeleteWebhookConfig) method() string {
1207	return "deleteWebhook"
1208}
1209
1210func (config DeleteWebhookConfig) params() (Params, error) {
1211	params := make(Params)
1212
1213	params.AddBool("drop_pending_updates", config.DropPendingUpdates)
1214
1215	return params, nil
1216}
1217
1218// InlineConfig contains information on making an InlineQuery response.
1219type InlineConfig struct {
1220	InlineQueryID     string        `json:"inline_query_id"`
1221	Results           []interface{} `json:"results"`
1222	CacheTime         int           `json:"cache_time"`
1223	IsPersonal        bool          `json:"is_personal"`
1224	NextOffset        string        `json:"next_offset"`
1225	SwitchPMText      string        `json:"switch_pm_text"`
1226	SwitchPMParameter string        `json:"switch_pm_parameter"`
1227}
1228
1229func (config InlineConfig) method() string {
1230	return "answerInlineQuery"
1231}
1232
1233func (config InlineConfig) params() (Params, error) {
1234	params := make(Params)
1235
1236	params["inline_query_id"] = config.InlineQueryID
1237	params.AddNonZero("cache_time", config.CacheTime)
1238	params.AddBool("is_personal", config.IsPersonal)
1239	params.AddNonEmpty("next_offset", config.NextOffset)
1240	params.AddNonEmpty("switch_pm_text", config.SwitchPMText)
1241	params.AddNonEmpty("switch_pm_parameter", config.SwitchPMParameter)
1242	err := params.AddInterface("results", config.Results)
1243
1244	return params, err
1245}
1246
1247// AnswerWebAppQueryConfig is used to set the result of an interaction with a
1248// Web App and send a corresponding message on behalf of the user to the chat
1249// from which the query originated.
1250type AnswerWebAppQueryConfig struct {
1251	// WebAppQueryID is the unique identifier for the query to be answered.
1252	WebAppQueryID string `json:"web_app_query_id"`
1253	// Result is an InlineQueryResult object describing the message to be sent.
1254	Result interface{} `json:"result"`
1255}
1256
1257func (config AnswerWebAppQueryConfig) method() string {
1258	return "answerWebAppQuery"
1259}
1260
1261func (config AnswerWebAppQueryConfig) params() (Params, error) {
1262	params := make(Params)
1263
1264	params["web_app_query_id"] = config.WebAppQueryID
1265	err := params.AddInterface("result", config.Result)
1266
1267	return params, err
1268}
1269
1270// CallbackConfig contains information on making a CallbackQuery response.
1271type CallbackConfig struct {
1272	CallbackQueryID string `json:"callback_query_id"`
1273	Text            string `json:"text"`
1274	ShowAlert       bool   `json:"show_alert"`
1275	URL             string `json:"url"`
1276	CacheTime       int    `json:"cache_time"`
1277}
1278
1279func (config CallbackConfig) method() string {
1280	return "answerCallbackQuery"
1281}
1282
1283func (config CallbackConfig) params() (Params, error) {
1284	params := make(Params)
1285
1286	params["callback_query_id"] = config.CallbackQueryID
1287	params.AddNonEmpty("text", config.Text)
1288	params.AddBool("show_alert", config.ShowAlert)
1289	params.AddNonEmpty("url", config.URL)
1290	params.AddNonZero("cache_time", config.CacheTime)
1291
1292	return params, nil
1293}
1294
1295// ChatMemberConfig contains information about a user in a chat for use
1296// with administrative functions such as kicking or unbanning a user.
1297type ChatMemberConfig struct {
1298	ChatID             int64
1299	SuperGroupUsername string
1300	ChannelUsername    string
1301	UserID             int64
1302}
1303
1304// UnbanChatMemberConfig allows you to unban a user.
1305type UnbanChatMemberConfig struct {
1306	ChatMemberConfig
1307	OnlyIfBanned bool
1308}
1309
1310func (config UnbanChatMemberConfig) method() string {
1311	return "unbanChatMember"
1312}
1313
1314func (config UnbanChatMemberConfig) params() (Params, error) {
1315	params := make(Params)
1316
1317	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1318	params.AddNonZero64("user_id", config.UserID)
1319	params.AddBool("only_if_banned", config.OnlyIfBanned)
1320
1321	return params, nil
1322}
1323
1324// BanChatMemberConfig contains extra fields to kick user.
1325type BanChatMemberConfig struct {
1326	ChatMemberConfig
1327	UntilDate      int64
1328	RevokeMessages bool
1329}
1330
1331func (config BanChatMemberConfig) method() string {
1332	return "banChatMember"
1333}
1334
1335func (config BanChatMemberConfig) params() (Params, error) {
1336	params := make(Params)
1337
1338	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1339	params.AddNonZero64("user_id", config.UserID)
1340	params.AddNonZero64("until_date", config.UntilDate)
1341	params.AddBool("revoke_messages", config.RevokeMessages)
1342
1343	return params, nil
1344}
1345
1346// KickChatMemberConfig contains extra fields to ban user.
1347//
1348// This was renamed to BanChatMember in later versions of the Telegram Bot API.
1349type KickChatMemberConfig = BanChatMemberConfig
1350
1351// RestrictChatMemberConfig contains fields to restrict members of chat
1352type RestrictChatMemberConfig struct {
1353	ChatMemberConfig
1354	UntilDate   int64
1355	Permissions *ChatPermissions
1356}
1357
1358func (config RestrictChatMemberConfig) method() string {
1359	return "restrictChatMember"
1360}
1361
1362func (config RestrictChatMemberConfig) params() (Params, error) {
1363	params := make(Params)
1364
1365	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1366	params.AddNonZero64("user_id", config.UserID)
1367
1368	err := params.AddInterface("permissions", config.Permissions)
1369	params.AddNonZero64("until_date", config.UntilDate)
1370
1371	return params, err
1372}
1373
1374// PromoteChatMemberConfig contains fields to promote members of chat
1375type PromoteChatMemberConfig struct {
1376	ChatMemberConfig
1377	IsAnonymous         bool
1378	CanManageChat       bool
1379	CanChangeInfo       bool
1380	CanPostMessages     bool
1381	CanEditMessages     bool
1382	CanDeleteMessages   bool
1383	CanManageVideoChats bool
1384	CanInviteUsers      bool
1385	CanRestrictMembers  bool
1386	CanPinMessages      bool
1387	CanPromoteMembers   bool
1388}
1389
1390func (config PromoteChatMemberConfig) method() string {
1391	return "promoteChatMember"
1392}
1393
1394func (config PromoteChatMemberConfig) params() (Params, error) {
1395	params := make(Params)
1396
1397	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1398	params.AddNonZero64("user_id", config.UserID)
1399
1400	params.AddBool("is_anonymous", config.IsAnonymous)
1401	params.AddBool("can_manage_chat", config.CanManageChat)
1402	params.AddBool("can_change_info", config.CanChangeInfo)
1403	params.AddBool("can_post_messages", config.CanPostMessages)
1404	params.AddBool("can_edit_messages", config.CanEditMessages)
1405	params.AddBool("can_delete_messages", config.CanDeleteMessages)
1406	params.AddBool("can_manage_video_chats", config.CanManageVideoChats)
1407	params.AddBool("can_invite_users", config.CanInviteUsers)
1408	params.AddBool("can_restrict_members", config.CanRestrictMembers)
1409	params.AddBool("can_pin_messages", config.CanPinMessages)
1410	params.AddBool("can_promote_members", config.CanPromoteMembers)
1411
1412	return params, nil
1413}
1414
1415// SetChatAdministratorCustomTitle sets the title of an administrative user
1416// promoted by the bot for a chat.
1417type SetChatAdministratorCustomTitle struct {
1418	ChatMemberConfig
1419	CustomTitle string
1420}
1421
1422func (SetChatAdministratorCustomTitle) method() string {
1423	return "setChatAdministratorCustomTitle"
1424}
1425
1426func (config SetChatAdministratorCustomTitle) params() (Params, error) {
1427	params := make(Params)
1428
1429	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1430	params.AddNonZero64("user_id", config.UserID)
1431	params.AddNonEmpty("custom_title", config.CustomTitle)
1432
1433	return params, nil
1434}
1435
1436// BanChatSenderChatConfig bans a channel chat in a supergroup or a channel. The
1437// owner of the chat will not be able to send messages and join live streams on
1438// behalf of the chat, unless it is unbanned first. The bot must be an
1439// administrator in the supergroup or channel for this to work and must have the
1440// appropriate administrator rights.
1441type BanChatSenderChatConfig struct {
1442	ChatID          int64
1443	ChannelUsername string
1444	SenderChatID    int64
1445	UntilDate       int
1446}
1447
1448func (config BanChatSenderChatConfig) method() string {
1449	return "banChatSenderChat"
1450}
1451
1452func (config BanChatSenderChatConfig) params() (Params, error) {
1453	params := make(Params)
1454
1455	_ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1456	params.AddNonZero64("sender_chat_id", config.SenderChatID)
1457	params.AddNonZero("until_date", config.UntilDate)
1458
1459	return params, nil
1460}
1461
1462// UnbanChatSenderChatConfig unbans a previously banned channel chat in a
1463// supergroup or channel. The bot must be an administrator for this to work and
1464// must have the appropriate administrator rights.
1465type UnbanChatSenderChatConfig struct {
1466	ChatID          int64
1467	ChannelUsername string
1468	SenderChatID    int64
1469}
1470
1471func (config UnbanChatSenderChatConfig) method() string {
1472	return "unbanChatSenderChat"
1473}
1474
1475func (config UnbanChatSenderChatConfig) params() (Params, error) {
1476	params := make(Params)
1477
1478	_ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1479	params.AddNonZero64("sender_chat_id", config.SenderChatID)
1480
1481	return params, nil
1482}
1483
1484// ChatConfig contains information about getting information on a chat.
1485type ChatConfig struct {
1486	ChatID             int64
1487	SuperGroupUsername string
1488}
1489
1490func (config ChatConfig) params() (Params, error) {
1491	params := make(Params)
1492
1493	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1494
1495	return params, nil
1496}
1497
1498// ChatInfoConfig contains information about getting chat information.
1499type ChatInfoConfig struct {
1500	ChatConfig
1501}
1502
1503func (ChatInfoConfig) method() string {
1504	return "getChat"
1505}
1506
1507// ChatMemberCountConfig contains information about getting the number of users in a chat.
1508type ChatMemberCountConfig struct {
1509	ChatConfig
1510}
1511
1512func (ChatMemberCountConfig) method() string {
1513	return "getChatMembersCount"
1514}
1515
1516// ChatAdministratorsConfig contains information about getting chat administrators.
1517type ChatAdministratorsConfig struct {
1518	ChatConfig
1519}
1520
1521func (ChatAdministratorsConfig) method() string {
1522	return "getChatAdministrators"
1523}
1524
1525// SetChatPermissionsConfig allows you to set default permissions for the
1526// members in a group. The bot must be an administrator and have rights to
1527// restrict members.
1528type SetChatPermissionsConfig struct {
1529	ChatConfig
1530	Permissions *ChatPermissions
1531}
1532
1533func (SetChatPermissionsConfig) method() string {
1534	return "setChatPermissions"
1535}
1536
1537func (config SetChatPermissionsConfig) params() (Params, error) {
1538	params := make(Params)
1539
1540	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1541	err := params.AddInterface("permissions", config.Permissions)
1542
1543	return params, err
1544}
1545
1546// ChatInviteLinkConfig contains information about getting a chat link.
1547//
1548// Note that generating a new link will revoke any previous links.
1549type ChatInviteLinkConfig struct {
1550	ChatConfig
1551}
1552
1553func (ChatInviteLinkConfig) method() string {
1554	return "exportChatInviteLink"
1555}
1556
1557func (config ChatInviteLinkConfig) params() (Params, error) {
1558	params := make(Params)
1559
1560	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1561
1562	return params, nil
1563}
1564
1565// CreateChatInviteLinkConfig allows you to create an additional invite link for
1566// a chat. The bot must be an administrator in the chat for this to work and
1567// must have the appropriate admin rights. The link can be revoked using the
1568// RevokeChatInviteLinkConfig.
1569type CreateChatInviteLinkConfig struct {
1570	ChatConfig
1571	Name               string
1572	ExpireDate         int
1573	MemberLimit        int
1574	CreatesJoinRequest bool
1575}
1576
1577func (CreateChatInviteLinkConfig) method() string {
1578	return "createChatInviteLink"
1579}
1580
1581func (config CreateChatInviteLinkConfig) params() (Params, error) {
1582	params := make(Params)
1583
1584	params.AddNonEmpty("name", config.Name)
1585	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1586	params.AddNonZero("expire_date", config.ExpireDate)
1587	params.AddNonZero("member_limit", config.MemberLimit)
1588	params.AddBool("creates_join_request", config.CreatesJoinRequest)
1589
1590	return params, nil
1591}
1592
1593// EditChatInviteLinkConfig allows you to edit a non-primary invite link created
1594// by the bot. The bot must be an administrator in the chat for this to work and
1595// must have the appropriate admin rights.
1596type EditChatInviteLinkConfig struct {
1597	ChatConfig
1598	InviteLink         string
1599	Name               string
1600	ExpireDate         int
1601	MemberLimit        int
1602	CreatesJoinRequest bool
1603}
1604
1605func (EditChatInviteLinkConfig) method() string {
1606	return "editChatInviteLink"
1607}
1608
1609func (config EditChatInviteLinkConfig) params() (Params, error) {
1610	params := make(Params)
1611
1612	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1613	params.AddNonEmpty("name", config.Name)
1614	params["invite_link"] = config.InviteLink
1615	params.AddNonZero("expire_date", config.ExpireDate)
1616	params.AddNonZero("member_limit", config.MemberLimit)
1617	params.AddBool("creates_join_request", config.CreatesJoinRequest)
1618
1619	return params, nil
1620}
1621
1622// RevokeChatInviteLinkConfig allows you to revoke an invite link created by the
1623// bot. If the primary link is revoked, a new link is automatically generated.
1624// The bot must be an administrator in the chat for this to work and must have
1625// the appropriate admin rights.
1626type RevokeChatInviteLinkConfig struct {
1627	ChatConfig
1628	InviteLink string
1629}
1630
1631func (RevokeChatInviteLinkConfig) method() string {
1632	return "revokeChatInviteLink"
1633}
1634
1635func (config RevokeChatInviteLinkConfig) params() (Params, error) {
1636	params := make(Params)
1637
1638	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1639	params["invite_link"] = config.InviteLink
1640
1641	return params, nil
1642}
1643
1644// ApproveChatJoinRequestConfig allows you to approve a chat join request.
1645type ApproveChatJoinRequestConfig struct {
1646	ChatConfig
1647	UserID int64
1648}
1649
1650func (ApproveChatJoinRequestConfig) method() string {
1651	return "approveChatJoinRequest"
1652}
1653
1654func (config ApproveChatJoinRequestConfig) params() (Params, error) {
1655	params := make(Params)
1656
1657	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1658	params.AddNonZero("user_id", int(config.UserID))
1659
1660	return params, nil
1661}
1662
1663// DeclineChatJoinRequest allows you to decline a chat join request.
1664type DeclineChatJoinRequest struct {
1665	ChatConfig
1666	UserID int64
1667}
1668
1669func (DeclineChatJoinRequest) method() string {
1670	return "declineChatJoinRequest"
1671}
1672
1673func (config DeclineChatJoinRequest) params() (Params, error) {
1674	params := make(Params)
1675
1676	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1677	params.AddNonZero("user_id", int(config.UserID))
1678
1679	return params, nil
1680}
1681
1682// LeaveChatConfig allows you to leave a chat.
1683type LeaveChatConfig struct {
1684	ChatID          int64
1685	ChannelUsername string
1686}
1687
1688func (config LeaveChatConfig) method() string {
1689	return "leaveChat"
1690}
1691
1692func (config LeaveChatConfig) params() (Params, error) {
1693	params := make(Params)
1694
1695	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1696
1697	return params, nil
1698}
1699
1700// ChatConfigWithUser contains information about a chat and a user.
1701type ChatConfigWithUser struct {
1702	ChatID             int64
1703	SuperGroupUsername string
1704	UserID             int64
1705}
1706
1707func (config ChatConfigWithUser) params() (Params, error) {
1708	params := make(Params)
1709
1710	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1711	params.AddNonZero64("user_id", config.UserID)
1712
1713	return params, nil
1714}
1715
1716// GetChatMemberConfig is information about getting a specific member in a chat.
1717type GetChatMemberConfig struct {
1718	ChatConfigWithUser
1719}
1720
1721func (GetChatMemberConfig) method() string {
1722	return "getChatMember"
1723}
1724
1725// InvoiceConfig contains information for sendInvoice request.
1726type InvoiceConfig struct {
1727	BaseChat
1728	Title                     string         // required
1729	Description               string         // required
1730	Payload                   string         // required
1731	ProviderToken             string         // required
1732	Currency                  string         // required
1733	Prices                    []LabeledPrice // required
1734	MaxTipAmount              int
1735	SuggestedTipAmounts       []int
1736	StartParameter            string
1737	ProviderData              string
1738	PhotoURL                  string
1739	PhotoSize                 int
1740	PhotoWidth                int
1741	PhotoHeight               int
1742	NeedName                  bool
1743	NeedPhoneNumber           bool
1744	NeedEmail                 bool
1745	NeedShippingAddress       bool
1746	SendPhoneNumberToProvider bool
1747	SendEmailToProvider       bool
1748	IsFlexible                bool
1749}
1750
1751func (config InvoiceConfig) params() (Params, error) {
1752	params, err := config.BaseChat.params()
1753	if err != nil {
1754		return params, err
1755	}
1756
1757	params["title"] = config.Title
1758	params["description"] = config.Description
1759	params["payload"] = config.Payload
1760	params["provider_token"] = config.ProviderToken
1761	params["currency"] = config.Currency
1762	if err = params.AddInterface("prices", config.Prices); err != nil {
1763		return params, err
1764	}
1765
1766	params.AddNonZero("max_tip_amount", config.MaxTipAmount)
1767	err = params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts)
1768	params.AddNonEmpty("start_parameter", config.StartParameter)
1769	params.AddNonEmpty("provider_data", config.ProviderData)
1770	params.AddNonEmpty("photo_url", config.PhotoURL)
1771	params.AddNonZero("photo_size", config.PhotoSize)
1772	params.AddNonZero("photo_width", config.PhotoWidth)
1773	params.AddNonZero("photo_height", config.PhotoHeight)
1774	params.AddBool("need_name", config.NeedName)
1775	params.AddBool("need_phone_number", config.NeedPhoneNumber)
1776	params.AddBool("need_email", config.NeedEmail)
1777	params.AddBool("need_shipping_address", config.NeedShippingAddress)
1778	params.AddBool("is_flexible", config.IsFlexible)
1779	params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider)
1780	params.AddBool("send_email_to_provider", config.SendEmailToProvider)
1781
1782	return params, err
1783}
1784
1785func (config InvoiceConfig) method() string {
1786	return "sendInvoice"
1787}
1788
1789// InvoiceLinkConfig contains information for createInvoiceLink method
1790type InvoiceLinkConfig struct {
1791	Title                     string         //Required
1792	Description               string         //Required
1793	Payload                   string         //Required
1794	ProviderToken             string         //Required
1795	Currency                  string         //Required
1796	Prices                    []LabeledPrice //Required
1797	MaxTipAmount              int
1798	SuggestedTipAmounts       []int
1799	ProviderData              string
1800	PhotoURL                  string
1801	PhotoSize                 int
1802	PhotoWidth                int
1803	PhotoHeight               int
1804	NeedName                  bool
1805	NeedPhoneNumber           bool
1806	NeedEmail                 bool
1807	NeedShippingAddress       bool
1808	SendPhoneNumberToProvider bool
1809	SendEmailToProvider       bool
1810	IsFlexible                bool
1811}
1812
1813func (config InvoiceLinkConfig) params() (Params, error) {
1814	params := make(Params)
1815
1816	params["title"] = config.Title
1817	params["description"] = config.Description
1818	params["payload"] = config.Payload
1819	params["provider_token"] = config.ProviderToken
1820	params["currency"] = config.Currency
1821	if err := params.AddInterface("prices", config.Prices); err != nil {
1822		return params, err
1823	}
1824
1825	params.AddNonZero("max_tip_amount", config.MaxTipAmount)
1826	err := params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts)
1827	params.AddNonEmpty("provider_data", config.ProviderData)
1828	params.AddNonEmpty("photo_url", config.PhotoURL)
1829	params.AddNonZero("photo_size", config.PhotoSize)
1830	params.AddNonZero("photo_width", config.PhotoWidth)
1831	params.AddNonZero("photo_height", config.PhotoHeight)
1832	params.AddBool("need_name", config.NeedName)
1833	params.AddBool("need_phone_number", config.NeedPhoneNumber)
1834	params.AddBool("need_email", config.NeedEmail)
1835	params.AddBool("need_shipping_address", config.NeedShippingAddress)
1836	params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider)
1837	params.AddBool("send_email_to_provider", config.SendEmailToProvider)
1838	params.AddBool("is_flexible", config.IsFlexible)
1839
1840	return params, err
1841}
1842
1843func (config InvoiceLinkConfig) method() string {
1844	return "createInvoiceLink"
1845}
1846
1847// ShippingConfig contains information for answerShippingQuery request.
1848type ShippingConfig struct {
1849	ShippingQueryID string // required
1850	OK              bool   // required
1851	ShippingOptions []ShippingOption
1852	ErrorMessage    string
1853}
1854
1855func (config ShippingConfig) method() string {
1856	return "answerShippingQuery"
1857}
1858
1859func (config ShippingConfig) params() (Params, error) {
1860	params := make(Params)
1861
1862	params["shipping_query_id"] = config.ShippingQueryID
1863	params.AddBool("ok", config.OK)
1864	err := params.AddInterface("shipping_options", config.ShippingOptions)
1865	params.AddNonEmpty("error_message", config.ErrorMessage)
1866
1867	return params, err
1868}
1869
1870// PreCheckoutConfig contains information for answerPreCheckoutQuery request.
1871type PreCheckoutConfig struct {
1872	PreCheckoutQueryID string // required
1873	OK                 bool   // required
1874	ErrorMessage       string
1875}
1876
1877func (config PreCheckoutConfig) method() string {
1878	return "answerPreCheckoutQuery"
1879}
1880
1881func (config PreCheckoutConfig) params() (Params, error) {
1882	params := make(Params)
1883
1884	params["pre_checkout_query_id"] = config.PreCheckoutQueryID
1885	params.AddBool("ok", config.OK)
1886	params.AddNonEmpty("error_message", config.ErrorMessage)
1887
1888	return params, nil
1889}
1890
1891// DeleteMessageConfig contains information of a message in a chat to delete.
1892type DeleteMessageConfig struct {
1893	ChannelUsername string
1894	ChatID          int64
1895	MessageID       int
1896}
1897
1898func (config DeleteMessageConfig) method() string {
1899	return "deleteMessage"
1900}
1901
1902func (config DeleteMessageConfig) params() (Params, error) {
1903	params := make(Params)
1904
1905	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1906	params.AddNonZero("message_id", config.MessageID)
1907
1908	return params, nil
1909}
1910
1911// PinChatMessageConfig contains information of a message in a chat to pin.
1912type PinChatMessageConfig struct {
1913	ChatID              int64
1914	ChannelUsername     string
1915	MessageID           int
1916	DisableNotification bool
1917}
1918
1919func (config PinChatMessageConfig) method() string {
1920	return "pinChatMessage"
1921}
1922
1923func (config PinChatMessageConfig) params() (Params, error) {
1924	params := make(Params)
1925
1926	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1927	params.AddNonZero("message_id", config.MessageID)
1928	params.AddBool("disable_notification", config.DisableNotification)
1929
1930	return params, nil
1931}
1932
1933// UnpinChatMessageConfig contains information of a chat message to unpin.
1934//
1935// If MessageID is not specified, it will unpin the most recent pin.
1936type UnpinChatMessageConfig struct {
1937	ChatID          int64
1938	ChannelUsername string
1939	MessageID       int
1940}
1941
1942func (config UnpinChatMessageConfig) method() string {
1943	return "unpinChatMessage"
1944}
1945
1946func (config UnpinChatMessageConfig) params() (Params, error) {
1947	params := make(Params)
1948
1949	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1950	params.AddNonZero("message_id", config.MessageID)
1951
1952	return params, nil
1953}
1954
1955// UnpinAllChatMessagesConfig contains information of all messages to unpin in
1956// a chat.
1957type UnpinAllChatMessagesConfig struct {
1958	ChatID          int64
1959	ChannelUsername string
1960}
1961
1962func (config UnpinAllChatMessagesConfig) method() string {
1963	return "unpinAllChatMessages"
1964}
1965
1966func (config UnpinAllChatMessagesConfig) params() (Params, error) {
1967	params := make(Params)
1968
1969	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1970
1971	return params, nil
1972}
1973
1974// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.
1975type SetChatPhotoConfig struct {
1976	BaseFile
1977}
1978
1979func (config SetChatPhotoConfig) method() string {
1980	return "setChatPhoto"
1981}
1982
1983func (config SetChatPhotoConfig) files() []RequestFile {
1984	return []RequestFile{{
1985		Name: "photo",
1986		Data: config.File,
1987	}}
1988}
1989
1990// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
1991type DeleteChatPhotoConfig struct {
1992	ChatID          int64
1993	ChannelUsername string
1994}
1995
1996func (config DeleteChatPhotoConfig) method() string {
1997	return "deleteChatPhoto"
1998}
1999
2000func (config DeleteChatPhotoConfig) params() (Params, error) {
2001	params := make(Params)
2002
2003	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2004
2005	return params, nil
2006}
2007
2008// SetChatTitleConfig allows you to set the title of something other than a private chat.
2009type SetChatTitleConfig struct {
2010	ChatID          int64
2011	ChannelUsername string
2012
2013	Title string
2014}
2015
2016func (config SetChatTitleConfig) method() string {
2017	return "setChatTitle"
2018}
2019
2020func (config SetChatTitleConfig) params() (Params, error) {
2021	params := make(Params)
2022
2023	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2024	params["title"] = config.Title
2025
2026	return params, nil
2027}
2028
2029// SetChatDescriptionConfig allows you to set the description of a supergroup or channel.
2030type SetChatDescriptionConfig struct {
2031	ChatID          int64
2032	ChannelUsername string
2033
2034	Description string
2035}
2036
2037func (config SetChatDescriptionConfig) method() string {
2038	return "setChatDescription"
2039}
2040
2041func (config SetChatDescriptionConfig) params() (Params, error) {
2042	params := make(Params)
2043
2044	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2045	params["description"] = config.Description
2046
2047	return params, nil
2048}
2049
2050// GetStickerSetConfig allows you to get the stickers in a set.
2051type GetStickerSetConfig struct {
2052	Name string
2053}
2054
2055func (config GetStickerSetConfig) method() string {
2056	return "getStickerSet"
2057}
2058
2059func (config GetStickerSetConfig) params() (Params, error) {
2060	params := make(Params)
2061
2062	params["name"] = config.Name
2063
2064	return params, nil
2065}
2066
2067// UploadStickerConfig allows you to upload a sticker for use in a set later.
2068type UploadStickerConfig struct {
2069	UserID     int64
2070	PNGSticker RequestFileData
2071}
2072
2073func (config UploadStickerConfig) method() string {
2074	return "uploadStickerFile"
2075}
2076
2077func (config UploadStickerConfig) params() (Params, error) {
2078	params := make(Params)
2079
2080	params.AddNonZero64("user_id", config.UserID)
2081
2082	return params, nil
2083}
2084
2085func (config UploadStickerConfig) files() []RequestFile {
2086	return []RequestFile{{
2087		Name: "png_sticker",
2088		Data: config.PNGSticker,
2089	}}
2090}
2091
2092// NewStickerSetConfig allows creating a new sticker set.
2093//
2094// You must set either PNGSticker or TGSSticker.
2095type NewStickerSetConfig struct {
2096	UserID        int64
2097	Name          string
2098	Title         string
2099	PNGSticker    RequestFileData
2100	TGSSticker    RequestFileData
2101	Emojis        string
2102	ContainsMasks bool
2103	MaskPosition  *MaskPosition
2104}
2105
2106func (config NewStickerSetConfig) method() string {
2107	return "createNewStickerSet"
2108}
2109
2110func (config NewStickerSetConfig) params() (Params, error) {
2111	params := make(Params)
2112
2113	params.AddNonZero64("user_id", config.UserID)
2114	params["name"] = config.Name
2115	params["title"] = config.Title
2116
2117	params["emojis"] = config.Emojis
2118
2119	params.AddBool("contains_masks", config.ContainsMasks)
2120
2121	err := params.AddInterface("mask_position", config.MaskPosition)
2122
2123	return params, err
2124}
2125
2126func (config NewStickerSetConfig) files() []RequestFile {
2127	if config.PNGSticker != nil {
2128		return []RequestFile{{
2129			Name: "png_sticker",
2130			Data: config.PNGSticker,
2131		}}
2132	}
2133
2134	return []RequestFile{{
2135		Name: "tgs_sticker",
2136		Data: config.TGSSticker,
2137	}}
2138}
2139
2140// AddStickerConfig allows you to add a sticker to a set.
2141type AddStickerConfig struct {
2142	UserID       int64
2143	Name         string
2144	PNGSticker   RequestFileData
2145	TGSSticker   RequestFileData
2146	Emojis       string
2147	MaskPosition *MaskPosition
2148}
2149
2150func (config AddStickerConfig) method() string {
2151	return "addStickerToSet"
2152}
2153
2154func (config AddStickerConfig) params() (Params, error) {
2155	params := make(Params)
2156
2157	params.AddNonZero64("user_id", config.UserID)
2158	params["name"] = config.Name
2159	params["emojis"] = config.Emojis
2160
2161	err := params.AddInterface("mask_position", config.MaskPosition)
2162
2163	return params, err
2164}
2165
2166func (config AddStickerConfig) files() []RequestFile {
2167	if config.PNGSticker != nil {
2168		return []RequestFile{{
2169			Name: "png_sticker",
2170			Data: config.PNGSticker,
2171		}}
2172	}
2173
2174	return []RequestFile{{
2175		Name: "tgs_sticker",
2176		Data: config.TGSSticker,
2177	}}
2178
2179}
2180
2181// SetStickerPositionConfig allows you to change the position of a sticker in a set.
2182type SetStickerPositionConfig struct {
2183	Sticker  string
2184	Position int
2185}
2186
2187func (config SetStickerPositionConfig) method() string {
2188	return "setStickerPositionInSet"
2189}
2190
2191func (config SetStickerPositionConfig) params() (Params, error) {
2192	params := make(Params)
2193
2194	params["sticker"] = config.Sticker
2195	params.AddNonZero("position", config.Position)
2196
2197	return params, nil
2198}
2199
2200// DeleteStickerConfig allows you to delete a sticker from a set.
2201type DeleteStickerConfig struct {
2202	Sticker string
2203}
2204
2205func (config DeleteStickerConfig) method() string {
2206	return "deleteStickerFromSet"
2207}
2208
2209func (config DeleteStickerConfig) params() (Params, error) {
2210	params := make(Params)
2211
2212	params["sticker"] = config.Sticker
2213
2214	return params, nil
2215}
2216
2217// SetStickerSetThumbConfig allows you to set the thumbnail for a sticker set.
2218type SetStickerSetThumbConfig struct {
2219	Name   string
2220	UserID int64
2221	Thumb  RequestFileData
2222}
2223
2224func (config SetStickerSetThumbConfig) method() string {
2225	return "setStickerSetThumb"
2226}
2227
2228func (config SetStickerSetThumbConfig) params() (Params, error) {
2229	params := make(Params)
2230
2231	params["name"] = config.Name
2232	params.AddNonZero64("user_id", config.UserID)
2233
2234	return params, nil
2235}
2236
2237func (config SetStickerSetThumbConfig) files() []RequestFile {
2238	return []RequestFile{{
2239		Name: "thumb",
2240		Data: config.Thumb,
2241	}}
2242}
2243
2244// SetChatStickerSetConfig allows you to set the sticker set for a supergroup.
2245type SetChatStickerSetConfig struct {
2246	ChatID             int64
2247	SuperGroupUsername string
2248
2249	StickerSetName string
2250}
2251
2252func (config SetChatStickerSetConfig) method() string {
2253	return "setChatStickerSet"
2254}
2255
2256func (config SetChatStickerSetConfig) params() (Params, error) {
2257	params := make(Params)
2258
2259	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
2260	params["sticker_set_name"] = config.StickerSetName
2261
2262	return params, nil
2263}
2264
2265// DeleteChatStickerSetConfig allows you to remove a supergroup's sticker set.
2266type DeleteChatStickerSetConfig struct {
2267	ChatID             int64
2268	SuperGroupUsername string
2269}
2270
2271func (config DeleteChatStickerSetConfig) method() string {
2272	return "deleteChatStickerSet"
2273}
2274
2275func (config DeleteChatStickerSetConfig) params() (Params, error) {
2276	params := make(Params)
2277
2278	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
2279
2280	return params, nil
2281}
2282
2283// MediaGroupConfig allows you to send a group of media.
2284//
2285// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo).
2286type MediaGroupConfig struct {
2287	ChatID          int64
2288	ChannelUsername string
2289
2290	Media               []interface{}
2291	DisableNotification bool
2292	ReplyToMessageID    int
2293}
2294
2295func (config MediaGroupConfig) method() string {
2296	return "sendMediaGroup"
2297}
2298
2299func (config MediaGroupConfig) params() (Params, error) {
2300	params := make(Params)
2301
2302	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2303	params.AddBool("disable_notification", config.DisableNotification)
2304	params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
2305
2306	err := params.AddInterface("media", prepareInputMediaForParams(config.Media))
2307
2308	return params, err
2309}
2310
2311func (config MediaGroupConfig) files() []RequestFile {
2312	return prepareInputMediaForFiles(config.Media)
2313}
2314
2315// DiceConfig contains information about a sendDice request.
2316type DiceConfig struct {
2317	BaseChat
2318	// Emoji on which the dice throw animation is based.
2319	// Currently, must be one of 🎲, 🎯, 🏀, ⚽, 🎳, or 🎰.
2320	// Dice can have values 1-6 for 🎲, 🎯, and 🎳, values 1-5 for 🏀 and ⚽,
2321	// and values 1-64 for 🎰.
2322	// Defaults to “🎲”
2323	Emoji string
2324}
2325
2326func (config DiceConfig) method() string {
2327	return "sendDice"
2328}
2329
2330func (config DiceConfig) params() (Params, error) {
2331	params, err := config.BaseChat.params()
2332	if err != nil {
2333		return params, err
2334	}
2335
2336	params.AddNonEmpty("emoji", config.Emoji)
2337
2338	return params, err
2339}
2340
2341// GetMyCommandsConfig gets a list of the currently registered commands.
2342type GetMyCommandsConfig struct {
2343	Scope        *BotCommandScope
2344	LanguageCode string
2345}
2346
2347func (config GetMyCommandsConfig) method() string {
2348	return "getMyCommands"
2349}
2350
2351func (config GetMyCommandsConfig) params() (Params, error) {
2352	params := make(Params)
2353
2354	err := params.AddInterface("scope", config.Scope)
2355	params.AddNonEmpty("language_code", config.LanguageCode)
2356
2357	return params, err
2358}
2359
2360// SetMyCommandsConfig sets a list of commands the bot understands.
2361type SetMyCommandsConfig struct {
2362	Commands     []BotCommand
2363	Scope        *BotCommandScope
2364	LanguageCode string
2365}
2366
2367func (config SetMyCommandsConfig) method() string {
2368	return "setMyCommands"
2369}
2370
2371func (config SetMyCommandsConfig) params() (Params, error) {
2372	params := make(Params)
2373
2374	if err := params.AddInterface("commands", config.Commands); err != nil {
2375		return params, err
2376	}
2377	err := params.AddInterface("scope", config.Scope)
2378	params.AddNonEmpty("language_code", config.LanguageCode)
2379
2380	return params, err
2381}
2382
2383type DeleteMyCommandsConfig struct {
2384	Scope        *BotCommandScope
2385	LanguageCode string
2386}
2387
2388func (config DeleteMyCommandsConfig) method() string {
2389	return "deleteMyCommands"
2390}
2391
2392func (config DeleteMyCommandsConfig) params() (Params, error) {
2393	params := make(Params)
2394
2395	err := params.AddInterface("scope", config.Scope)
2396	params.AddNonEmpty("language_code", config.LanguageCode)
2397
2398	return params, err
2399}
2400
2401// SetChatMenuButtonConfig changes the bot's menu button in a private chat,
2402// or the default menu button.
2403type SetChatMenuButtonConfig struct {
2404	ChatID          int64
2405	ChannelUsername string
2406
2407	MenuButton *MenuButton
2408}
2409
2410func (config SetChatMenuButtonConfig) method() string {
2411	return "setChatMenuButton"
2412}
2413
2414func (config SetChatMenuButtonConfig) params() (Params, error) {
2415	params := make(Params)
2416
2417	if err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername); err != nil {
2418		return params, err
2419	}
2420	err := params.AddInterface("menu_button", config.MenuButton)
2421
2422	return params, err
2423}
2424
2425type GetChatMenuButtonConfig struct {
2426	ChatID          int64
2427	ChannelUsername string
2428}
2429
2430func (config GetChatMenuButtonConfig) method() string {
2431	return "getChatMenuButton"
2432}
2433
2434func (config GetChatMenuButtonConfig) params() (Params, error) {
2435	params := make(Params)
2436
2437	err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2438
2439	return params, err
2440}
2441
2442type SetMyDefaultAdministratorRightsConfig struct {
2443	Rights      ChatAdministratorRights
2444	ForChannels bool
2445}
2446
2447func (config SetMyDefaultAdministratorRightsConfig) method() string {
2448	return "setMyDefaultAdministratorRights"
2449}
2450
2451func (config SetMyDefaultAdministratorRightsConfig) params() (Params, error) {
2452	params := make(Params)
2453
2454	err := params.AddInterface("rights", config.Rights)
2455	params.AddBool("for_channels", config.ForChannels)
2456
2457	return params, err
2458}
2459
2460type GetMyDefaultAdministratorRightsConfig struct {
2461	ForChannels bool
2462}
2463
2464func (config GetMyDefaultAdministratorRightsConfig) method() string {
2465	return "getMyDefaultAdministratorRights"
2466}
2467
2468func (config GetMyDefaultAdministratorRightsConfig) params() (Params, error) {
2469	params := make(Params)
2470
2471	params.AddBool("for_channels", config.ForChannels)
2472
2473	return params, nil
2474}
2475
2476// prepareInputMediaParam evaluates a single InputMedia and determines if it
2477// needs to be modified for a successful upload. If it returns nil, then the
2478// value does not need to be included in the params. Otherwise, it will return
2479// the same type as was originally provided.
2480//
2481// The idx is used to calculate the file field name. If you only have a single
2482// file, 0 may be used. It is formatted into "attach://file-%d" for the primary
2483// media and "attach://file-%d-thumb" for thumbnails.
2484//
2485// It is expected to be used in conjunction with prepareInputMediaFile.
2486func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} {
2487	switch m := inputMedia.(type) {
2488	case InputMediaPhoto:
2489		if m.Media.NeedsUpload() {
2490			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2491		}
2492
2493		return m
2494	case InputMediaVideo:
2495		if m.Media.NeedsUpload() {
2496			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2497		}
2498
2499		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2500			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2501		}
2502
2503		return m
2504	case InputMediaAudio:
2505		if m.Media.NeedsUpload() {
2506			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2507		}
2508
2509		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2510			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2511		}
2512
2513		return m
2514	case InputMediaDocument:
2515		if m.Media.NeedsUpload() {
2516			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2517		}
2518
2519		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2520			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2521		}
2522
2523		return m
2524	}
2525
2526	return nil
2527}
2528
2529// prepareInputMediaFile generates an array of RequestFile to provide for
2530// Fileable's files method. It returns an array as a single InputMedia may have
2531// multiple files, for the primary media and a thumbnail.
2532//
2533// The idx parameter is used to generate file field names. It uses the names
2534// "file-%d" for the main file and "file-%d-thumb" for the thumbnail.
2535//
2536// It is expected to be used in conjunction with prepareInputMediaParam.
2537func prepareInputMediaFile(inputMedia interface{}, idx int) []RequestFile {
2538	files := []RequestFile{}
2539
2540	switch m := inputMedia.(type) {
2541	case InputMediaPhoto:
2542		if m.Media.NeedsUpload() {
2543			files = append(files, RequestFile{
2544				Name: fmt.Sprintf("file-%d", idx),
2545				Data: m.Media,
2546			})
2547		}
2548	case InputMediaVideo:
2549		if m.Media.NeedsUpload() {
2550			files = append(files, RequestFile{
2551				Name: fmt.Sprintf("file-%d", idx),
2552				Data: m.Media,
2553			})
2554		}
2555
2556		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2557			files = append(files, RequestFile{
2558				Name: fmt.Sprintf("file-%d", idx),
2559				Data: m.Thumb,
2560			})
2561		}
2562	case InputMediaDocument:
2563		if m.Media.NeedsUpload() {
2564			files = append(files, RequestFile{
2565				Name: fmt.Sprintf("file-%d", idx),
2566				Data: m.Media,
2567			})
2568		}
2569
2570		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2571			files = append(files, RequestFile{
2572				Name: fmt.Sprintf("file-%d", idx),
2573				Data: m.Thumb,
2574			})
2575		}
2576	case InputMediaAudio:
2577		if m.Media.NeedsUpload() {
2578			files = append(files, RequestFile{
2579				Name: fmt.Sprintf("file-%d", idx),
2580				Data: m.Media,
2581			})
2582		}
2583
2584		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2585			files = append(files, RequestFile{
2586				Name: fmt.Sprintf("file-%d", idx),
2587				Data: m.Thumb,
2588			})
2589		}
2590	}
2591
2592	return files
2593}
2594
2595// prepareInputMediaForParams calls prepareInputMediaParam for each item
2596// provided and returns a new array with the correct params for a request.
2597//
2598// It is expected that files will get data from the associated function,
2599// prepareInputMediaForFiles.
2600func prepareInputMediaForParams(inputMedia []interface{}) []interface{} {
2601	newMedia := make([]interface{}, len(inputMedia))
2602	copy(newMedia, inputMedia)
2603
2604	for idx, media := range inputMedia {
2605		if param := prepareInputMediaParam(media, idx); param != nil {
2606			newMedia[idx] = param
2607		}
2608	}
2609
2610	return newMedia
2611}
2612
2613// prepareInputMediaForFiles calls prepareInputMediaFile for each item
2614// provided and returns a new array with the correct files for a request.
2615//
2616// It is expected that params will get data from the associated function,
2617// prepareInputMediaForParams.
2618func prepareInputMediaForFiles(inputMedia []interface{}) []RequestFile {
2619	files := []RequestFile{}
2620
2621	for idx, media := range inputMedia {
2622		if file := prepareInputMediaFile(media, idx); file != nil {
2623			files = append(files, file...)
2624		}
2625	}
2626
2627	return files
2628}