all repos — telegram-bot-api @ 24489300eeddd40eae3ca241f584e921335585ad

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	ReplyToMessageID         int
 270	ReplyMarkup              interface{}
 271	DisableNotification      bool
 272	AllowSendingWithoutReply bool
 273}
 274
 275func (chat *BaseChat) params() (Params, error) {
 276	params := make(Params)
 277
 278	params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername)
 279	params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID)
 280	params.AddBool("disable_notification", chat.DisableNotification)
 281	params.AddBool("allow_sending_without_reply", chat.AllowSendingWithoutReply)
 282
 283	err := params.AddInterface("reply_markup", chat.ReplyMarkup)
 284
 285	return params, err
 286}
 287
 288// BaseFile is a base type for all file config types.
 289type BaseFile struct {
 290	BaseChat
 291	File RequestFileData
 292}
 293
 294func (file BaseFile) params() (Params, error) {
 295	return file.BaseChat.params()
 296}
 297
 298// BaseEdit is base type of all chat edits.
 299type BaseEdit struct {
 300	ChatID          int64
 301	ChannelUsername string
 302	MessageID       int
 303	InlineMessageID string
 304	ReplyMarkup     *InlineKeyboardMarkup
 305}
 306
 307func (edit BaseEdit) params() (Params, error) {
 308	params := make(Params)
 309
 310	if edit.InlineMessageID != "" {
 311		params["inline_message_id"] = edit.InlineMessageID
 312	} else {
 313		params.AddFirstValid("chat_id", edit.ChatID, edit.ChannelUsername)
 314		params.AddNonZero("message_id", edit.MessageID)
 315	}
 316
 317	err := params.AddInterface("reply_markup", edit.ReplyMarkup)
 318
 319	return params, err
 320}
 321
 322// MessageConfig contains information about a SendMessage request.
 323type MessageConfig struct {
 324	BaseChat
 325	Text                  string
 326	ParseMode             string
 327	Entities              []MessageEntity
 328	DisableWebPagePreview bool
 329}
 330
 331func (config MessageConfig) params() (Params, error) {
 332	params, err := config.BaseChat.params()
 333	if err != nil {
 334		return params, err
 335	}
 336
 337	params.AddNonEmpty("text", config.Text)
 338	params.AddBool("disable_web_page_preview", config.DisableWebPagePreview)
 339	params.AddNonEmpty("parse_mode", config.ParseMode)
 340	err = params.AddInterface("entities", config.Entities)
 341
 342	return params, err
 343}
 344
 345func (config MessageConfig) method() string {
 346	return "sendMessage"
 347}
 348
 349// ForwardConfig contains information about a ForwardMessage request.
 350type ForwardConfig struct {
 351	BaseChat
 352	FromChatID          int64 // required
 353	FromChannelUsername string
 354	MessageID           int // required
 355}
 356
 357func (config ForwardConfig) params() (Params, error) {
 358	params, err := config.BaseChat.params()
 359	if err != nil {
 360		return params, err
 361	}
 362
 363	params.AddNonZero64("from_chat_id", config.FromChatID)
 364	params.AddNonZero("message_id", config.MessageID)
 365
 366	return params, nil
 367}
 368
 369func (config ForwardConfig) method() string {
 370	return "forwardMessage"
 371}
 372
 373// CopyMessageConfig contains information about a copyMessage request.
 374type CopyMessageConfig struct {
 375	BaseChat
 376	FromChatID          int64
 377	FromChannelUsername string
 378	MessageID           int
 379	Caption             string
 380	ParseMode           string
 381	CaptionEntities     []MessageEntity
 382}
 383
 384func (config CopyMessageConfig) params() (Params, error) {
 385	params, err := config.BaseChat.params()
 386	if err != nil {
 387		return params, err
 388	}
 389
 390	params.AddFirstValid("from_chat_id", config.FromChatID, config.FromChannelUsername)
 391	params.AddNonZero("message_id", config.MessageID)
 392	params.AddNonEmpty("caption", config.Caption)
 393	params.AddNonEmpty("parse_mode", config.ParseMode)
 394	err = params.AddInterface("caption_entities", config.CaptionEntities)
 395
 396	return params, err
 397}
 398
 399func (config CopyMessageConfig) method() string {
 400	return "copyMessage"
 401}
 402
 403// PhotoConfig contains information about a SendPhoto request.
 404type PhotoConfig struct {
 405	BaseFile
 406	Thumb           RequestFileData
 407	Caption         string
 408	ParseMode       string
 409	CaptionEntities []MessageEntity
 410}
 411
 412func (config PhotoConfig) params() (Params, error) {
 413	params, err := config.BaseFile.params()
 414	if err != nil {
 415		return params, err
 416	}
 417
 418	params.AddNonEmpty("caption", config.Caption)
 419	params.AddNonEmpty("parse_mode", config.ParseMode)
 420	err = params.AddInterface("caption_entities", config.CaptionEntities)
 421
 422	return params, err
 423}
 424
 425func (config PhotoConfig) method() string {
 426	return "sendPhoto"
 427}
 428
 429func (config PhotoConfig) files() []RequestFile {
 430	files := []RequestFile{{
 431		Name: "photo",
 432		Data: config.File,
 433	}}
 434
 435	if config.Thumb != nil {
 436		files = append(files, RequestFile{
 437			Name: "thumb",
 438			Data: config.Thumb,
 439		})
 440	}
 441
 442	return files
 443}
 444
 445// AudioConfig contains information about a SendAudio request.
 446type AudioConfig struct {
 447	BaseFile
 448	Thumb           RequestFileData
 449	Caption         string
 450	ParseMode       string
 451	CaptionEntities []MessageEntity
 452	Duration        int
 453	Performer       string
 454	Title           string
 455}
 456
 457func (config AudioConfig) params() (Params, error) {
 458	params, err := config.BaseChat.params()
 459	if err != nil {
 460		return params, err
 461	}
 462
 463	params.AddNonZero("duration", config.Duration)
 464	params.AddNonEmpty("performer", config.Performer)
 465	params.AddNonEmpty("title", config.Title)
 466	params.AddNonEmpty("caption", config.Caption)
 467	params.AddNonEmpty("parse_mode", config.ParseMode)
 468	err = params.AddInterface("caption_entities", config.CaptionEntities)
 469
 470	return params, err
 471}
 472
 473func (config AudioConfig) method() string {
 474	return "sendAudio"
 475}
 476
 477func (config AudioConfig) files() []RequestFile {
 478	files := []RequestFile{{
 479		Name: "audio",
 480		Data: config.File,
 481	}}
 482
 483	if config.Thumb != nil {
 484		files = append(files, RequestFile{
 485			Name: "thumb",
 486			Data: config.Thumb,
 487		})
 488	}
 489
 490	return files
 491}
 492
 493// DocumentConfig contains information about a SendDocument request.
 494type DocumentConfig struct {
 495	BaseFile
 496	Thumb                       RequestFileData
 497	Caption                     string
 498	ParseMode                   string
 499	CaptionEntities             []MessageEntity
 500	DisableContentTypeDetection bool
 501}
 502
 503func (config DocumentConfig) params() (Params, error) {
 504	params, err := config.BaseFile.params()
 505
 506	params.AddNonEmpty("caption", config.Caption)
 507	params.AddNonEmpty("parse_mode", config.ParseMode)
 508	params.AddBool("disable_content_type_detection", config.DisableContentTypeDetection)
 509
 510	return params, err
 511}
 512
 513func (config DocumentConfig) method() string {
 514	return "sendDocument"
 515}
 516
 517func (config DocumentConfig) files() []RequestFile {
 518	files := []RequestFile{{
 519		Name: "document",
 520		Data: config.File,
 521	}}
 522
 523	if config.Thumb != nil {
 524		files = append(files, RequestFile{
 525			Name: "thumb",
 526			Data: config.Thumb,
 527		})
 528	}
 529
 530	return files
 531}
 532
 533// StickerConfig contains information about a SendSticker request.
 534type StickerConfig struct {
 535	BaseFile
 536}
 537
 538func (config StickerConfig) params() (Params, error) {
 539	return config.BaseChat.params()
 540}
 541
 542func (config StickerConfig) method() string {
 543	return "sendSticker"
 544}
 545
 546func (config StickerConfig) files() []RequestFile {
 547	return []RequestFile{{
 548		Name: "sticker",
 549		Data: config.File,
 550	}}
 551}
 552
 553// VideoConfig contains information about a SendVideo request.
 554type VideoConfig struct {
 555	BaseFile
 556	Thumb             RequestFileData
 557	Duration          int
 558	Caption           string
 559	ParseMode         string
 560	CaptionEntities   []MessageEntity
 561	SupportsStreaming bool
 562}
 563
 564func (config VideoConfig) params() (Params, error) {
 565	params, err := config.BaseChat.params()
 566	if err != nil {
 567		return params, err
 568	}
 569
 570	params.AddNonZero("duration", config.Duration)
 571	params.AddNonEmpty("caption", config.Caption)
 572	params.AddNonEmpty("parse_mode", config.ParseMode)
 573	params.AddBool("supports_streaming", config.SupportsStreaming)
 574	err = params.AddInterface("caption_entities", config.CaptionEntities)
 575
 576	return params, err
 577}
 578
 579func (config VideoConfig) method() string {
 580	return "sendVideo"
 581}
 582
 583func (config VideoConfig) files() []RequestFile {
 584	files := []RequestFile{{
 585		Name: "video",
 586		Data: config.File,
 587	}}
 588
 589	if config.Thumb != nil {
 590		files = append(files, RequestFile{
 591			Name: "thumb",
 592			Data: config.Thumb,
 593		})
 594	}
 595
 596	return files
 597}
 598
 599// AnimationConfig contains information about a SendAnimation request.
 600type AnimationConfig struct {
 601	BaseFile
 602	Duration        int
 603	Thumb           RequestFileData
 604	Caption         string
 605	ParseMode       string
 606	CaptionEntities []MessageEntity
 607}
 608
 609func (config AnimationConfig) params() (Params, error) {
 610	params, err := config.BaseChat.params()
 611	if err != nil {
 612		return params, err
 613	}
 614
 615	params.AddNonZero("duration", config.Duration)
 616	params.AddNonEmpty("caption", config.Caption)
 617	params.AddNonEmpty("parse_mode", config.ParseMode)
 618	err = params.AddInterface("caption_entities", config.CaptionEntities)
 619
 620	return params, err
 621}
 622
 623func (config AnimationConfig) method() string {
 624	return "sendAnimation"
 625}
 626
 627func (config AnimationConfig) files() []RequestFile {
 628	files := []RequestFile{{
 629		Name: "animation",
 630		Data: config.File,
 631	}}
 632
 633	if config.Thumb != nil {
 634		files = append(files, RequestFile{
 635			Name: "thumb",
 636			Data: config.Thumb,
 637		})
 638	}
 639
 640	return files
 641}
 642
 643// VideoNoteConfig contains information about a SendVideoNote request.
 644type VideoNoteConfig struct {
 645	BaseFile
 646	Thumb    RequestFileData
 647	Duration int
 648	Length   int
 649}
 650
 651func (config VideoNoteConfig) params() (Params, error) {
 652	params, err := config.BaseChat.params()
 653
 654	params.AddNonZero("duration", config.Duration)
 655	params.AddNonZero("length", config.Length)
 656
 657	return params, err
 658}
 659
 660func (config VideoNoteConfig) method() string {
 661	return "sendVideoNote"
 662}
 663
 664func (config VideoNoteConfig) files() []RequestFile {
 665	files := []RequestFile{{
 666		Name: "video_note",
 667		Data: config.File,
 668	}}
 669
 670	if config.Thumb != nil {
 671		files = append(files, RequestFile{
 672			Name: "thumb",
 673			Data: config.Thumb,
 674		})
 675	}
 676
 677	return files
 678}
 679
 680// VoiceConfig contains information about a SendVoice request.
 681type VoiceConfig struct {
 682	BaseFile
 683	Thumb           RequestFileData
 684	Caption         string
 685	ParseMode       string
 686	CaptionEntities []MessageEntity
 687	Duration        int
 688}
 689
 690func (config VoiceConfig) params() (Params, error) {
 691	params, err := config.BaseChat.params()
 692	if err != nil {
 693		return params, err
 694	}
 695
 696	params.AddNonZero("duration", config.Duration)
 697	params.AddNonEmpty("caption", config.Caption)
 698	params.AddNonEmpty("parse_mode", config.ParseMode)
 699	err = params.AddInterface("caption_entities", config.CaptionEntities)
 700
 701	return params, err
 702}
 703
 704func (config VoiceConfig) method() string {
 705	return "sendVoice"
 706}
 707
 708func (config VoiceConfig) files() []RequestFile {
 709	files := []RequestFile{{
 710		Name: "voice",
 711		Data: config.File,
 712	}}
 713
 714	if config.Thumb != nil {
 715		files = append(files, RequestFile{
 716			Name: "thumb",
 717			Data: config.Thumb,
 718		})
 719	}
 720
 721	return files
 722}
 723
 724// LocationConfig contains information about a SendLocation request.
 725type LocationConfig struct {
 726	BaseChat
 727	Latitude             float64 // required
 728	Longitude            float64 // required
 729	HorizontalAccuracy   float64 // optional
 730	LivePeriod           int     // optional
 731	Heading              int     // optional
 732	ProximityAlertRadius int     // optional
 733}
 734
 735func (config LocationConfig) params() (Params, error) {
 736	params, err := config.BaseChat.params()
 737
 738	params.AddNonZeroFloat("latitude", config.Latitude)
 739	params.AddNonZeroFloat("longitude", config.Longitude)
 740	params.AddNonZeroFloat("horizontal_accuracy", config.HorizontalAccuracy)
 741	params.AddNonZero("live_period", config.LivePeriod)
 742	params.AddNonZero("heading", config.Heading)
 743	params.AddNonZero("proximity_alert_radius", config.ProximityAlertRadius)
 744
 745	return params, err
 746}
 747
 748func (config LocationConfig) method() string {
 749	return "sendLocation"
 750}
 751
 752// EditMessageLiveLocationConfig allows you to update a live location.
 753type EditMessageLiveLocationConfig struct {
 754	BaseEdit
 755	Latitude             float64 // required
 756	Longitude            float64 // required
 757	HorizontalAccuracy   float64 // optional
 758	Heading              int     // optional
 759	ProximityAlertRadius int     // optional
 760}
 761
 762func (config EditMessageLiveLocationConfig) params() (Params, error) {
 763	params, err := config.BaseEdit.params()
 764
 765	params.AddNonZeroFloat("latitude", config.Latitude)
 766	params.AddNonZeroFloat("longitude", config.Longitude)
 767	params.AddNonZeroFloat("horizontal_accuracy", config.HorizontalAccuracy)
 768	params.AddNonZero("heading", config.Heading)
 769	params.AddNonZero("proximity_alert_radius", config.ProximityAlertRadius)
 770
 771	return params, err
 772}
 773
 774func (config EditMessageLiveLocationConfig) method() string {
 775	return "editMessageLiveLocation"
 776}
 777
 778// StopMessageLiveLocationConfig stops updating a live location.
 779type StopMessageLiveLocationConfig struct {
 780	BaseEdit
 781}
 782
 783func (config StopMessageLiveLocationConfig) params() (Params, error) {
 784	return config.BaseEdit.params()
 785}
 786
 787func (config StopMessageLiveLocationConfig) method() string {
 788	return "stopMessageLiveLocation"
 789}
 790
 791// VenueConfig contains information about a SendVenue request.
 792type VenueConfig struct {
 793	BaseChat
 794	Latitude        float64 // required
 795	Longitude       float64 // required
 796	Title           string  // required
 797	Address         string  // required
 798	FoursquareID    string
 799	FoursquareType  string
 800	GooglePlaceID   string
 801	GooglePlaceType string
 802}
 803
 804func (config VenueConfig) params() (Params, error) {
 805	params, err := config.BaseChat.params()
 806
 807	params.AddNonZeroFloat("latitude", config.Latitude)
 808	params.AddNonZeroFloat("longitude", config.Longitude)
 809	params["title"] = config.Title
 810	params["address"] = config.Address
 811	params.AddNonEmpty("foursquare_id", config.FoursquareID)
 812	params.AddNonEmpty("foursquare_type", config.FoursquareType)
 813	params.AddNonEmpty("google_place_id", config.GooglePlaceID)
 814	params.AddNonEmpty("google_place_type", config.GooglePlaceType)
 815
 816	return params, err
 817}
 818
 819func (config VenueConfig) method() string {
 820	return "sendVenue"
 821}
 822
 823// ContactConfig allows you to send a contact.
 824type ContactConfig struct {
 825	BaseChat
 826	PhoneNumber string
 827	FirstName   string
 828	LastName    string
 829	VCard       string
 830}
 831
 832func (config ContactConfig) params() (Params, error) {
 833	params, err := config.BaseChat.params()
 834
 835	params["phone_number"] = config.PhoneNumber
 836	params["first_name"] = config.FirstName
 837
 838	params.AddNonEmpty("last_name", config.LastName)
 839	params.AddNonEmpty("vcard", config.VCard)
 840
 841	return params, err
 842}
 843
 844func (config ContactConfig) method() string {
 845	return "sendContact"
 846}
 847
 848// SendPollConfig allows you to send a poll.
 849type SendPollConfig struct {
 850	BaseChat
 851	Question              string
 852	Options               []string
 853	IsAnonymous           bool
 854	Type                  string
 855	AllowsMultipleAnswers bool
 856	CorrectOptionID       int64
 857	Explanation           string
 858	ExplanationParseMode  string
 859	ExplanationEntities   []MessageEntity
 860	OpenPeriod            int
 861	CloseDate             int
 862	IsClosed              bool
 863}
 864
 865func (config SendPollConfig) params() (Params, error) {
 866	params, err := config.BaseChat.params()
 867	if err != nil {
 868		return params, err
 869	}
 870
 871	params["question"] = config.Question
 872	if err = params.AddInterface("options", config.Options); err != nil {
 873		return params, err
 874	}
 875	params["is_anonymous"] = strconv.FormatBool(config.IsAnonymous)
 876	params.AddNonEmpty("type", config.Type)
 877	params["allows_multiple_answers"] = strconv.FormatBool(config.AllowsMultipleAnswers)
 878	params["correct_option_id"] = strconv.FormatInt(config.CorrectOptionID, 10)
 879	params.AddBool("is_closed", config.IsClosed)
 880	params.AddNonEmpty("explanation", config.Explanation)
 881	params.AddNonEmpty("explanation_parse_mode", config.ExplanationParseMode)
 882	params.AddNonZero("open_period", config.OpenPeriod)
 883	params.AddNonZero("close_date", config.CloseDate)
 884	err = params.AddInterface("explanation_entities", config.ExplanationEntities)
 885
 886	return params, err
 887}
 888
 889func (SendPollConfig) method() string {
 890	return "sendPoll"
 891}
 892
 893// GameConfig allows you to send a game.
 894type GameConfig struct {
 895	BaseChat
 896	GameShortName string
 897}
 898
 899func (config GameConfig) params() (Params, error) {
 900	params, err := config.BaseChat.params()
 901
 902	params["game_short_name"] = config.GameShortName
 903
 904	return params, err
 905}
 906
 907func (config GameConfig) method() string {
 908	return "sendGame"
 909}
 910
 911// SetGameScoreConfig allows you to update the game score in a chat.
 912type SetGameScoreConfig struct {
 913	UserID             int64
 914	Score              int
 915	Force              bool
 916	DisableEditMessage bool
 917	ChatID             int64
 918	ChannelUsername    string
 919	MessageID          int
 920	InlineMessageID    string
 921}
 922
 923func (config SetGameScoreConfig) params() (Params, error) {
 924	params := make(Params)
 925
 926	params.AddNonZero64("user_id", config.UserID)
 927	params.AddNonZero("scrore", config.Score)
 928	params.AddBool("disable_edit_message", config.DisableEditMessage)
 929
 930	if config.InlineMessageID != "" {
 931		params["inline_message_id"] = config.InlineMessageID
 932	} else {
 933		params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
 934		params.AddNonZero("message_id", config.MessageID)
 935	}
 936
 937	return params, nil
 938}
 939
 940func (config SetGameScoreConfig) method() string {
 941	return "setGameScore"
 942}
 943
 944// GetGameHighScoresConfig allows you to fetch the high scores for a game.
 945type GetGameHighScoresConfig struct {
 946	UserID          int64
 947	ChatID          int64
 948	ChannelUsername string
 949	MessageID       int
 950	InlineMessageID string
 951}
 952
 953func (config GetGameHighScoresConfig) params() (Params, error) {
 954	params := make(Params)
 955
 956	params.AddNonZero64("user_id", config.UserID)
 957
 958	if config.InlineMessageID != "" {
 959		params["inline_message_id"] = config.InlineMessageID
 960	} else {
 961		params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
 962		params.AddNonZero("message_id", config.MessageID)
 963	}
 964
 965	return params, nil
 966}
 967
 968func (config GetGameHighScoresConfig) method() string {
 969	return "getGameHighScores"
 970}
 971
 972// ChatActionConfig contains information about a SendChatAction request.
 973type ChatActionConfig struct {
 974	BaseChat
 975	Action string // required
 976}
 977
 978func (config ChatActionConfig) params() (Params, error) {
 979	params, err := config.BaseChat.params()
 980
 981	params["action"] = config.Action
 982
 983	return params, err
 984}
 985
 986func (config ChatActionConfig) method() string {
 987	return "sendChatAction"
 988}
 989
 990// EditMessageTextConfig allows you to modify the text in a message.
 991type EditMessageTextConfig struct {
 992	BaseEdit
 993	Text                  string
 994	ParseMode             string
 995	Entities              []MessageEntity
 996	DisableWebPagePreview bool
 997}
 998
 999func (config EditMessageTextConfig) params() (Params, error) {
1000	params, err := config.BaseEdit.params()
1001	if err != nil {
1002		return params, err
1003	}
1004
1005	params["text"] = config.Text
1006	params.AddNonEmpty("parse_mode", config.ParseMode)
1007	params.AddBool("disable_web_page_preview", config.DisableWebPagePreview)
1008	err = params.AddInterface("entities", config.Entities)
1009
1010	return params, err
1011}
1012
1013func (config EditMessageTextConfig) method() string {
1014	return "editMessageText"
1015}
1016
1017// EditMessageCaptionConfig allows you to modify the caption of a message.
1018type EditMessageCaptionConfig struct {
1019	BaseEdit
1020	Caption         string
1021	ParseMode       string
1022	CaptionEntities []MessageEntity
1023}
1024
1025func (config EditMessageCaptionConfig) params() (Params, error) {
1026	params, err := config.BaseEdit.params()
1027	if err != nil {
1028		return params, err
1029	}
1030
1031	params["caption"] = config.Caption
1032	params.AddNonEmpty("parse_mode", config.ParseMode)
1033	err = params.AddInterface("caption_entities", config.CaptionEntities)
1034
1035	return params, err
1036}
1037
1038func (config EditMessageCaptionConfig) method() string {
1039	return "editMessageCaption"
1040}
1041
1042// EditMessageMediaConfig allows you to make an editMessageMedia request.
1043type EditMessageMediaConfig struct {
1044	BaseEdit
1045
1046	Media interface{}
1047}
1048
1049func (EditMessageMediaConfig) method() string {
1050	return "editMessageMedia"
1051}
1052
1053func (config EditMessageMediaConfig) params() (Params, error) {
1054	params, err := config.BaseEdit.params()
1055	if err != nil {
1056		return params, err
1057	}
1058
1059	err = params.AddInterface("media", prepareInputMediaParam(config.Media, 0))
1060
1061	return params, err
1062}
1063
1064func (config EditMessageMediaConfig) files() []RequestFile {
1065	return prepareInputMediaFile(config.Media, 0)
1066}
1067
1068// EditMessageReplyMarkupConfig allows you to modify the reply markup
1069// of a message.
1070type EditMessageReplyMarkupConfig struct {
1071	BaseEdit
1072}
1073
1074func (config EditMessageReplyMarkupConfig) params() (Params, error) {
1075	return config.BaseEdit.params()
1076}
1077
1078func (config EditMessageReplyMarkupConfig) method() string {
1079	return "editMessageReplyMarkup"
1080}
1081
1082// StopPollConfig allows you to stop a poll sent by the bot.
1083type StopPollConfig struct {
1084	BaseEdit
1085}
1086
1087func (config StopPollConfig) params() (Params, error) {
1088	return config.BaseEdit.params()
1089}
1090
1091func (StopPollConfig) method() string {
1092	return "stopPoll"
1093}
1094
1095// UserProfilePhotosConfig contains information about a
1096// GetUserProfilePhotos request.
1097type UserProfilePhotosConfig struct {
1098	UserID int64
1099	Offset int
1100	Limit  int
1101}
1102
1103func (UserProfilePhotosConfig) method() string {
1104	return "getUserProfilePhotos"
1105}
1106
1107func (config UserProfilePhotosConfig) params() (Params, error) {
1108	params := make(Params)
1109
1110	params.AddNonZero64("user_id", config.UserID)
1111	params.AddNonZero("offset", config.Offset)
1112	params.AddNonZero("limit", config.Limit)
1113
1114	return params, nil
1115}
1116
1117// FileConfig has information about a file hosted on Telegram.
1118type FileConfig struct {
1119	FileID string
1120}
1121
1122func (FileConfig) method() string {
1123	return "getFile"
1124}
1125
1126func (config FileConfig) params() (Params, error) {
1127	params := make(Params)
1128
1129	params["file_id"] = config.FileID
1130
1131	return params, nil
1132}
1133
1134// UpdateConfig contains information about a GetUpdates request.
1135type UpdateConfig struct {
1136	Offset         int
1137	Limit          int
1138	Timeout        int
1139	AllowedUpdates []string
1140}
1141
1142func (UpdateConfig) method() string {
1143	return "getUpdates"
1144}
1145
1146func (config UpdateConfig) params() (Params, error) {
1147	params := make(Params)
1148
1149	params.AddNonZero("offset", config.Offset)
1150	params.AddNonZero("limit", config.Limit)
1151	params.AddNonZero("timeout", config.Timeout)
1152	params.AddInterface("allowed_updates", config.AllowedUpdates)
1153
1154	return params, nil
1155}
1156
1157// WebhookConfig contains information about a SetWebhook request.
1158type WebhookConfig struct {
1159	URL                *url.URL
1160	Certificate        RequestFileData
1161	IPAddress          string
1162	MaxConnections     int
1163	AllowedUpdates     []string
1164	DropPendingUpdates bool
1165}
1166
1167func (config WebhookConfig) method() string {
1168	return "setWebhook"
1169}
1170
1171func (config WebhookConfig) params() (Params, error) {
1172	params := make(Params)
1173
1174	if config.URL != nil {
1175		params["url"] = config.URL.String()
1176	}
1177
1178	params.AddNonEmpty("ip_address", config.IPAddress)
1179	params.AddNonZero("max_connections", config.MaxConnections)
1180	err := params.AddInterface("allowed_updates", config.AllowedUpdates)
1181	params.AddBool("drop_pending_updates", config.DropPendingUpdates)
1182
1183	return params, err
1184}
1185
1186func (config WebhookConfig) files() []RequestFile {
1187	if config.Certificate != nil {
1188		return []RequestFile{{
1189			Name: "certificate",
1190			Data: config.Certificate,
1191		}}
1192	}
1193
1194	return nil
1195}
1196
1197// DeleteWebhookConfig is a helper to delete a webhook.
1198type DeleteWebhookConfig struct {
1199	DropPendingUpdates bool
1200}
1201
1202func (config DeleteWebhookConfig) method() string {
1203	return "deleteWebhook"
1204}
1205
1206func (config DeleteWebhookConfig) params() (Params, error) {
1207	params := make(Params)
1208
1209	params.AddBool("drop_pending_updates", config.DropPendingUpdates)
1210
1211	return params, nil
1212}
1213
1214// InlineConfig contains information on making an InlineQuery response.
1215type InlineConfig struct {
1216	InlineQueryID     string        `json:"inline_query_id"`
1217	Results           []interface{} `json:"results"`
1218	CacheTime         int           `json:"cache_time"`
1219	IsPersonal        bool          `json:"is_personal"`
1220	NextOffset        string        `json:"next_offset"`
1221	SwitchPMText      string        `json:"switch_pm_text"`
1222	SwitchPMParameter string        `json:"switch_pm_parameter"`
1223}
1224
1225func (config InlineConfig) method() string {
1226	return "answerInlineQuery"
1227}
1228
1229func (config InlineConfig) params() (Params, error) {
1230	params := make(Params)
1231
1232	params["inline_query_id"] = config.InlineQueryID
1233	params.AddNonZero("cache_time", config.CacheTime)
1234	params.AddBool("is_personal", config.IsPersonal)
1235	params.AddNonEmpty("next_offset", config.NextOffset)
1236	params.AddNonEmpty("switch_pm_text", config.SwitchPMText)
1237	params.AddNonEmpty("switch_pm_parameter", config.SwitchPMParameter)
1238	err := params.AddInterface("results", config.Results)
1239
1240	return params, err
1241}
1242
1243// CallbackConfig contains information on making a CallbackQuery response.
1244type CallbackConfig struct {
1245	CallbackQueryID string `json:"callback_query_id"`
1246	Text            string `json:"text"`
1247	ShowAlert       bool   `json:"show_alert"`
1248	URL             string `json:"url"`
1249	CacheTime       int    `json:"cache_time"`
1250}
1251
1252func (config CallbackConfig) method() string {
1253	return "answerCallbackQuery"
1254}
1255
1256func (config CallbackConfig) params() (Params, error) {
1257	params := make(Params)
1258
1259	params["callback_query_id"] = config.CallbackQueryID
1260	params.AddNonEmpty("text", config.Text)
1261	params.AddBool("show_alert", config.ShowAlert)
1262	params.AddNonEmpty("url", config.URL)
1263	params.AddNonZero("cache_time", config.CacheTime)
1264
1265	return params, nil
1266}
1267
1268// ChatMemberConfig contains information about a user in a chat for use
1269// with administrative functions such as kicking or unbanning a user.
1270type ChatMemberConfig struct {
1271	ChatID             int64
1272	SuperGroupUsername string
1273	ChannelUsername    string
1274	UserID             int64
1275}
1276
1277// UnbanChatMemberConfig allows you to unban a user.
1278type UnbanChatMemberConfig struct {
1279	ChatMemberConfig
1280	OnlyIfBanned bool
1281}
1282
1283func (config UnbanChatMemberConfig) method() string {
1284	return "unbanChatMember"
1285}
1286
1287func (config UnbanChatMemberConfig) params() (Params, error) {
1288	params := make(Params)
1289
1290	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1291	params.AddNonZero64("user_id", config.UserID)
1292	params.AddBool("only_if_banned", config.OnlyIfBanned)
1293
1294	return params, nil
1295}
1296
1297// KickChatMemberConfig contains extra fields to kick user
1298type KickChatMemberConfig struct {
1299	ChatMemberConfig
1300	UntilDate      int64
1301	RevokeMessages bool
1302}
1303
1304func (config KickChatMemberConfig) method() string {
1305	return "kickChatMember"
1306}
1307
1308func (config KickChatMemberConfig) params() (Params, error) {
1309	params := make(Params)
1310
1311	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1312	params.AddNonZero64("user_id", config.UserID)
1313	params.AddNonZero64("until_date", config.UntilDate)
1314	params.AddBool("revoke_messages", config.RevokeMessages)
1315
1316	return params, nil
1317}
1318
1319// RestrictChatMemberConfig contains fields to restrict members of chat
1320type RestrictChatMemberConfig struct {
1321	ChatMemberConfig
1322	UntilDate   int64
1323	Permissions *ChatPermissions
1324}
1325
1326func (config RestrictChatMemberConfig) method() string {
1327	return "restrictChatMember"
1328}
1329
1330func (config RestrictChatMemberConfig) params() (Params, error) {
1331	params := make(Params)
1332
1333	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1334	params.AddNonZero64("user_id", config.UserID)
1335
1336	err := params.AddInterface("permissions", config.Permissions)
1337	params.AddNonZero64("until_date", config.UntilDate)
1338
1339	return params, err
1340}
1341
1342// PromoteChatMemberConfig contains fields to promote members of chat
1343type PromoteChatMemberConfig struct {
1344	ChatMemberConfig
1345	IsAnonymous         bool
1346	CanManageChat       bool
1347	CanChangeInfo       bool
1348	CanPostMessages     bool
1349	CanEditMessages     bool
1350	CanDeleteMessages   bool
1351	CanManageVoiceChats bool
1352	CanInviteUsers      bool
1353	CanRestrictMembers  bool
1354	CanPinMessages      bool
1355	CanPromoteMembers   bool
1356}
1357
1358func (config PromoteChatMemberConfig) method() string {
1359	return "promoteChatMember"
1360}
1361
1362func (config PromoteChatMemberConfig) 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	params.AddBool("is_anonymous", config.IsAnonymous)
1369	params.AddBool("can_manage_chat", config.CanManageChat)
1370	params.AddBool("can_change_info", config.CanChangeInfo)
1371	params.AddBool("can_post_messages", config.CanPostMessages)
1372	params.AddBool("can_edit_messages", config.CanEditMessages)
1373	params.AddBool("can_delete_messages", config.CanDeleteMessages)
1374	params.AddBool("can_manage_voice_chats", config.CanManageVoiceChats)
1375	params.AddBool("can_invite_users", config.CanInviteUsers)
1376	params.AddBool("can_restrict_members", config.CanRestrictMembers)
1377	params.AddBool("can_pin_messages", config.CanPinMessages)
1378	params.AddBool("can_promote_members", config.CanPromoteMembers)
1379
1380	return params, nil
1381}
1382
1383// SetChatAdministratorCustomTitle sets the title of an administrative user
1384// promoted by the bot for a chat.
1385type SetChatAdministratorCustomTitle struct {
1386	ChatMemberConfig
1387	CustomTitle string
1388}
1389
1390func (SetChatAdministratorCustomTitle) method() string {
1391	return "setChatAdministratorCustomTitle"
1392}
1393
1394func (config SetChatAdministratorCustomTitle) 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	params.AddNonEmpty("custom_title", config.CustomTitle)
1400
1401	return params, nil
1402}
1403
1404// ChatConfig contains information about getting information on a chat.
1405type ChatConfig struct {
1406	ChatID             int64
1407	SuperGroupUsername string
1408}
1409
1410func (config ChatConfig) params() (Params, error) {
1411	params := make(Params)
1412
1413	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1414
1415	return params, nil
1416}
1417
1418// ChatInfoConfig contains information about getting chat information.
1419type ChatInfoConfig struct {
1420	ChatConfig
1421}
1422
1423func (ChatInfoConfig) method() string {
1424	return "getChat"
1425}
1426
1427// ChatMemberCountConfig contains information about getting the number of users in a chat.
1428type ChatMemberCountConfig struct {
1429	ChatConfig
1430}
1431
1432func (ChatMemberCountConfig) method() string {
1433	return "getChatMembersCount"
1434}
1435
1436// ChatAdministratorsConfig contains information about getting chat administrators.
1437type ChatAdministratorsConfig struct {
1438	ChatConfig
1439}
1440
1441func (ChatAdministratorsConfig) method() string {
1442	return "getChatAdministrators"
1443}
1444
1445// SetChatPermissionsConfig allows you to set default permissions for the
1446// members in a group. The bot must be an administrator and have rights to
1447// restrict members.
1448type SetChatPermissionsConfig struct {
1449	ChatConfig
1450	Permissions *ChatPermissions
1451}
1452
1453func (SetChatPermissionsConfig) method() string {
1454	return "setChatPermissions"
1455}
1456
1457func (config SetChatPermissionsConfig) params() (Params, error) {
1458	params := make(Params)
1459
1460	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1461	err := params.AddInterface("permissions", config.Permissions)
1462
1463	return params, err
1464}
1465
1466// ChatInviteLinkConfig contains information about getting a chat link.
1467//
1468// Note that generating a new link will revoke any previous links.
1469type ChatInviteLinkConfig struct {
1470	ChatConfig
1471}
1472
1473func (ChatInviteLinkConfig) method() string {
1474	return "exportChatInviteLink"
1475}
1476
1477func (config ChatInviteLinkConfig) params() (Params, error) {
1478	params := make(Params)
1479
1480	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1481
1482	return params, nil
1483}
1484
1485// CreateChatInviteLinkConfig allows you to create an additional invite link for
1486// a chat. The bot must be an administrator in the chat for this to work and
1487// must have the appropriate admin rights. The link can be revoked using the
1488// RevokeChatInviteLinkConfig.
1489type CreateChatInviteLinkConfig struct {
1490	ChatConfig
1491	Name               string
1492	ExpireDate         int
1493	MemberLimit        int
1494	CreatesJoinRequest bool
1495}
1496
1497func (CreateChatInviteLinkConfig) method() string {
1498	return "createChatInviteLink"
1499}
1500
1501func (config CreateChatInviteLinkConfig) params() (Params, error) {
1502	params := make(Params)
1503
1504	params.AddNonEmpty("name", config.Name)
1505	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1506	params.AddNonZero("expire_date", config.ExpireDate)
1507	params.AddNonZero("member_limit", config.MemberLimit)
1508	params.AddBool("creates_join_request", config.CreatesJoinRequest)
1509
1510	return params, nil
1511}
1512
1513// EditChatInviteLinkConfig allows you to edit a non-primary invite link created
1514// by the bot. The bot must be an administrator in the chat for this to work and
1515// must have the appropriate admin rights.
1516type EditChatInviteLinkConfig struct {
1517	ChatConfig
1518	InviteLink         string
1519	Name               string
1520	ExpireDate         int
1521	MemberLimit        int
1522	CreatesJoinRequest bool
1523}
1524
1525func (EditChatInviteLinkConfig) method() string {
1526	return "editChatInviteLink"
1527}
1528
1529func (config EditChatInviteLinkConfig) params() (Params, error) {
1530	params := make(Params)
1531
1532	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1533	params.AddNonEmpty("name", config.Name)
1534	params["invite_link"] = config.InviteLink
1535	params.AddNonZero("expire_date", config.ExpireDate)
1536	params.AddNonZero("member_limit", config.MemberLimit)
1537	params.AddBool("creates_join_request", config.CreatesJoinRequest)
1538
1539	return params, nil
1540}
1541
1542// RevokeChatInviteLinkConfig allows you to revoke an invite link created by the
1543// bot. If the primary link is revoked, a new link is automatically generated.
1544// The bot must be an administrator in the chat for this to work and must have
1545// the appropriate admin rights.
1546type RevokeChatInviteLinkConfig struct {
1547	ChatConfig
1548	InviteLink string
1549}
1550
1551func (RevokeChatInviteLinkConfig) method() string {
1552	return "revokeChatInviteLink"
1553}
1554
1555func (config RevokeChatInviteLinkConfig) params() (Params, error) {
1556	params := make(Params)
1557
1558	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1559	params["invite_link"] = config.InviteLink
1560
1561	return params, nil
1562}
1563
1564// ApproveChatJoinRequestConfig allows you to approve a chat join request.
1565type ApproveChatJoinRequestConfig struct {
1566	ChatConfig
1567	UserID int64
1568}
1569
1570func (ApproveChatJoinRequestConfig) method() string {
1571	return "approveChatJoinRequest"
1572}
1573
1574func (config ApproveChatJoinRequestConfig) params() (Params, error) {
1575	params := make(Params)
1576
1577	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1578	params.AddNonZero("user_id", int(config.UserID))
1579
1580	return params, nil
1581}
1582
1583// DeclineChatJoinRequest allows you to decline a chat join request.
1584type DeclineChatJoinRequest struct {
1585	ChatConfig
1586	UserID int64
1587}
1588
1589func (DeclineChatJoinRequest) method() string {
1590	return "declineChatJoinRequest"
1591}
1592
1593func (config DeclineChatJoinRequest) params() (Params, error) {
1594	params := make(Params)
1595
1596	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1597	params.AddNonZero("user_id", int(config.UserID))
1598
1599	return params, nil
1600}
1601
1602// LeaveChatConfig allows you to leave a chat.
1603type LeaveChatConfig struct {
1604	ChatID          int64
1605	ChannelUsername string
1606}
1607
1608func (config LeaveChatConfig) method() string {
1609	return "leaveChat"
1610}
1611
1612func (config LeaveChatConfig) params() (Params, error) {
1613	params := make(Params)
1614
1615	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1616
1617	return params, nil
1618}
1619
1620// ChatConfigWithUser contains information about a chat and a user.
1621type ChatConfigWithUser struct {
1622	ChatID             int64
1623	SuperGroupUsername string
1624	UserID             int64
1625}
1626
1627func (config ChatConfigWithUser) params() (Params, error) {
1628	params := make(Params)
1629
1630	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1631	params.AddNonZero64("user_id", config.UserID)
1632
1633	return params, nil
1634}
1635
1636// GetChatMemberConfig is information about getting a specific member in a chat.
1637type GetChatMemberConfig struct {
1638	ChatConfigWithUser
1639}
1640
1641func (GetChatMemberConfig) method() string {
1642	return "getChatMember"
1643}
1644
1645// InvoiceConfig contains information for sendInvoice request.
1646type InvoiceConfig struct {
1647	BaseChat
1648	Title                     string         // required
1649	Description               string         // required
1650	Payload                   string         // required
1651	ProviderToken             string         // required
1652	Currency                  string         // required
1653	Prices                    []LabeledPrice // required
1654	MaxTipAmount              int
1655	SuggestedTipAmounts       []int
1656	StartParameter            string
1657	ProviderData              string
1658	PhotoURL                  string
1659	PhotoSize                 int
1660	PhotoWidth                int
1661	PhotoHeight               int
1662	NeedName                  bool
1663	NeedPhoneNumber           bool
1664	NeedEmail                 bool
1665	NeedShippingAddress       bool
1666	SendPhoneNumberToProvider bool
1667	SendEmailToProvider       bool
1668	IsFlexible                bool
1669}
1670
1671func (config InvoiceConfig) params() (Params, error) {
1672	params, err := config.BaseChat.params()
1673	if err != nil {
1674		return params, err
1675	}
1676
1677	params["title"] = config.Title
1678	params["description"] = config.Description
1679	params["payload"] = config.Payload
1680	params["provider_token"] = config.ProviderToken
1681	params["currency"] = config.Currency
1682	if err = params.AddInterface("prices", config.Prices); err != nil {
1683		return params, err
1684	}
1685
1686	params.AddNonZero("max_tip_amount", config.MaxTipAmount)
1687	err = params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts)
1688	params.AddNonEmpty("start_parameter", config.StartParameter)
1689	params.AddNonEmpty("provider_data", config.ProviderData)
1690	params.AddNonEmpty("photo_url", config.PhotoURL)
1691	params.AddNonZero("photo_size", config.PhotoSize)
1692	params.AddNonZero("photo_width", config.PhotoWidth)
1693	params.AddNonZero("photo_height", config.PhotoHeight)
1694	params.AddBool("need_name", config.NeedName)
1695	params.AddBool("need_phone_number", config.NeedPhoneNumber)
1696	params.AddBool("need_email", config.NeedEmail)
1697	params.AddBool("need_shipping_address", config.NeedShippingAddress)
1698	params.AddBool("is_flexible", config.IsFlexible)
1699	params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider)
1700	params.AddBool("send_email_to_provider", config.SendEmailToProvider)
1701
1702	return params, err
1703}
1704
1705func (config InvoiceConfig) method() string {
1706	return "sendInvoice"
1707}
1708
1709// ShippingConfig contains information for answerShippingQuery request.
1710type ShippingConfig struct {
1711	ShippingQueryID string // required
1712	OK              bool   // required
1713	ShippingOptions []ShippingOption
1714	ErrorMessage    string
1715}
1716
1717func (config ShippingConfig) method() string {
1718	return "answerShippingQuery"
1719}
1720
1721func (config ShippingConfig) params() (Params, error) {
1722	params := make(Params)
1723
1724	params["shipping_query_id"] = config.ShippingQueryID
1725	params.AddBool("ok", config.OK)
1726	err := params.AddInterface("shipping_options", config.ShippingOptions)
1727	params.AddNonEmpty("error_message", config.ErrorMessage)
1728
1729	return params, err
1730}
1731
1732// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
1733type PreCheckoutConfig struct {
1734	PreCheckoutQueryID string // required
1735	OK                 bool   // required
1736	ErrorMessage       string
1737}
1738
1739func (config PreCheckoutConfig) method() string {
1740	return "answerPreCheckoutQuery"
1741}
1742
1743func (config PreCheckoutConfig) params() (Params, error) {
1744	params := make(Params)
1745
1746	params["pre_checkout_query_id"] = config.PreCheckoutQueryID
1747	params.AddBool("ok", config.OK)
1748	params.AddNonEmpty("error_message", config.ErrorMessage)
1749
1750	return params, nil
1751}
1752
1753// DeleteMessageConfig contains information of a message in a chat to delete.
1754type DeleteMessageConfig struct {
1755	ChannelUsername string
1756	ChatID          int64
1757	MessageID       int
1758}
1759
1760func (config DeleteMessageConfig) method() string {
1761	return "deleteMessage"
1762}
1763
1764func (config DeleteMessageConfig) params() (Params, error) {
1765	params := make(Params)
1766
1767	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1768	params.AddNonZero("message_id", config.MessageID)
1769
1770	return params, nil
1771}
1772
1773// PinChatMessageConfig contains information of a message in a chat to pin.
1774type PinChatMessageConfig struct {
1775	ChatID              int64
1776	ChannelUsername     string
1777	MessageID           int
1778	DisableNotification bool
1779}
1780
1781func (config PinChatMessageConfig) method() string {
1782	return "pinChatMessage"
1783}
1784
1785func (config PinChatMessageConfig) params() (Params, error) {
1786	params := make(Params)
1787
1788	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1789	params.AddNonZero("message_id", config.MessageID)
1790	params.AddBool("disable_notification", config.DisableNotification)
1791
1792	return params, nil
1793}
1794
1795// UnpinChatMessageConfig contains information of a chat message to unpin.
1796//
1797// If MessageID is not specified, it will unpin the most recent pin.
1798type UnpinChatMessageConfig struct {
1799	ChatID          int64
1800	ChannelUsername string
1801	MessageID       int
1802}
1803
1804func (config UnpinChatMessageConfig) method() string {
1805	return "unpinChatMessage"
1806}
1807
1808func (config UnpinChatMessageConfig) params() (Params, error) {
1809	params := make(Params)
1810
1811	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1812	params.AddNonZero("message_id", config.MessageID)
1813
1814	return params, nil
1815}
1816
1817// UnpinAllChatMessagesConfig contains information of all messages to unpin in
1818// a chat.
1819type UnpinAllChatMessagesConfig struct {
1820	ChatID          int64
1821	ChannelUsername string
1822}
1823
1824func (config UnpinAllChatMessagesConfig) method() string {
1825	return "unpinAllChatMessages"
1826}
1827
1828func (config UnpinAllChatMessagesConfig) params() (Params, error) {
1829	params := make(Params)
1830
1831	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1832
1833	return params, nil
1834}
1835
1836// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.
1837type SetChatPhotoConfig struct {
1838	BaseFile
1839}
1840
1841func (config SetChatPhotoConfig) method() string {
1842	return "setChatPhoto"
1843}
1844
1845func (config SetChatPhotoConfig) files() []RequestFile {
1846	return []RequestFile{{
1847		Name: "photo",
1848		Data: config.File,
1849	}}
1850}
1851
1852// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
1853type DeleteChatPhotoConfig struct {
1854	ChatID          int64
1855	ChannelUsername string
1856}
1857
1858func (config DeleteChatPhotoConfig) method() string {
1859	return "deleteChatPhoto"
1860}
1861
1862func (config DeleteChatPhotoConfig) params() (Params, error) {
1863	params := make(Params)
1864
1865	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1866
1867	return params, nil
1868}
1869
1870// SetChatTitleConfig allows you to set the title of something other than a private chat.
1871type SetChatTitleConfig struct {
1872	ChatID          int64
1873	ChannelUsername string
1874
1875	Title string
1876}
1877
1878func (config SetChatTitleConfig) method() string {
1879	return "setChatTitle"
1880}
1881
1882func (config SetChatTitleConfig) params() (Params, error) {
1883	params := make(Params)
1884
1885	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1886	params["title"] = config.Title
1887
1888	return params, nil
1889}
1890
1891// SetChatDescriptionConfig allows you to set the description of a supergroup or channel.
1892type SetChatDescriptionConfig struct {
1893	ChatID          int64
1894	ChannelUsername string
1895
1896	Description string
1897}
1898
1899func (config SetChatDescriptionConfig) method() string {
1900	return "setChatDescription"
1901}
1902
1903func (config SetChatDescriptionConfig) params() (Params, error) {
1904	params := make(Params)
1905
1906	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1907	params["description"] = config.Description
1908
1909	return params, nil
1910}
1911
1912// GetStickerSetConfig allows you to get the stickers in a set.
1913type GetStickerSetConfig struct {
1914	Name string
1915}
1916
1917func (config GetStickerSetConfig) method() string {
1918	return "getStickerSet"
1919}
1920
1921func (config GetStickerSetConfig) params() (Params, error) {
1922	params := make(Params)
1923
1924	params["name"] = config.Name
1925
1926	return params, nil
1927}
1928
1929// UploadStickerConfig allows you to upload a sticker for use in a set later.
1930type UploadStickerConfig struct {
1931	UserID     int64
1932	PNGSticker RequestFileData
1933}
1934
1935func (config UploadStickerConfig) method() string {
1936	return "uploadStickerFile"
1937}
1938
1939func (config UploadStickerConfig) params() (Params, error) {
1940	params := make(Params)
1941
1942	params.AddNonZero64("user_id", config.UserID)
1943
1944	return params, nil
1945}
1946
1947func (config UploadStickerConfig) files() []RequestFile {
1948	return []RequestFile{{
1949		Name: "png_sticker",
1950		Data: config.PNGSticker,
1951	}}
1952}
1953
1954// NewStickerSetConfig allows creating a new sticker set.
1955//
1956// You must set either PNGSticker or TGSSticker.
1957type NewStickerSetConfig struct {
1958	UserID        int64
1959	Name          string
1960	Title         string
1961	PNGSticker    RequestFileData
1962	TGSSticker    RequestFileData
1963	Emojis        string
1964	ContainsMasks bool
1965	MaskPosition  *MaskPosition
1966}
1967
1968func (config NewStickerSetConfig) method() string {
1969	return "createNewStickerSet"
1970}
1971
1972func (config NewStickerSetConfig) params() (Params, error) {
1973	params := make(Params)
1974
1975	params.AddNonZero64("user_id", config.UserID)
1976	params["name"] = config.Name
1977	params["title"] = config.Title
1978
1979	params["emojis"] = config.Emojis
1980
1981	params.AddBool("contains_masks", config.ContainsMasks)
1982
1983	err := params.AddInterface("mask_position", config.MaskPosition)
1984
1985	return params, err
1986}
1987
1988func (config NewStickerSetConfig) files() []RequestFile {
1989	if config.PNGSticker != nil {
1990		return []RequestFile{{
1991			Name: "png_sticker",
1992			Data: config.PNGSticker,
1993		}}
1994	}
1995
1996	return []RequestFile{{
1997		Name: "tgs_sticker",
1998		Data: config.TGSSticker,
1999	}}
2000}
2001
2002// AddStickerConfig allows you to add a sticker to a set.
2003type AddStickerConfig struct {
2004	UserID       int64
2005	Name         string
2006	PNGSticker   RequestFileData
2007	TGSSticker   RequestFileData
2008	Emojis       string
2009	MaskPosition *MaskPosition
2010}
2011
2012func (config AddStickerConfig) method() string {
2013	return "addStickerToSet"
2014}
2015
2016func (config AddStickerConfig) params() (Params, error) {
2017	params := make(Params)
2018
2019	params.AddNonZero64("user_id", config.UserID)
2020	params["name"] = config.Name
2021	params["emojis"] = config.Emojis
2022
2023	err := params.AddInterface("mask_position", config.MaskPosition)
2024
2025	return params, err
2026}
2027
2028func (config AddStickerConfig) files() []RequestFile {
2029	if config.PNGSticker != nil {
2030		return []RequestFile{{
2031			Name: "png_sticker",
2032			Data: config.PNGSticker,
2033		}}
2034	}
2035
2036	return []RequestFile{{
2037		Name: "tgs_sticker",
2038		Data: config.TGSSticker,
2039	}}
2040
2041}
2042
2043// SetStickerPositionConfig allows you to change the position of a sticker in a set.
2044type SetStickerPositionConfig struct {
2045	Sticker  string
2046	Position int
2047}
2048
2049func (config SetStickerPositionConfig) method() string {
2050	return "setStickerPositionInSet"
2051}
2052
2053func (config SetStickerPositionConfig) params() (Params, error) {
2054	params := make(Params)
2055
2056	params["sticker"] = config.Sticker
2057	params.AddNonZero("position", config.Position)
2058
2059	return params, nil
2060}
2061
2062// DeleteStickerConfig allows you to delete a sticker from a set.
2063type DeleteStickerConfig struct {
2064	Sticker string
2065}
2066
2067func (config DeleteStickerConfig) method() string {
2068	return "deleteStickerFromSet"
2069}
2070
2071func (config DeleteStickerConfig) params() (Params, error) {
2072	params := make(Params)
2073
2074	params["sticker"] = config.Sticker
2075
2076	return params, nil
2077}
2078
2079// SetStickerSetThumbConfig allows you to set the thumbnail for a sticker set.
2080type SetStickerSetThumbConfig struct {
2081	Name   string
2082	UserID int64
2083	Thumb  RequestFileData
2084}
2085
2086func (config SetStickerSetThumbConfig) method() string {
2087	return "setStickerSetThumb"
2088}
2089
2090func (config SetStickerSetThumbConfig) params() (Params, error) {
2091	params := make(Params)
2092
2093	params["name"] = config.Name
2094	params.AddNonZero64("user_id", config.UserID)
2095
2096	return params, nil
2097}
2098
2099func (config SetStickerSetThumbConfig) files() []RequestFile {
2100	return []RequestFile{{
2101		Name: "thumb",
2102		Data: config.Thumb,
2103	}}
2104}
2105
2106// SetChatStickerSetConfig allows you to set the sticker set for a supergroup.
2107type SetChatStickerSetConfig struct {
2108	ChatID             int64
2109	SuperGroupUsername string
2110
2111	StickerSetName string
2112}
2113
2114func (config SetChatStickerSetConfig) method() string {
2115	return "setChatStickerSet"
2116}
2117
2118func (config SetChatStickerSetConfig) params() (Params, error) {
2119	params := make(Params)
2120
2121	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
2122	params["sticker_set_name"] = config.StickerSetName
2123
2124	return params, nil
2125}
2126
2127// DeleteChatStickerSetConfig allows you to remove a supergroup's sticker set.
2128type DeleteChatStickerSetConfig struct {
2129	ChatID             int64
2130	SuperGroupUsername string
2131}
2132
2133func (config DeleteChatStickerSetConfig) method() string {
2134	return "deleteChatStickerSet"
2135}
2136
2137func (config DeleteChatStickerSetConfig) params() (Params, error) {
2138	params := make(Params)
2139
2140	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
2141
2142	return params, nil
2143}
2144
2145// MediaGroupConfig allows you to send a group of media.
2146//
2147// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo).
2148type MediaGroupConfig struct {
2149	ChatID          int64
2150	ChannelUsername string
2151
2152	Media               []interface{}
2153	DisableNotification bool
2154	ReplyToMessageID    int
2155}
2156
2157func (config MediaGroupConfig) method() string {
2158	return "sendMediaGroup"
2159}
2160
2161func (config MediaGroupConfig) params() (Params, error) {
2162	params := make(Params)
2163
2164	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2165	params.AddBool("disable_notification", config.DisableNotification)
2166	params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
2167
2168	err := params.AddInterface("media", prepareInputMediaForParams(config.Media))
2169
2170	return params, err
2171}
2172
2173func (config MediaGroupConfig) files() []RequestFile {
2174	return prepareInputMediaForFiles(config.Media)
2175}
2176
2177// DiceConfig contains information about a sendDice request.
2178type DiceConfig struct {
2179	BaseChat
2180	// Emoji on which the dice throw animation is based.
2181	// Currently, must be one of 🎲, 🎯, 🏀, ⚽, 🎳, or 🎰.
2182	// Dice can have values 1-6 for 🎲, 🎯, and 🎳, values 1-5 for 🏀 and ⚽,
2183	// and values 1-64 for 🎰.
2184	// Defaults to “🎲”
2185	Emoji string
2186}
2187
2188func (config DiceConfig) method() string {
2189	return "sendDice"
2190}
2191
2192func (config DiceConfig) params() (Params, error) {
2193	params, err := config.BaseChat.params()
2194	if err != nil {
2195		return params, err
2196	}
2197
2198	params.AddNonEmpty("emoji", config.Emoji)
2199
2200	return params, err
2201}
2202
2203// GetMyCommandsConfig gets a list of the currently registered commands.
2204type GetMyCommandsConfig struct {
2205	Scope        *BotCommandScope
2206	LanguageCode string
2207}
2208
2209func (config GetMyCommandsConfig) method() string {
2210	return "getMyCommands"
2211}
2212
2213func (config GetMyCommandsConfig) params() (Params, error) {
2214	params := make(Params)
2215
2216	err := params.AddInterface("scope", config.Scope)
2217	params.AddNonEmpty("language_code", config.LanguageCode)
2218
2219	return params, err
2220}
2221
2222// SetMyCommandsConfig sets a list of commands the bot understands.
2223type SetMyCommandsConfig struct {
2224	Commands     []BotCommand
2225	Scope        *BotCommandScope
2226	LanguageCode string
2227}
2228
2229func (config SetMyCommandsConfig) method() string {
2230	return "setMyCommands"
2231}
2232
2233func (config SetMyCommandsConfig) params() (Params, error) {
2234	params := make(Params)
2235
2236	if err := params.AddInterface("commands", config.Commands); err != nil {
2237		return params, err
2238	}
2239	err := params.AddInterface("scope", config.Scope)
2240	params.AddNonEmpty("language_code", config.LanguageCode)
2241
2242	return params, err
2243}
2244
2245type DeleteMyCommandsConfig struct {
2246	Scope        *BotCommandScope
2247	LanguageCode string
2248}
2249
2250func (config DeleteMyCommandsConfig) method() string {
2251	return "deleteMyCommands"
2252}
2253
2254func (config DeleteMyCommandsConfig) params() (Params, error) {
2255	params := make(Params)
2256
2257	err := params.AddInterface("scope", config.Scope)
2258	params.AddNonEmpty("language_code", config.LanguageCode)
2259
2260	return params, err
2261}
2262
2263// prepareInputMediaParam evaluates a single InputMedia and determines if it
2264// needs to be modified for a successful upload. If it returns nil, then the
2265// value does not need to be included in the params. Otherwise, it will return
2266// the same type as was originally provided.
2267//
2268// The idx is used to calculate the file field name. If you only have a single
2269// file, 0 may be used. It is formatted into "attach://file-%d" for the primary
2270// media and "attach://file-%d-thumb" for thumbnails.
2271//
2272// It is expected to be used in conjunction with prepareInputMediaFile.
2273func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} {
2274	switch m := inputMedia.(type) {
2275	case InputMediaPhoto:
2276		if m.Media.NeedsUpload() {
2277			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2278		}
2279
2280		return m
2281	case InputMediaVideo:
2282		if m.Media.NeedsUpload() {
2283			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2284		}
2285
2286		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2287			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2288		}
2289
2290		return m
2291	case InputMediaAudio:
2292		if m.Media.NeedsUpload() {
2293			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2294		}
2295
2296		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2297			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2298		}
2299
2300		return m
2301	case InputMediaDocument:
2302		if m.Media.NeedsUpload() {
2303			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2304		}
2305
2306		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2307			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2308		}
2309
2310		return m
2311	}
2312
2313	return nil
2314}
2315
2316// prepareInputMediaFile generates an array of RequestFile to provide for
2317// Fileable's files method. It returns an array as a single InputMedia may have
2318// multiple files, for the primary media and a thumbnail.
2319//
2320// The idx parameter is used to generate file field names. It uses the names
2321// "file-%d" for the main file and "file-%d-thumb" for the thumbnail.
2322//
2323// It is expected to be used in conjunction with prepareInputMediaParam.
2324func prepareInputMediaFile(inputMedia interface{}, idx int) []RequestFile {
2325	files := []RequestFile{}
2326
2327	switch m := inputMedia.(type) {
2328	case InputMediaPhoto:
2329		if m.Media.NeedsUpload() {
2330			files = append(files, RequestFile{
2331				Name: fmt.Sprintf("file-%d", idx),
2332				Data: m.Media,
2333			})
2334		}
2335	case InputMediaVideo:
2336		if m.Media.NeedsUpload() {
2337			files = append(files, RequestFile{
2338				Name: fmt.Sprintf("file-%d", idx),
2339				Data: m.Media,
2340			})
2341		}
2342
2343		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2344			files = append(files, RequestFile{
2345				Name: fmt.Sprintf("file-%d", idx),
2346				Data: m.Thumb,
2347			})
2348		}
2349	case InputMediaDocument:
2350		if m.Media.NeedsUpload() {
2351			files = append(files, RequestFile{
2352				Name: fmt.Sprintf("file-%d", idx),
2353				Data: m.Media,
2354			})
2355		}
2356
2357		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2358			files = append(files, RequestFile{
2359				Name: fmt.Sprintf("file-%d", idx),
2360				Data: m.Thumb,
2361			})
2362		}
2363	case InputMediaAudio:
2364		if m.Media.NeedsUpload() {
2365			files = append(files, RequestFile{
2366				Name: fmt.Sprintf("file-%d", idx),
2367				Data: m.Media,
2368			})
2369		}
2370
2371		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2372			files = append(files, RequestFile{
2373				Name: fmt.Sprintf("file-%d", idx),
2374				Data: m.Thumb,
2375			})
2376		}
2377	}
2378
2379	return files
2380}
2381
2382// prepareInputMediaForParams calls prepareInputMediaParam for each item
2383// provided and returns a new array with the correct params for a request.
2384//
2385// It is expected that files will get data from the associated function,
2386// prepareInputMediaForFiles.
2387func prepareInputMediaForParams(inputMedia []interface{}) []interface{} {
2388	newMedia := make([]interface{}, len(inputMedia))
2389	copy(newMedia, inputMedia)
2390
2391	for idx, media := range inputMedia {
2392		if param := prepareInputMediaParam(media, idx); param != nil {
2393			newMedia[idx] = param
2394		}
2395	}
2396
2397	return newMedia
2398}
2399
2400// prepareInputMediaForFiles calls prepareInputMediaFile for each item
2401// provided and returns a new array with the correct files for a request.
2402//
2403// It is expected that params will get data from the associated function,
2404// prepareInputMediaForParams.
2405func prepareInputMediaForFiles(inputMedia []interface{}) []RequestFile {
2406	files := []RequestFile{}
2407
2408	for idx, media := range inputMedia {
2409		if file := prepareInputMediaFile(media, idx); file != nil {
2410			files = append(files, file...)
2411		}
2412	}
2413
2414	return files
2415}