all repos — telegram-bot-api @ fde05dd128a5e2c022eb2236bfa1c99f6f8e1d82

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}
1168
1169func (config WebhookConfig) method() string {
1170	return "setWebhook"
1171}
1172
1173func (config WebhookConfig) params() (Params, error) {
1174	params := make(Params)
1175
1176	if config.URL != nil {
1177		params["url"] = config.URL.String()
1178	}
1179
1180	params.AddNonEmpty("ip_address", config.IPAddress)
1181	params.AddNonZero("max_connections", config.MaxConnections)
1182	err := params.AddInterface("allowed_updates", config.AllowedUpdates)
1183	params.AddBool("drop_pending_updates", config.DropPendingUpdates)
1184
1185	return params, err
1186}
1187
1188func (config WebhookConfig) files() []RequestFile {
1189	if config.Certificate != nil {
1190		return []RequestFile{{
1191			Name: "certificate",
1192			Data: config.Certificate,
1193		}}
1194	}
1195
1196	return nil
1197}
1198
1199// DeleteWebhookConfig is a helper to delete a webhook.
1200type DeleteWebhookConfig struct {
1201	DropPendingUpdates bool
1202}
1203
1204func (config DeleteWebhookConfig) method() string {
1205	return "deleteWebhook"
1206}
1207
1208func (config DeleteWebhookConfig) params() (Params, error) {
1209	params := make(Params)
1210
1211	params.AddBool("drop_pending_updates", config.DropPendingUpdates)
1212
1213	return params, nil
1214}
1215
1216// InlineConfig contains information on making an InlineQuery response.
1217type InlineConfig struct {
1218	InlineQueryID     string        `json:"inline_query_id"`
1219	Results           []interface{} `json:"results"`
1220	CacheTime         int           `json:"cache_time"`
1221	IsPersonal        bool          `json:"is_personal"`
1222	NextOffset        string        `json:"next_offset"`
1223	SwitchPMText      string        `json:"switch_pm_text"`
1224	SwitchPMParameter string        `json:"switch_pm_parameter"`
1225}
1226
1227func (config InlineConfig) method() string {
1228	return "answerInlineQuery"
1229}
1230
1231func (config InlineConfig) params() (Params, error) {
1232	params := make(Params)
1233
1234	params["inline_query_id"] = config.InlineQueryID
1235	params.AddNonZero("cache_time", config.CacheTime)
1236	params.AddBool("is_personal", config.IsPersonal)
1237	params.AddNonEmpty("next_offset", config.NextOffset)
1238	params.AddNonEmpty("switch_pm_text", config.SwitchPMText)
1239	params.AddNonEmpty("switch_pm_parameter", config.SwitchPMParameter)
1240	err := params.AddInterface("results", config.Results)
1241
1242	return params, err
1243}
1244
1245// AnswerWebAppQueryConfig is used to set the result of an interaction with a
1246// Web App and send a corresponding message on behalf of the user to the chat
1247// from which the query originated.
1248type AnswerWebAppQueryConfig struct {
1249	// WebAppQueryID is the unique identifier for the query to be answered.
1250	WebAppQueryID string `json:"web_app_query_id"`
1251	// Result is an InlineQueryResult object describing the message to be sent.
1252	Result interface{} `json:"result"`
1253}
1254
1255func (config AnswerWebAppQueryConfig) method() string {
1256	return "answerWebAppQuery"
1257}
1258
1259func (config AnswerWebAppQueryConfig) params() (Params, error) {
1260	params := make(Params)
1261
1262	params["web_app_query_id"] = config.WebAppQueryID
1263	err := params.AddInterface("result", config.Result)
1264
1265	return params, err
1266}
1267
1268// CallbackConfig contains information on making a CallbackQuery response.
1269type CallbackConfig struct {
1270	CallbackQueryID string `json:"callback_query_id"`
1271	Text            string `json:"text"`
1272	ShowAlert       bool   `json:"show_alert"`
1273	URL             string `json:"url"`
1274	CacheTime       int    `json:"cache_time"`
1275}
1276
1277func (config CallbackConfig) method() string {
1278	return "answerCallbackQuery"
1279}
1280
1281func (config CallbackConfig) params() (Params, error) {
1282	params := make(Params)
1283
1284	params["callback_query_id"] = config.CallbackQueryID
1285	params.AddNonEmpty("text", config.Text)
1286	params.AddBool("show_alert", config.ShowAlert)
1287	params.AddNonEmpty("url", config.URL)
1288	params.AddNonZero("cache_time", config.CacheTime)
1289
1290	return params, nil
1291}
1292
1293// ChatMemberConfig contains information about a user in a chat for use
1294// with administrative functions such as kicking or unbanning a user.
1295type ChatMemberConfig struct {
1296	ChatID             int64
1297	SuperGroupUsername string
1298	ChannelUsername    string
1299	UserID             int64
1300}
1301
1302// UnbanChatMemberConfig allows you to unban a user.
1303type UnbanChatMemberConfig struct {
1304	ChatMemberConfig
1305	OnlyIfBanned bool
1306}
1307
1308func (config UnbanChatMemberConfig) method() string {
1309	return "unbanChatMember"
1310}
1311
1312func (config UnbanChatMemberConfig) params() (Params, error) {
1313	params := make(Params)
1314
1315	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1316	params.AddNonZero64("user_id", config.UserID)
1317	params.AddBool("only_if_banned", config.OnlyIfBanned)
1318
1319	return params, nil
1320}
1321
1322// BanChatMemberConfig contains extra fields to kick user.
1323type BanChatMemberConfig struct {
1324	ChatMemberConfig
1325	UntilDate      int64
1326	RevokeMessages bool
1327}
1328
1329func (config BanChatMemberConfig) method() string {
1330	return "banChatMember"
1331}
1332
1333func (config BanChatMemberConfig) params() (Params, error) {
1334	params := make(Params)
1335
1336	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1337	params.AddNonZero64("user_id", config.UserID)
1338	params.AddNonZero64("until_date", config.UntilDate)
1339	params.AddBool("revoke_messages", config.RevokeMessages)
1340
1341	return params, nil
1342}
1343
1344// KickChatMemberConfig contains extra fields to ban user.
1345//
1346// This was renamed to BanChatMember in later versions of the Telegram Bot API.
1347type KickChatMemberConfig = BanChatMemberConfig
1348
1349// RestrictChatMemberConfig contains fields to restrict members of chat
1350type RestrictChatMemberConfig struct {
1351	ChatMemberConfig
1352	UntilDate   int64
1353	Permissions *ChatPermissions
1354}
1355
1356func (config RestrictChatMemberConfig) method() string {
1357	return "restrictChatMember"
1358}
1359
1360func (config RestrictChatMemberConfig) params() (Params, error) {
1361	params := make(Params)
1362
1363	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1364	params.AddNonZero64("user_id", config.UserID)
1365
1366	err := params.AddInterface("permissions", config.Permissions)
1367	params.AddNonZero64("until_date", config.UntilDate)
1368
1369	return params, err
1370}
1371
1372// PromoteChatMemberConfig contains fields to promote members of chat
1373type PromoteChatMemberConfig struct {
1374	ChatMemberConfig
1375	IsAnonymous         bool
1376	CanManageChat       bool
1377	CanChangeInfo       bool
1378	CanPostMessages     bool
1379	CanEditMessages     bool
1380	CanDeleteMessages   bool
1381	CanManageVideoChats bool
1382	CanInviteUsers      bool
1383	CanRestrictMembers  bool
1384	CanPinMessages      bool
1385	CanPromoteMembers   bool
1386}
1387
1388func (config PromoteChatMemberConfig) method() string {
1389	return "promoteChatMember"
1390}
1391
1392func (config PromoteChatMemberConfig) params() (Params, error) {
1393	params := make(Params)
1394
1395	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1396	params.AddNonZero64("user_id", config.UserID)
1397
1398	params.AddBool("is_anonymous", config.IsAnonymous)
1399	params.AddBool("can_manage_chat", config.CanManageChat)
1400	params.AddBool("can_change_info", config.CanChangeInfo)
1401	params.AddBool("can_post_messages", config.CanPostMessages)
1402	params.AddBool("can_edit_messages", config.CanEditMessages)
1403	params.AddBool("can_delete_messages", config.CanDeleteMessages)
1404	params.AddBool("can_manage_video_chats", config.CanManageVideoChats)
1405	params.AddBool("can_invite_users", config.CanInviteUsers)
1406	params.AddBool("can_restrict_members", config.CanRestrictMembers)
1407	params.AddBool("can_pin_messages", config.CanPinMessages)
1408	params.AddBool("can_promote_members", config.CanPromoteMembers)
1409
1410	return params, nil
1411}
1412
1413// SetChatAdministratorCustomTitle sets the title of an administrative user
1414// promoted by the bot for a chat.
1415type SetChatAdministratorCustomTitle struct {
1416	ChatMemberConfig
1417	CustomTitle string
1418}
1419
1420func (SetChatAdministratorCustomTitle) method() string {
1421	return "setChatAdministratorCustomTitle"
1422}
1423
1424func (config SetChatAdministratorCustomTitle) params() (Params, error) {
1425	params := make(Params)
1426
1427	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1428	params.AddNonZero64("user_id", config.UserID)
1429	params.AddNonEmpty("custom_title", config.CustomTitle)
1430
1431	return params, nil
1432}
1433
1434// BanChatSenderChatConfig bans a channel chat in a supergroup or a channel. The
1435// owner of the chat will not be able to send messages and join live streams on
1436// behalf of the chat, unless it is unbanned first. The bot must be an
1437// administrator in the supergroup or channel for this to work and must have the
1438// appropriate administrator rights.
1439type BanChatSenderChatConfig struct {
1440	ChatID          int64
1441	ChannelUsername string
1442	SenderChatID    int64
1443	UntilDate       int
1444}
1445
1446func (config BanChatSenderChatConfig) method() string {
1447	return "banChatSenderChat"
1448}
1449
1450func (config BanChatSenderChatConfig) params() (Params, error) {
1451	params := make(Params)
1452
1453	_ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1454	params.AddNonZero64("sender_chat_id", config.SenderChatID)
1455	params.AddNonZero("until_date", config.UntilDate)
1456
1457	return params, nil
1458}
1459
1460// UnbanChatSenderChatConfig unbans a previously banned channel chat in a
1461// supergroup or channel. The bot must be an administrator for this to work and
1462// must have the appropriate administrator rights.
1463type UnbanChatSenderChatConfig struct {
1464	ChatID          int64
1465	ChannelUsername string
1466	SenderChatID    int64
1467}
1468
1469func (config UnbanChatSenderChatConfig) method() string {
1470	return "unbanChatSenderChat"
1471}
1472
1473func (config UnbanChatSenderChatConfig) params() (Params, error) {
1474	params := make(Params)
1475
1476	_ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1477	params.AddNonZero64("sender_chat_id", config.SenderChatID)
1478
1479	return params, nil
1480}
1481
1482// ChatConfig contains information about getting information on a chat.
1483type ChatConfig struct {
1484	ChatID             int64
1485	SuperGroupUsername string
1486}
1487
1488func (config ChatConfig) params() (Params, error) {
1489	params := make(Params)
1490
1491	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1492
1493	return params, nil
1494}
1495
1496// ChatInfoConfig contains information about getting chat information.
1497type ChatInfoConfig struct {
1498	ChatConfig
1499}
1500
1501func (ChatInfoConfig) method() string {
1502	return "getChat"
1503}
1504
1505// ChatMemberCountConfig contains information about getting the number of users in a chat.
1506type ChatMemberCountConfig struct {
1507	ChatConfig
1508}
1509
1510func (ChatMemberCountConfig) method() string {
1511	return "getChatMembersCount"
1512}
1513
1514// ChatAdministratorsConfig contains information about getting chat administrators.
1515type ChatAdministratorsConfig struct {
1516	ChatConfig
1517}
1518
1519func (ChatAdministratorsConfig) method() string {
1520	return "getChatAdministrators"
1521}
1522
1523// SetChatPermissionsConfig allows you to set default permissions for the
1524// members in a group. The bot must be an administrator and have rights to
1525// restrict members.
1526type SetChatPermissionsConfig struct {
1527	ChatConfig
1528	Permissions *ChatPermissions
1529}
1530
1531func (SetChatPermissionsConfig) method() string {
1532	return "setChatPermissions"
1533}
1534
1535func (config SetChatPermissionsConfig) params() (Params, error) {
1536	params := make(Params)
1537
1538	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1539	err := params.AddInterface("permissions", config.Permissions)
1540
1541	return params, err
1542}
1543
1544// ChatInviteLinkConfig contains information about getting a chat link.
1545//
1546// Note that generating a new link will revoke any previous links.
1547type ChatInviteLinkConfig struct {
1548	ChatConfig
1549}
1550
1551func (ChatInviteLinkConfig) method() string {
1552	return "exportChatInviteLink"
1553}
1554
1555func (config ChatInviteLinkConfig) params() (Params, error) {
1556	params := make(Params)
1557
1558	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1559
1560	return params, nil
1561}
1562
1563// CreateChatInviteLinkConfig allows you to create an additional invite link for
1564// a chat. The bot must be an administrator in the chat for this to work and
1565// must have the appropriate admin rights. The link can be revoked using the
1566// RevokeChatInviteLinkConfig.
1567type CreateChatInviteLinkConfig struct {
1568	ChatConfig
1569	Name               string
1570	ExpireDate         int
1571	MemberLimit        int
1572	CreatesJoinRequest bool
1573}
1574
1575func (CreateChatInviteLinkConfig) method() string {
1576	return "createChatInviteLink"
1577}
1578
1579func (config CreateChatInviteLinkConfig) params() (Params, error) {
1580	params := make(Params)
1581
1582	params.AddNonEmpty("name", config.Name)
1583	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1584	params.AddNonZero("expire_date", config.ExpireDate)
1585	params.AddNonZero("member_limit", config.MemberLimit)
1586	params.AddBool("creates_join_request", config.CreatesJoinRequest)
1587
1588	return params, nil
1589}
1590
1591// EditChatInviteLinkConfig allows you to edit a non-primary invite link created
1592// by the bot. The bot must be an administrator in the chat for this to work and
1593// must have the appropriate admin rights.
1594type EditChatInviteLinkConfig struct {
1595	ChatConfig
1596	InviteLink         string
1597	Name               string
1598	ExpireDate         int
1599	MemberLimit        int
1600	CreatesJoinRequest bool
1601}
1602
1603func (EditChatInviteLinkConfig) method() string {
1604	return "editChatInviteLink"
1605}
1606
1607func (config EditChatInviteLinkConfig) params() (Params, error) {
1608	params := make(Params)
1609
1610	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1611	params.AddNonEmpty("name", config.Name)
1612	params["invite_link"] = config.InviteLink
1613	params.AddNonZero("expire_date", config.ExpireDate)
1614	params.AddNonZero("member_limit", config.MemberLimit)
1615	params.AddBool("creates_join_request", config.CreatesJoinRequest)
1616
1617	return params, nil
1618}
1619
1620// RevokeChatInviteLinkConfig allows you to revoke an invite link created by the
1621// bot. If the primary link is revoked, a new link is automatically generated.
1622// The bot must be an administrator in the chat for this to work and must have
1623// the appropriate admin rights.
1624type RevokeChatInviteLinkConfig struct {
1625	ChatConfig
1626	InviteLink string
1627}
1628
1629func (RevokeChatInviteLinkConfig) method() string {
1630	return "revokeChatInviteLink"
1631}
1632
1633func (config RevokeChatInviteLinkConfig) params() (Params, error) {
1634	params := make(Params)
1635
1636	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1637	params["invite_link"] = config.InviteLink
1638
1639	return params, nil
1640}
1641
1642// ApproveChatJoinRequestConfig allows you to approve a chat join request.
1643type ApproveChatJoinRequestConfig struct {
1644	ChatConfig
1645	UserID int64
1646}
1647
1648func (ApproveChatJoinRequestConfig) method() string {
1649	return "approveChatJoinRequest"
1650}
1651
1652func (config ApproveChatJoinRequestConfig) params() (Params, error) {
1653	params := make(Params)
1654
1655	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1656	params.AddNonZero("user_id", int(config.UserID))
1657
1658	return params, nil
1659}
1660
1661// DeclineChatJoinRequest allows you to decline a chat join request.
1662type DeclineChatJoinRequest struct {
1663	ChatConfig
1664	UserID int64
1665}
1666
1667func (DeclineChatJoinRequest) method() string {
1668	return "declineChatJoinRequest"
1669}
1670
1671func (config DeclineChatJoinRequest) params() (Params, error) {
1672	params := make(Params)
1673
1674	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1675	params.AddNonZero("user_id", int(config.UserID))
1676
1677	return params, nil
1678}
1679
1680// LeaveChatConfig allows you to leave a chat.
1681type LeaveChatConfig struct {
1682	ChatID          int64
1683	ChannelUsername string
1684}
1685
1686func (config LeaveChatConfig) method() string {
1687	return "leaveChat"
1688}
1689
1690func (config LeaveChatConfig) params() (Params, error) {
1691	params := make(Params)
1692
1693	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1694
1695	return params, nil
1696}
1697
1698// ChatConfigWithUser contains information about a chat and a user.
1699type ChatConfigWithUser struct {
1700	ChatID             int64
1701	SuperGroupUsername string
1702	UserID             int64
1703}
1704
1705func (config ChatConfigWithUser) params() (Params, error) {
1706	params := make(Params)
1707
1708	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1709	params.AddNonZero64("user_id", config.UserID)
1710
1711	return params, nil
1712}
1713
1714// GetChatMemberConfig is information about getting a specific member in a chat.
1715type GetChatMemberConfig struct {
1716	ChatConfigWithUser
1717}
1718
1719func (GetChatMemberConfig) method() string {
1720	return "getChatMember"
1721}
1722
1723// InvoiceConfig contains information for sendInvoice request.
1724type InvoiceConfig struct {
1725	BaseChat
1726	Title                     string         // required
1727	Description               string         // required
1728	Payload                   string         // required
1729	ProviderToken             string         // required
1730	Currency                  string         // required
1731	Prices                    []LabeledPrice // required
1732	MaxTipAmount              int
1733	SuggestedTipAmounts       []int
1734	StartParameter            string
1735	ProviderData              string
1736	PhotoURL                  string
1737	PhotoSize                 int
1738	PhotoWidth                int
1739	PhotoHeight               int
1740	NeedName                  bool
1741	NeedPhoneNumber           bool
1742	NeedEmail                 bool
1743	NeedShippingAddress       bool
1744	SendPhoneNumberToProvider bool
1745	SendEmailToProvider       bool
1746	IsFlexible                bool
1747}
1748
1749func (config InvoiceConfig) params() (Params, error) {
1750	params, err := config.BaseChat.params()
1751	if err != nil {
1752		return params, err
1753	}
1754
1755	params["title"] = config.Title
1756	params["description"] = config.Description
1757	params["payload"] = config.Payload
1758	params["provider_token"] = config.ProviderToken
1759	params["currency"] = config.Currency
1760	if err = params.AddInterface("prices", config.Prices); err != nil {
1761		return params, err
1762	}
1763
1764	params.AddNonZero("max_tip_amount", config.MaxTipAmount)
1765	err = params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts)
1766	params.AddNonEmpty("start_parameter", config.StartParameter)
1767	params.AddNonEmpty("provider_data", config.ProviderData)
1768	params.AddNonEmpty("photo_url", config.PhotoURL)
1769	params.AddNonZero("photo_size", config.PhotoSize)
1770	params.AddNonZero("photo_width", config.PhotoWidth)
1771	params.AddNonZero("photo_height", config.PhotoHeight)
1772	params.AddBool("need_name", config.NeedName)
1773	params.AddBool("need_phone_number", config.NeedPhoneNumber)
1774	params.AddBool("need_email", config.NeedEmail)
1775	params.AddBool("need_shipping_address", config.NeedShippingAddress)
1776	params.AddBool("is_flexible", config.IsFlexible)
1777	params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider)
1778	params.AddBool("send_email_to_provider", config.SendEmailToProvider)
1779
1780	return params, err
1781}
1782
1783func (config InvoiceConfig) method() string {
1784	return "sendInvoice"
1785}
1786
1787// ShippingConfig contains information for answerShippingQuery request.
1788type ShippingConfig struct {
1789	ShippingQueryID string // required
1790	OK              bool   // required
1791	ShippingOptions []ShippingOption
1792	ErrorMessage    string
1793}
1794
1795func (config ShippingConfig) method() string {
1796	return "answerShippingQuery"
1797}
1798
1799func (config ShippingConfig) params() (Params, error) {
1800	params := make(Params)
1801
1802	params["shipping_query_id"] = config.ShippingQueryID
1803	params.AddBool("ok", config.OK)
1804	err := params.AddInterface("shipping_options", config.ShippingOptions)
1805	params.AddNonEmpty("error_message", config.ErrorMessage)
1806
1807	return params, err
1808}
1809
1810// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
1811type PreCheckoutConfig struct {
1812	PreCheckoutQueryID string // required
1813	OK                 bool   // required
1814	ErrorMessage       string
1815}
1816
1817func (config PreCheckoutConfig) method() string {
1818	return "answerPreCheckoutQuery"
1819}
1820
1821func (config PreCheckoutConfig) params() (Params, error) {
1822	params := make(Params)
1823
1824	params["pre_checkout_query_id"] = config.PreCheckoutQueryID
1825	params.AddBool("ok", config.OK)
1826	params.AddNonEmpty("error_message", config.ErrorMessage)
1827
1828	return params, nil
1829}
1830
1831// DeleteMessageConfig contains information of a message in a chat to delete.
1832type DeleteMessageConfig struct {
1833	ChannelUsername string
1834	ChatID          int64
1835	MessageID       int
1836}
1837
1838func (config DeleteMessageConfig) method() string {
1839	return "deleteMessage"
1840}
1841
1842func (config DeleteMessageConfig) params() (Params, error) {
1843	params := make(Params)
1844
1845	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1846	params.AddNonZero("message_id", config.MessageID)
1847
1848	return params, nil
1849}
1850
1851// PinChatMessageConfig contains information of a message in a chat to pin.
1852type PinChatMessageConfig struct {
1853	ChatID              int64
1854	ChannelUsername     string
1855	MessageID           int
1856	DisableNotification bool
1857}
1858
1859func (config PinChatMessageConfig) method() string {
1860	return "pinChatMessage"
1861}
1862
1863func (config PinChatMessageConfig) params() (Params, error) {
1864	params := make(Params)
1865
1866	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1867	params.AddNonZero("message_id", config.MessageID)
1868	params.AddBool("disable_notification", config.DisableNotification)
1869
1870	return params, nil
1871}
1872
1873// UnpinChatMessageConfig contains information of a chat message to unpin.
1874//
1875// If MessageID is not specified, it will unpin the most recent pin.
1876type UnpinChatMessageConfig struct {
1877	ChatID          int64
1878	ChannelUsername string
1879	MessageID       int
1880}
1881
1882func (config UnpinChatMessageConfig) method() string {
1883	return "unpinChatMessage"
1884}
1885
1886func (config UnpinChatMessageConfig) params() (Params, error) {
1887	params := make(Params)
1888
1889	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1890	params.AddNonZero("message_id", config.MessageID)
1891
1892	return params, nil
1893}
1894
1895// UnpinAllChatMessagesConfig contains information of all messages to unpin in
1896// a chat.
1897type UnpinAllChatMessagesConfig struct {
1898	ChatID          int64
1899	ChannelUsername string
1900}
1901
1902func (config UnpinAllChatMessagesConfig) method() string {
1903	return "unpinAllChatMessages"
1904}
1905
1906func (config UnpinAllChatMessagesConfig) params() (Params, error) {
1907	params := make(Params)
1908
1909	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1910
1911	return params, nil
1912}
1913
1914// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.
1915type SetChatPhotoConfig struct {
1916	BaseFile
1917}
1918
1919func (config SetChatPhotoConfig) method() string {
1920	return "setChatPhoto"
1921}
1922
1923func (config SetChatPhotoConfig) files() []RequestFile {
1924	return []RequestFile{{
1925		Name: "photo",
1926		Data: config.File,
1927	}}
1928}
1929
1930// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
1931type DeleteChatPhotoConfig struct {
1932	ChatID          int64
1933	ChannelUsername string
1934}
1935
1936func (config DeleteChatPhotoConfig) method() string {
1937	return "deleteChatPhoto"
1938}
1939
1940func (config DeleteChatPhotoConfig) params() (Params, error) {
1941	params := make(Params)
1942
1943	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1944
1945	return params, nil
1946}
1947
1948// SetChatTitleConfig allows you to set the title of something other than a private chat.
1949type SetChatTitleConfig struct {
1950	ChatID          int64
1951	ChannelUsername string
1952
1953	Title string
1954}
1955
1956func (config SetChatTitleConfig) method() string {
1957	return "setChatTitle"
1958}
1959
1960func (config SetChatTitleConfig) params() (Params, error) {
1961	params := make(Params)
1962
1963	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1964	params["title"] = config.Title
1965
1966	return params, nil
1967}
1968
1969// SetChatDescriptionConfig allows you to set the description of a supergroup or channel.
1970type SetChatDescriptionConfig struct {
1971	ChatID          int64
1972	ChannelUsername string
1973
1974	Description string
1975}
1976
1977func (config SetChatDescriptionConfig) method() string {
1978	return "setChatDescription"
1979}
1980
1981func (config SetChatDescriptionConfig) params() (Params, error) {
1982	params := make(Params)
1983
1984	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1985	params["description"] = config.Description
1986
1987	return params, nil
1988}
1989
1990// GetStickerSetConfig allows you to get the stickers in a set.
1991type GetStickerSetConfig struct {
1992	Name string
1993}
1994
1995func (config GetStickerSetConfig) method() string {
1996	return "getStickerSet"
1997}
1998
1999func (config GetStickerSetConfig) params() (Params, error) {
2000	params := make(Params)
2001
2002	params["name"] = config.Name
2003
2004	return params, nil
2005}
2006
2007// UploadStickerConfig allows you to upload a sticker for use in a set later.
2008type UploadStickerConfig struct {
2009	UserID     int64
2010	PNGSticker RequestFileData
2011}
2012
2013func (config UploadStickerConfig) method() string {
2014	return "uploadStickerFile"
2015}
2016
2017func (config UploadStickerConfig) params() (Params, error) {
2018	params := make(Params)
2019
2020	params.AddNonZero64("user_id", config.UserID)
2021
2022	return params, nil
2023}
2024
2025func (config UploadStickerConfig) files() []RequestFile {
2026	return []RequestFile{{
2027		Name: "png_sticker",
2028		Data: config.PNGSticker,
2029	}}
2030}
2031
2032// NewStickerSetConfig allows creating a new sticker set.
2033//
2034// You must set either PNGSticker or TGSSticker.
2035type NewStickerSetConfig struct {
2036	UserID        int64
2037	Name          string
2038	Title         string
2039	PNGSticker    RequestFileData
2040	TGSSticker    RequestFileData
2041	Emojis        string
2042	ContainsMasks bool
2043	MaskPosition  *MaskPosition
2044}
2045
2046func (config NewStickerSetConfig) method() string {
2047	return "createNewStickerSet"
2048}
2049
2050func (config NewStickerSetConfig) params() (Params, error) {
2051	params := make(Params)
2052
2053	params.AddNonZero64("user_id", config.UserID)
2054	params["name"] = config.Name
2055	params["title"] = config.Title
2056
2057	params["emojis"] = config.Emojis
2058
2059	params.AddBool("contains_masks", config.ContainsMasks)
2060
2061	err := params.AddInterface("mask_position", config.MaskPosition)
2062
2063	return params, err
2064}
2065
2066func (config NewStickerSetConfig) files() []RequestFile {
2067	if config.PNGSticker != nil {
2068		return []RequestFile{{
2069			Name: "png_sticker",
2070			Data: config.PNGSticker,
2071		}}
2072	}
2073
2074	return []RequestFile{{
2075		Name: "tgs_sticker",
2076		Data: config.TGSSticker,
2077	}}
2078}
2079
2080// AddStickerConfig allows you to add a sticker to a set.
2081type AddStickerConfig struct {
2082	UserID       int64
2083	Name         string
2084	PNGSticker   RequestFileData
2085	TGSSticker   RequestFileData
2086	Emojis       string
2087	MaskPosition *MaskPosition
2088}
2089
2090func (config AddStickerConfig) method() string {
2091	return "addStickerToSet"
2092}
2093
2094func (config AddStickerConfig) params() (Params, error) {
2095	params := make(Params)
2096
2097	params.AddNonZero64("user_id", config.UserID)
2098	params["name"] = config.Name
2099	params["emojis"] = config.Emojis
2100
2101	err := params.AddInterface("mask_position", config.MaskPosition)
2102
2103	return params, err
2104}
2105
2106func (config AddStickerConfig) files() []RequestFile {
2107	if config.PNGSticker != nil {
2108		return []RequestFile{{
2109			Name: "png_sticker",
2110			Data: config.PNGSticker,
2111		}}
2112	}
2113
2114	return []RequestFile{{
2115		Name: "tgs_sticker",
2116		Data: config.TGSSticker,
2117	}}
2118
2119}
2120
2121// SetStickerPositionConfig allows you to change the position of a sticker in a set.
2122type SetStickerPositionConfig struct {
2123	Sticker  string
2124	Position int
2125}
2126
2127func (config SetStickerPositionConfig) method() string {
2128	return "setStickerPositionInSet"
2129}
2130
2131func (config SetStickerPositionConfig) params() (Params, error) {
2132	params := make(Params)
2133
2134	params["sticker"] = config.Sticker
2135	params.AddNonZero("position", config.Position)
2136
2137	return params, nil
2138}
2139
2140// DeleteStickerConfig allows you to delete a sticker from a set.
2141type DeleteStickerConfig struct {
2142	Sticker string
2143}
2144
2145func (config DeleteStickerConfig) method() string {
2146	return "deleteStickerFromSet"
2147}
2148
2149func (config DeleteStickerConfig) params() (Params, error) {
2150	params := make(Params)
2151
2152	params["sticker"] = config.Sticker
2153
2154	return params, nil
2155}
2156
2157// SetStickerSetThumbConfig allows you to set the thumbnail for a sticker set.
2158type SetStickerSetThumbConfig struct {
2159	Name   string
2160	UserID int64
2161	Thumb  RequestFileData
2162}
2163
2164func (config SetStickerSetThumbConfig) method() string {
2165	return "setStickerSetThumb"
2166}
2167
2168func (config SetStickerSetThumbConfig) params() (Params, error) {
2169	params := make(Params)
2170
2171	params["name"] = config.Name
2172	params.AddNonZero64("user_id", config.UserID)
2173
2174	return params, nil
2175}
2176
2177func (config SetStickerSetThumbConfig) files() []RequestFile {
2178	return []RequestFile{{
2179		Name: "thumb",
2180		Data: config.Thumb,
2181	}}
2182}
2183
2184// SetChatStickerSetConfig allows you to set the sticker set for a supergroup.
2185type SetChatStickerSetConfig struct {
2186	ChatID             int64
2187	SuperGroupUsername string
2188
2189	StickerSetName string
2190}
2191
2192func (config SetChatStickerSetConfig) method() string {
2193	return "setChatStickerSet"
2194}
2195
2196func (config SetChatStickerSetConfig) params() (Params, error) {
2197	params := make(Params)
2198
2199	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
2200	params["sticker_set_name"] = config.StickerSetName
2201
2202	return params, nil
2203}
2204
2205// DeleteChatStickerSetConfig allows you to remove a supergroup's sticker set.
2206type DeleteChatStickerSetConfig struct {
2207	ChatID             int64
2208	SuperGroupUsername string
2209}
2210
2211func (config DeleteChatStickerSetConfig) method() string {
2212	return "deleteChatStickerSet"
2213}
2214
2215func (config DeleteChatStickerSetConfig) params() (Params, error) {
2216	params := make(Params)
2217
2218	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
2219
2220	return params, nil
2221}
2222
2223// MediaGroupConfig allows you to send a group of media.
2224//
2225// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo).
2226type MediaGroupConfig struct {
2227	ChatID          int64
2228	ChannelUsername string
2229
2230	Media               []interface{}
2231	DisableNotification bool
2232	ReplyToMessageID    int
2233}
2234
2235func (config MediaGroupConfig) method() string {
2236	return "sendMediaGroup"
2237}
2238
2239func (config MediaGroupConfig) params() (Params, error) {
2240	params := make(Params)
2241
2242	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2243	params.AddBool("disable_notification", config.DisableNotification)
2244	params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
2245
2246	err := params.AddInterface("media", prepareInputMediaForParams(config.Media))
2247
2248	return params, err
2249}
2250
2251func (config MediaGroupConfig) files() []RequestFile {
2252	return prepareInputMediaForFiles(config.Media)
2253}
2254
2255// DiceConfig contains information about a sendDice request.
2256type DiceConfig struct {
2257	BaseChat
2258	// Emoji on which the dice throw animation is based.
2259	// Currently, must be one of 🎲, 🎯, 🏀, ⚽, 🎳, or 🎰.
2260	// Dice can have values 1-6 for 🎲, 🎯, and 🎳, values 1-5 for 🏀 and ⚽,
2261	// and values 1-64 for 🎰.
2262	// Defaults to “🎲”
2263	Emoji string
2264}
2265
2266func (config DiceConfig) method() string {
2267	return "sendDice"
2268}
2269
2270func (config DiceConfig) params() (Params, error) {
2271	params, err := config.BaseChat.params()
2272	if err != nil {
2273		return params, err
2274	}
2275
2276	params.AddNonEmpty("emoji", config.Emoji)
2277
2278	return params, err
2279}
2280
2281// GetMyCommandsConfig gets a list of the currently registered commands.
2282type GetMyCommandsConfig struct {
2283	Scope        *BotCommandScope
2284	LanguageCode string
2285}
2286
2287func (config GetMyCommandsConfig) method() string {
2288	return "getMyCommands"
2289}
2290
2291func (config GetMyCommandsConfig) params() (Params, error) {
2292	params := make(Params)
2293
2294	err := params.AddInterface("scope", config.Scope)
2295	params.AddNonEmpty("language_code", config.LanguageCode)
2296
2297	return params, err
2298}
2299
2300// SetMyCommandsConfig sets a list of commands the bot understands.
2301type SetMyCommandsConfig struct {
2302	Commands     []BotCommand
2303	Scope        *BotCommandScope
2304	LanguageCode string
2305}
2306
2307func (config SetMyCommandsConfig) method() string {
2308	return "setMyCommands"
2309}
2310
2311func (config SetMyCommandsConfig) params() (Params, error) {
2312	params := make(Params)
2313
2314	if err := params.AddInterface("commands", config.Commands); err != nil {
2315		return params, err
2316	}
2317	err := params.AddInterface("scope", config.Scope)
2318	params.AddNonEmpty("language_code", config.LanguageCode)
2319
2320	return params, err
2321}
2322
2323type DeleteMyCommandsConfig struct {
2324	Scope        *BotCommandScope
2325	LanguageCode string
2326}
2327
2328func (config DeleteMyCommandsConfig) method() string {
2329	return "deleteMyCommands"
2330}
2331
2332func (config DeleteMyCommandsConfig) params() (Params, error) {
2333	params := make(Params)
2334
2335	err := params.AddInterface("scope", config.Scope)
2336	params.AddNonEmpty("language_code", config.LanguageCode)
2337
2338	return params, err
2339}
2340
2341// SetChatMenuButtonConfig changes the bot's menu button in a private chat,
2342// or the default menu button.
2343type SetChatMenuButtonConfig struct {
2344	ChatID          int64
2345	ChannelUsername string
2346
2347	MenuButton *MenuButton
2348}
2349
2350func (config SetChatMenuButtonConfig) method() string {
2351	return "setChatMenuButton"
2352}
2353
2354func (config SetChatMenuButtonConfig) params() (Params, error) {
2355	params := make(Params)
2356
2357	if err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername); err != nil {
2358		return params, err
2359	}
2360	err := params.AddInterface("menu_button", config.MenuButton)
2361
2362	return params, err
2363}
2364
2365type GetChatMenuButtonConfig struct {
2366	ChatID          int64
2367	ChannelUsername string
2368}
2369
2370func (config GetChatMenuButtonConfig) method() string {
2371	return "getChatMenuButton"
2372}
2373
2374func (config GetChatMenuButtonConfig) params() (Params, error) {
2375	params := make(Params)
2376
2377	err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2378
2379	return params, err
2380}
2381
2382type SetMyDefaultAdministratorRightsConfig struct {
2383	Rights      ChatAdministratorRights
2384	ForChannels bool
2385}
2386
2387func (config SetMyDefaultAdministratorRightsConfig) method() string {
2388	return "setMyDefaultAdministratorRights"
2389}
2390
2391func (config SetMyDefaultAdministratorRightsConfig) params() (Params, error) {
2392	params := make(Params)
2393
2394	err := params.AddInterface("rights", config.Rights)
2395	params.AddBool("for_channels", config.ForChannels)
2396
2397	return params, err
2398}
2399
2400type GetMyDefaultAdministratorRightsConfig struct {
2401	ForChannels bool
2402}
2403
2404func (config GetMyDefaultAdministratorRightsConfig) method() string {
2405	return "getMyDefaultAdministratorRights"
2406}
2407
2408func (config GetMyDefaultAdministratorRightsConfig) params() (Params, error) {
2409	params := make(Params)
2410
2411	params.AddBool("for_channels", config.ForChannels)
2412
2413	return params, nil
2414}
2415
2416// prepareInputMediaParam evaluates a single InputMedia and determines if it
2417// needs to be modified for a successful upload. If it returns nil, then the
2418// value does not need to be included in the params. Otherwise, it will return
2419// the same type as was originally provided.
2420//
2421// The idx is used to calculate the file field name. If you only have a single
2422// file, 0 may be used. It is formatted into "attach://file-%d" for the primary
2423// media and "attach://file-%d-thumb" for thumbnails.
2424//
2425// It is expected to be used in conjunction with prepareInputMediaFile.
2426func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} {
2427	switch m := inputMedia.(type) {
2428	case InputMediaPhoto:
2429		if m.Media.NeedsUpload() {
2430			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2431		}
2432
2433		return m
2434	case InputMediaVideo:
2435		if m.Media.NeedsUpload() {
2436			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2437		}
2438
2439		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2440			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2441		}
2442
2443		return m
2444	case InputMediaAudio:
2445		if m.Media.NeedsUpload() {
2446			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2447		}
2448
2449		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2450			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2451		}
2452
2453		return m
2454	case InputMediaDocument:
2455		if m.Media.NeedsUpload() {
2456			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2457		}
2458
2459		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2460			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2461		}
2462
2463		return m
2464	}
2465
2466	return nil
2467}
2468
2469// prepareInputMediaFile generates an array of RequestFile to provide for
2470// Fileable's files method. It returns an array as a single InputMedia may have
2471// multiple files, for the primary media and a thumbnail.
2472//
2473// The idx parameter is used to generate file field names. It uses the names
2474// "file-%d" for the main file and "file-%d-thumb" for the thumbnail.
2475//
2476// It is expected to be used in conjunction with prepareInputMediaParam.
2477func prepareInputMediaFile(inputMedia interface{}, idx int) []RequestFile {
2478	files := []RequestFile{}
2479
2480	switch m := inputMedia.(type) {
2481	case InputMediaPhoto:
2482		if m.Media.NeedsUpload() {
2483			files = append(files, RequestFile{
2484				Name: fmt.Sprintf("file-%d", idx),
2485				Data: m.Media,
2486			})
2487		}
2488	case InputMediaVideo:
2489		if m.Media.NeedsUpload() {
2490			files = append(files, RequestFile{
2491				Name: fmt.Sprintf("file-%d", idx),
2492				Data: m.Media,
2493			})
2494		}
2495
2496		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2497			files = append(files, RequestFile{
2498				Name: fmt.Sprintf("file-%d", idx),
2499				Data: m.Thumb,
2500			})
2501		}
2502	case InputMediaDocument:
2503		if m.Media.NeedsUpload() {
2504			files = append(files, RequestFile{
2505				Name: fmt.Sprintf("file-%d", idx),
2506				Data: m.Media,
2507			})
2508		}
2509
2510		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2511			files = append(files, RequestFile{
2512				Name: fmt.Sprintf("file-%d", idx),
2513				Data: m.Thumb,
2514			})
2515		}
2516	case InputMediaAudio:
2517		if m.Media.NeedsUpload() {
2518			files = append(files, RequestFile{
2519				Name: fmt.Sprintf("file-%d", idx),
2520				Data: m.Media,
2521			})
2522		}
2523
2524		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2525			files = append(files, RequestFile{
2526				Name: fmt.Sprintf("file-%d", idx),
2527				Data: m.Thumb,
2528			})
2529		}
2530	}
2531
2532	return files
2533}
2534
2535// prepareInputMediaForParams calls prepareInputMediaParam for each item
2536// provided and returns a new array with the correct params for a request.
2537//
2538// It is expected that files will get data from the associated function,
2539// prepareInputMediaForFiles.
2540func prepareInputMediaForParams(inputMedia []interface{}) []interface{} {
2541	newMedia := make([]interface{}, len(inputMedia))
2542	copy(newMedia, inputMedia)
2543
2544	for idx, media := range inputMedia {
2545		if param := prepareInputMediaParam(media, idx); param != nil {
2546			newMedia[idx] = param
2547		}
2548	}
2549
2550	return newMedia
2551}
2552
2553// prepareInputMediaForFiles calls prepareInputMediaFile for each item
2554// provided and returns a new array with the correct files for a request.
2555//
2556// It is expected that params will get data from the associated function,
2557// prepareInputMediaForParams.
2558func prepareInputMediaForFiles(inputMedia []interface{}) []RequestFile {
2559	files := []RequestFile{}
2560
2561	for idx, media := range inputMedia {
2562		if file := prepareInputMediaFile(media, idx); file != nil {
2563			files = append(files, file...)
2564		}
2565	}
2566
2567	return files
2568}