all repos — telegram-bot-api @ f2ef2729ab6c83b860cde5326e70b3c143b00ec3

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// BanChatMemberConfig contains extra fields to kick user.
1298type BanChatMemberConfig struct {
1299	ChatMemberConfig
1300	UntilDate      int64
1301	RevokeMessages bool
1302}
1303
1304func (config BanChatMemberConfig) method() string {
1305	return "banChatMember"
1306}
1307
1308func (config BanChatMemberConfig) 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// KickChatMemberConfig contains extra fields to ban user.
1320//
1321// This was renamed to BanChatMember in later versions of the Telegram Bot API.
1322type KickChatMemberConfig = BanChatMemberConfig
1323
1324// RestrictChatMemberConfig contains fields to restrict members of chat
1325type RestrictChatMemberConfig struct {
1326	ChatMemberConfig
1327	UntilDate   int64
1328	Permissions *ChatPermissions
1329}
1330
1331func (config RestrictChatMemberConfig) method() string {
1332	return "restrictChatMember"
1333}
1334
1335func (config RestrictChatMemberConfig) params() (Params, error) {
1336	params := make(Params)
1337
1338	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1339	params.AddNonZero64("user_id", config.UserID)
1340
1341	err := params.AddInterface("permissions", config.Permissions)
1342	params.AddNonZero64("until_date", config.UntilDate)
1343
1344	return params, err
1345}
1346
1347// PromoteChatMemberConfig contains fields to promote members of chat
1348type PromoteChatMemberConfig struct {
1349	ChatMemberConfig
1350	IsAnonymous         bool
1351	CanManageChat       bool
1352	CanChangeInfo       bool
1353	CanPostMessages     bool
1354	CanEditMessages     bool
1355	CanDeleteMessages   bool
1356	CanManageVoiceChats bool
1357	CanInviteUsers      bool
1358	CanRestrictMembers  bool
1359	CanPinMessages      bool
1360	CanPromoteMembers   bool
1361}
1362
1363func (config PromoteChatMemberConfig) method() string {
1364	return "promoteChatMember"
1365}
1366
1367func (config PromoteChatMemberConfig) params() (Params, error) {
1368	params := make(Params)
1369
1370	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1371	params.AddNonZero64("user_id", config.UserID)
1372
1373	params.AddBool("is_anonymous", config.IsAnonymous)
1374	params.AddBool("can_manage_chat", config.CanManageChat)
1375	params.AddBool("can_change_info", config.CanChangeInfo)
1376	params.AddBool("can_post_messages", config.CanPostMessages)
1377	params.AddBool("can_edit_messages", config.CanEditMessages)
1378	params.AddBool("can_delete_messages", config.CanDeleteMessages)
1379	params.AddBool("can_manage_voice_chats", config.CanManageVoiceChats)
1380	params.AddBool("can_invite_users", config.CanInviteUsers)
1381	params.AddBool("can_restrict_members", config.CanRestrictMembers)
1382	params.AddBool("can_pin_messages", config.CanPinMessages)
1383	params.AddBool("can_promote_members", config.CanPromoteMembers)
1384
1385	return params, nil
1386}
1387
1388// SetChatAdministratorCustomTitle sets the title of an administrative user
1389// promoted by the bot for a chat.
1390type SetChatAdministratorCustomTitle struct {
1391	ChatMemberConfig
1392	CustomTitle string
1393}
1394
1395func (SetChatAdministratorCustomTitle) method() string {
1396	return "setChatAdministratorCustomTitle"
1397}
1398
1399func (config SetChatAdministratorCustomTitle) params() (Params, error) {
1400	params := make(Params)
1401
1402	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1403	params.AddNonZero64("user_id", config.UserID)
1404	params.AddNonEmpty("custom_title", config.CustomTitle)
1405
1406	return params, nil
1407}
1408
1409// ChatConfig contains information about getting information on a chat.
1410type ChatConfig struct {
1411	ChatID             int64
1412	SuperGroupUsername string
1413}
1414
1415func (config ChatConfig) params() (Params, error) {
1416	params := make(Params)
1417
1418	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1419
1420	return params, nil
1421}
1422
1423// ChatInfoConfig contains information about getting chat information.
1424type ChatInfoConfig struct {
1425	ChatConfig
1426}
1427
1428func (ChatInfoConfig) method() string {
1429	return "getChat"
1430}
1431
1432// ChatMemberCountConfig contains information about getting the number of users in a chat.
1433type ChatMemberCountConfig struct {
1434	ChatConfig
1435}
1436
1437func (ChatMemberCountConfig) method() string {
1438	return "getChatMembersCount"
1439}
1440
1441// ChatAdministratorsConfig contains information about getting chat administrators.
1442type ChatAdministratorsConfig struct {
1443	ChatConfig
1444}
1445
1446func (ChatAdministratorsConfig) method() string {
1447	return "getChatAdministrators"
1448}
1449
1450// SetChatPermissionsConfig allows you to set default permissions for the
1451// members in a group. The bot must be an administrator and have rights to
1452// restrict members.
1453type SetChatPermissionsConfig struct {
1454	ChatConfig
1455	Permissions *ChatPermissions
1456}
1457
1458func (SetChatPermissionsConfig) method() string {
1459	return "setChatPermissions"
1460}
1461
1462func (config SetChatPermissionsConfig) params() (Params, error) {
1463	params := make(Params)
1464
1465	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1466	err := params.AddInterface("permissions", config.Permissions)
1467
1468	return params, err
1469}
1470
1471// ChatInviteLinkConfig contains information about getting a chat link.
1472//
1473// Note that generating a new link will revoke any previous links.
1474type ChatInviteLinkConfig struct {
1475	ChatConfig
1476}
1477
1478func (ChatInviteLinkConfig) method() string {
1479	return "exportChatInviteLink"
1480}
1481
1482func (config ChatInviteLinkConfig) params() (Params, error) {
1483	params := make(Params)
1484
1485	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1486
1487	return params, nil
1488}
1489
1490// CreateChatInviteLinkConfig allows you to create an additional invite link for
1491// a chat. The bot must be an administrator in the chat for this to work and
1492// must have the appropriate admin rights. The link can be revoked using the
1493// RevokeChatInviteLinkConfig.
1494type CreateChatInviteLinkConfig struct {
1495	ChatConfig
1496	Name               string
1497	ExpireDate         int
1498	MemberLimit        int
1499	CreatesJoinRequest bool
1500}
1501
1502func (CreateChatInviteLinkConfig) method() string {
1503	return "createChatInviteLink"
1504}
1505
1506func (config CreateChatInviteLinkConfig) params() (Params, error) {
1507	params := make(Params)
1508
1509	params.AddNonEmpty("name", config.Name)
1510	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1511	params.AddNonZero("expire_date", config.ExpireDate)
1512	params.AddNonZero("member_limit", config.MemberLimit)
1513	params.AddBool("creates_join_request", config.CreatesJoinRequest)
1514
1515	return params, nil
1516}
1517
1518// EditChatInviteLinkConfig allows you to edit a non-primary invite link created
1519// by the bot. The bot must be an administrator in the chat for this to work and
1520// must have the appropriate admin rights.
1521type EditChatInviteLinkConfig struct {
1522	ChatConfig
1523	InviteLink         string
1524	Name               string
1525	ExpireDate         int
1526	MemberLimit        int
1527	CreatesJoinRequest bool
1528}
1529
1530func (EditChatInviteLinkConfig) method() string {
1531	return "editChatInviteLink"
1532}
1533
1534func (config EditChatInviteLinkConfig) params() (Params, error) {
1535	params := make(Params)
1536
1537	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1538	params.AddNonEmpty("name", config.Name)
1539	params["invite_link"] = config.InviteLink
1540	params.AddNonZero("expire_date", config.ExpireDate)
1541	params.AddNonZero("member_limit", config.MemberLimit)
1542	params.AddBool("creates_join_request", config.CreatesJoinRequest)
1543
1544	return params, nil
1545}
1546
1547// RevokeChatInviteLinkConfig allows you to revoke an invite link created by the
1548// bot. If the primary link is revoked, a new link is automatically generated.
1549// The bot must be an administrator in the chat for this to work and must have
1550// the appropriate admin rights.
1551type RevokeChatInviteLinkConfig struct {
1552	ChatConfig
1553	InviteLink string
1554}
1555
1556func (RevokeChatInviteLinkConfig) method() string {
1557	return "revokeChatInviteLink"
1558}
1559
1560func (config RevokeChatInviteLinkConfig) params() (Params, error) {
1561	params := make(Params)
1562
1563	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1564	params["invite_link"] = config.InviteLink
1565
1566	return params, nil
1567}
1568
1569// ApproveChatJoinRequestConfig allows you to approve a chat join request.
1570type ApproveChatJoinRequestConfig struct {
1571	ChatConfig
1572	UserID int64
1573}
1574
1575func (ApproveChatJoinRequestConfig) method() string {
1576	return "approveChatJoinRequest"
1577}
1578
1579func (config ApproveChatJoinRequestConfig) params() (Params, error) {
1580	params := make(Params)
1581
1582	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1583	params.AddNonZero("user_id", int(config.UserID))
1584
1585	return params, nil
1586}
1587
1588// DeclineChatJoinRequest allows you to decline a chat join request.
1589type DeclineChatJoinRequest struct {
1590	ChatConfig
1591	UserID int64
1592}
1593
1594func (DeclineChatJoinRequest) method() string {
1595	return "declineChatJoinRequest"
1596}
1597
1598func (config DeclineChatJoinRequest) params() (Params, error) {
1599	params := make(Params)
1600
1601	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1602	params.AddNonZero("user_id", int(config.UserID))
1603
1604	return params, nil
1605}
1606
1607// LeaveChatConfig allows you to leave a chat.
1608type LeaveChatConfig struct {
1609	ChatID          int64
1610	ChannelUsername string
1611}
1612
1613func (config LeaveChatConfig) method() string {
1614	return "leaveChat"
1615}
1616
1617func (config LeaveChatConfig) params() (Params, error) {
1618	params := make(Params)
1619
1620	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1621
1622	return params, nil
1623}
1624
1625// ChatConfigWithUser contains information about a chat and a user.
1626type ChatConfigWithUser struct {
1627	ChatID             int64
1628	SuperGroupUsername string
1629	UserID             int64
1630}
1631
1632func (config ChatConfigWithUser) params() (Params, error) {
1633	params := make(Params)
1634
1635	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1636	params.AddNonZero64("user_id", config.UserID)
1637
1638	return params, nil
1639}
1640
1641// GetChatMemberConfig is information about getting a specific member in a chat.
1642type GetChatMemberConfig struct {
1643	ChatConfigWithUser
1644}
1645
1646func (GetChatMemberConfig) method() string {
1647	return "getChatMember"
1648}
1649
1650// InvoiceConfig contains information for sendInvoice request.
1651type InvoiceConfig struct {
1652	BaseChat
1653	Title                     string         // required
1654	Description               string         // required
1655	Payload                   string         // required
1656	ProviderToken             string         // required
1657	Currency                  string         // required
1658	Prices                    []LabeledPrice // required
1659	MaxTipAmount              int
1660	SuggestedTipAmounts       []int
1661	StartParameter            string
1662	ProviderData              string
1663	PhotoURL                  string
1664	PhotoSize                 int
1665	PhotoWidth                int
1666	PhotoHeight               int
1667	NeedName                  bool
1668	NeedPhoneNumber           bool
1669	NeedEmail                 bool
1670	NeedShippingAddress       bool
1671	SendPhoneNumberToProvider bool
1672	SendEmailToProvider       bool
1673	IsFlexible                bool
1674}
1675
1676func (config InvoiceConfig) params() (Params, error) {
1677	params, err := config.BaseChat.params()
1678	if err != nil {
1679		return params, err
1680	}
1681
1682	params["title"] = config.Title
1683	params["description"] = config.Description
1684	params["payload"] = config.Payload
1685	params["provider_token"] = config.ProviderToken
1686	params["currency"] = config.Currency
1687	if err = params.AddInterface("prices", config.Prices); err != nil {
1688		return params, err
1689	}
1690
1691	params.AddNonZero("max_tip_amount", config.MaxTipAmount)
1692	err = params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts)
1693	params.AddNonEmpty("start_parameter", config.StartParameter)
1694	params.AddNonEmpty("provider_data", config.ProviderData)
1695	params.AddNonEmpty("photo_url", config.PhotoURL)
1696	params.AddNonZero("photo_size", config.PhotoSize)
1697	params.AddNonZero("photo_width", config.PhotoWidth)
1698	params.AddNonZero("photo_height", config.PhotoHeight)
1699	params.AddBool("need_name", config.NeedName)
1700	params.AddBool("need_phone_number", config.NeedPhoneNumber)
1701	params.AddBool("need_email", config.NeedEmail)
1702	params.AddBool("need_shipping_address", config.NeedShippingAddress)
1703	params.AddBool("is_flexible", config.IsFlexible)
1704	params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider)
1705	params.AddBool("send_email_to_provider", config.SendEmailToProvider)
1706
1707	return params, err
1708}
1709
1710func (config InvoiceConfig) method() string {
1711	return "sendInvoice"
1712}
1713
1714// ShippingConfig contains information for answerShippingQuery request.
1715type ShippingConfig struct {
1716	ShippingQueryID string // required
1717	OK              bool   // required
1718	ShippingOptions []ShippingOption
1719	ErrorMessage    string
1720}
1721
1722func (config ShippingConfig) method() string {
1723	return "answerShippingQuery"
1724}
1725
1726func (config ShippingConfig) params() (Params, error) {
1727	params := make(Params)
1728
1729	params["shipping_query_id"] = config.ShippingQueryID
1730	params.AddBool("ok", config.OK)
1731	err := params.AddInterface("shipping_options", config.ShippingOptions)
1732	params.AddNonEmpty("error_message", config.ErrorMessage)
1733
1734	return params, err
1735}
1736
1737// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
1738type PreCheckoutConfig struct {
1739	PreCheckoutQueryID string // required
1740	OK                 bool   // required
1741	ErrorMessage       string
1742}
1743
1744func (config PreCheckoutConfig) method() string {
1745	return "answerPreCheckoutQuery"
1746}
1747
1748func (config PreCheckoutConfig) params() (Params, error) {
1749	params := make(Params)
1750
1751	params["pre_checkout_query_id"] = config.PreCheckoutQueryID
1752	params.AddBool("ok", config.OK)
1753	params.AddNonEmpty("error_message", config.ErrorMessage)
1754
1755	return params, nil
1756}
1757
1758// DeleteMessageConfig contains information of a message in a chat to delete.
1759type DeleteMessageConfig struct {
1760	ChannelUsername string
1761	ChatID          int64
1762	MessageID       int
1763}
1764
1765func (config DeleteMessageConfig) method() string {
1766	return "deleteMessage"
1767}
1768
1769func (config DeleteMessageConfig) params() (Params, error) {
1770	params := make(Params)
1771
1772	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1773	params.AddNonZero("message_id", config.MessageID)
1774
1775	return params, nil
1776}
1777
1778// PinChatMessageConfig contains information of a message in a chat to pin.
1779type PinChatMessageConfig struct {
1780	ChatID              int64
1781	ChannelUsername     string
1782	MessageID           int
1783	DisableNotification bool
1784}
1785
1786func (config PinChatMessageConfig) method() string {
1787	return "pinChatMessage"
1788}
1789
1790func (config PinChatMessageConfig) params() (Params, error) {
1791	params := make(Params)
1792
1793	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1794	params.AddNonZero("message_id", config.MessageID)
1795	params.AddBool("disable_notification", config.DisableNotification)
1796
1797	return params, nil
1798}
1799
1800// UnpinChatMessageConfig contains information of a chat message to unpin.
1801//
1802// If MessageID is not specified, it will unpin the most recent pin.
1803type UnpinChatMessageConfig struct {
1804	ChatID          int64
1805	ChannelUsername string
1806	MessageID       int
1807}
1808
1809func (config UnpinChatMessageConfig) method() string {
1810	return "unpinChatMessage"
1811}
1812
1813func (config UnpinChatMessageConfig) params() (Params, error) {
1814	params := make(Params)
1815
1816	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1817	params.AddNonZero("message_id", config.MessageID)
1818
1819	return params, nil
1820}
1821
1822// UnpinAllChatMessagesConfig contains information of all messages to unpin in
1823// a chat.
1824type UnpinAllChatMessagesConfig struct {
1825	ChatID          int64
1826	ChannelUsername string
1827}
1828
1829func (config UnpinAllChatMessagesConfig) method() string {
1830	return "unpinAllChatMessages"
1831}
1832
1833func (config UnpinAllChatMessagesConfig) params() (Params, error) {
1834	params := make(Params)
1835
1836	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1837
1838	return params, nil
1839}
1840
1841// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.
1842type SetChatPhotoConfig struct {
1843	BaseFile
1844}
1845
1846func (config SetChatPhotoConfig) method() string {
1847	return "setChatPhoto"
1848}
1849
1850func (config SetChatPhotoConfig) files() []RequestFile {
1851	return []RequestFile{{
1852		Name: "photo",
1853		Data: config.File,
1854	}}
1855}
1856
1857// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
1858type DeleteChatPhotoConfig struct {
1859	ChatID          int64
1860	ChannelUsername string
1861}
1862
1863func (config DeleteChatPhotoConfig) method() string {
1864	return "deleteChatPhoto"
1865}
1866
1867func (config DeleteChatPhotoConfig) params() (Params, error) {
1868	params := make(Params)
1869
1870	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1871
1872	return params, nil
1873}
1874
1875// SetChatTitleConfig allows you to set the title of something other than a private chat.
1876type SetChatTitleConfig struct {
1877	ChatID          int64
1878	ChannelUsername string
1879
1880	Title string
1881}
1882
1883func (config SetChatTitleConfig) method() string {
1884	return "setChatTitle"
1885}
1886
1887func (config SetChatTitleConfig) params() (Params, error) {
1888	params := make(Params)
1889
1890	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1891	params["title"] = config.Title
1892
1893	return params, nil
1894}
1895
1896// SetChatDescriptionConfig allows you to set the description of a supergroup or channel.
1897type SetChatDescriptionConfig struct {
1898	ChatID          int64
1899	ChannelUsername string
1900
1901	Description string
1902}
1903
1904func (config SetChatDescriptionConfig) method() string {
1905	return "setChatDescription"
1906}
1907
1908func (config SetChatDescriptionConfig) params() (Params, error) {
1909	params := make(Params)
1910
1911	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1912	params["description"] = config.Description
1913
1914	return params, nil
1915}
1916
1917// GetStickerSetConfig allows you to get the stickers in a set.
1918type GetStickerSetConfig struct {
1919	Name string
1920}
1921
1922func (config GetStickerSetConfig) method() string {
1923	return "getStickerSet"
1924}
1925
1926func (config GetStickerSetConfig) params() (Params, error) {
1927	params := make(Params)
1928
1929	params["name"] = config.Name
1930
1931	return params, nil
1932}
1933
1934// UploadStickerConfig allows you to upload a sticker for use in a set later.
1935type UploadStickerConfig struct {
1936	UserID     int64
1937	PNGSticker RequestFileData
1938}
1939
1940func (config UploadStickerConfig) method() string {
1941	return "uploadStickerFile"
1942}
1943
1944func (config UploadStickerConfig) params() (Params, error) {
1945	params := make(Params)
1946
1947	params.AddNonZero64("user_id", config.UserID)
1948
1949	return params, nil
1950}
1951
1952func (config UploadStickerConfig) files() []RequestFile {
1953	return []RequestFile{{
1954		Name: "png_sticker",
1955		Data: config.PNGSticker,
1956	}}
1957}
1958
1959// NewStickerSetConfig allows creating a new sticker set.
1960//
1961// You must set either PNGSticker or TGSSticker.
1962type NewStickerSetConfig struct {
1963	UserID        int64
1964	Name          string
1965	Title         string
1966	PNGSticker    RequestFileData
1967	TGSSticker    RequestFileData
1968	Emojis        string
1969	ContainsMasks bool
1970	MaskPosition  *MaskPosition
1971}
1972
1973func (config NewStickerSetConfig) method() string {
1974	return "createNewStickerSet"
1975}
1976
1977func (config NewStickerSetConfig) params() (Params, error) {
1978	params := make(Params)
1979
1980	params.AddNonZero64("user_id", config.UserID)
1981	params["name"] = config.Name
1982	params["title"] = config.Title
1983
1984	params["emojis"] = config.Emojis
1985
1986	params.AddBool("contains_masks", config.ContainsMasks)
1987
1988	err := params.AddInterface("mask_position", config.MaskPosition)
1989
1990	return params, err
1991}
1992
1993func (config NewStickerSetConfig) files() []RequestFile {
1994	if config.PNGSticker != nil {
1995		return []RequestFile{{
1996			Name: "png_sticker",
1997			Data: config.PNGSticker,
1998		}}
1999	}
2000
2001	return []RequestFile{{
2002		Name: "tgs_sticker",
2003		Data: config.TGSSticker,
2004	}}
2005}
2006
2007// AddStickerConfig allows you to add a sticker to a set.
2008type AddStickerConfig struct {
2009	UserID       int64
2010	Name         string
2011	PNGSticker   RequestFileData
2012	TGSSticker   RequestFileData
2013	Emojis       string
2014	MaskPosition *MaskPosition
2015}
2016
2017func (config AddStickerConfig) method() string {
2018	return "addStickerToSet"
2019}
2020
2021func (config AddStickerConfig) params() (Params, error) {
2022	params := make(Params)
2023
2024	params.AddNonZero64("user_id", config.UserID)
2025	params["name"] = config.Name
2026	params["emojis"] = config.Emojis
2027
2028	err := params.AddInterface("mask_position", config.MaskPosition)
2029
2030	return params, err
2031}
2032
2033func (config AddStickerConfig) files() []RequestFile {
2034	if config.PNGSticker != nil {
2035		return []RequestFile{{
2036			Name: "png_sticker",
2037			Data: config.PNGSticker,
2038		}}
2039	}
2040
2041	return []RequestFile{{
2042		Name: "tgs_sticker",
2043		Data: config.TGSSticker,
2044	}}
2045
2046}
2047
2048// SetStickerPositionConfig allows you to change the position of a sticker in a set.
2049type SetStickerPositionConfig struct {
2050	Sticker  string
2051	Position int
2052}
2053
2054func (config SetStickerPositionConfig) method() string {
2055	return "setStickerPositionInSet"
2056}
2057
2058func (config SetStickerPositionConfig) params() (Params, error) {
2059	params := make(Params)
2060
2061	params["sticker"] = config.Sticker
2062	params.AddNonZero("position", config.Position)
2063
2064	return params, nil
2065}
2066
2067// DeleteStickerConfig allows you to delete a sticker from a set.
2068type DeleteStickerConfig struct {
2069	Sticker string
2070}
2071
2072func (config DeleteStickerConfig) method() string {
2073	return "deleteStickerFromSet"
2074}
2075
2076func (config DeleteStickerConfig) params() (Params, error) {
2077	params := make(Params)
2078
2079	params["sticker"] = config.Sticker
2080
2081	return params, nil
2082}
2083
2084// SetStickerSetThumbConfig allows you to set the thumbnail for a sticker set.
2085type SetStickerSetThumbConfig struct {
2086	Name   string
2087	UserID int64
2088	Thumb  RequestFileData
2089}
2090
2091func (config SetStickerSetThumbConfig) method() string {
2092	return "setStickerSetThumb"
2093}
2094
2095func (config SetStickerSetThumbConfig) params() (Params, error) {
2096	params := make(Params)
2097
2098	params["name"] = config.Name
2099	params.AddNonZero64("user_id", config.UserID)
2100
2101	return params, nil
2102}
2103
2104func (config SetStickerSetThumbConfig) files() []RequestFile {
2105	return []RequestFile{{
2106		Name: "thumb",
2107		Data: config.Thumb,
2108	}}
2109}
2110
2111// SetChatStickerSetConfig allows you to set the sticker set for a supergroup.
2112type SetChatStickerSetConfig struct {
2113	ChatID             int64
2114	SuperGroupUsername string
2115
2116	StickerSetName string
2117}
2118
2119func (config SetChatStickerSetConfig) method() string {
2120	return "setChatStickerSet"
2121}
2122
2123func (config SetChatStickerSetConfig) params() (Params, error) {
2124	params := make(Params)
2125
2126	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
2127	params["sticker_set_name"] = config.StickerSetName
2128
2129	return params, nil
2130}
2131
2132// DeleteChatStickerSetConfig allows you to remove a supergroup's sticker set.
2133type DeleteChatStickerSetConfig struct {
2134	ChatID             int64
2135	SuperGroupUsername string
2136}
2137
2138func (config DeleteChatStickerSetConfig) method() string {
2139	return "deleteChatStickerSet"
2140}
2141
2142func (config DeleteChatStickerSetConfig) params() (Params, error) {
2143	params := make(Params)
2144
2145	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
2146
2147	return params, nil
2148}
2149
2150// MediaGroupConfig allows you to send a group of media.
2151//
2152// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo).
2153type MediaGroupConfig struct {
2154	ChatID          int64
2155	ChannelUsername string
2156
2157	Media               []interface{}
2158	DisableNotification bool
2159	ReplyToMessageID    int
2160}
2161
2162func (config MediaGroupConfig) method() string {
2163	return "sendMediaGroup"
2164}
2165
2166func (config MediaGroupConfig) params() (Params, error) {
2167	params := make(Params)
2168
2169	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
2170	params.AddBool("disable_notification", config.DisableNotification)
2171	params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
2172
2173	err := params.AddInterface("media", prepareInputMediaForParams(config.Media))
2174
2175	return params, err
2176}
2177
2178func (config MediaGroupConfig) files() []RequestFile {
2179	return prepareInputMediaForFiles(config.Media)
2180}
2181
2182// DiceConfig contains information about a sendDice request.
2183type DiceConfig struct {
2184	BaseChat
2185	// Emoji on which the dice throw animation is based.
2186	// Currently, must be one of 🎲, 🎯, 🏀, ⚽, 🎳, or 🎰.
2187	// Dice can have values 1-6 for 🎲, 🎯, and 🎳, values 1-5 for 🏀 and ⚽,
2188	// and values 1-64 for 🎰.
2189	// Defaults to “🎲”
2190	Emoji string
2191}
2192
2193func (config DiceConfig) method() string {
2194	return "sendDice"
2195}
2196
2197func (config DiceConfig) params() (Params, error) {
2198	params, err := config.BaseChat.params()
2199	if err != nil {
2200		return params, err
2201	}
2202
2203	params.AddNonEmpty("emoji", config.Emoji)
2204
2205	return params, err
2206}
2207
2208// GetMyCommandsConfig gets a list of the currently registered commands.
2209type GetMyCommandsConfig struct {
2210	Scope        *BotCommandScope
2211	LanguageCode string
2212}
2213
2214func (config GetMyCommandsConfig) method() string {
2215	return "getMyCommands"
2216}
2217
2218func (config GetMyCommandsConfig) params() (Params, error) {
2219	params := make(Params)
2220
2221	err := params.AddInterface("scope", config.Scope)
2222	params.AddNonEmpty("language_code", config.LanguageCode)
2223
2224	return params, err
2225}
2226
2227// SetMyCommandsConfig sets a list of commands the bot understands.
2228type SetMyCommandsConfig struct {
2229	Commands     []BotCommand
2230	Scope        *BotCommandScope
2231	LanguageCode string
2232}
2233
2234func (config SetMyCommandsConfig) method() string {
2235	return "setMyCommands"
2236}
2237
2238func (config SetMyCommandsConfig) params() (Params, error) {
2239	params := make(Params)
2240
2241	if err := params.AddInterface("commands", config.Commands); err != nil {
2242		return params, err
2243	}
2244	err := params.AddInterface("scope", config.Scope)
2245	params.AddNonEmpty("language_code", config.LanguageCode)
2246
2247	return params, err
2248}
2249
2250type DeleteMyCommandsConfig struct {
2251	Scope        *BotCommandScope
2252	LanguageCode string
2253}
2254
2255func (config DeleteMyCommandsConfig) method() string {
2256	return "deleteMyCommands"
2257}
2258
2259func (config DeleteMyCommandsConfig) params() (Params, error) {
2260	params := make(Params)
2261
2262	err := params.AddInterface("scope", config.Scope)
2263	params.AddNonEmpty("language_code", config.LanguageCode)
2264
2265	return params, err
2266}
2267
2268// prepareInputMediaParam evaluates a single InputMedia and determines if it
2269// needs to be modified for a successful upload. If it returns nil, then the
2270// value does not need to be included in the params. Otherwise, it will return
2271// the same type as was originally provided.
2272//
2273// The idx is used to calculate the file field name. If you only have a single
2274// file, 0 may be used. It is formatted into "attach://file-%d" for the primary
2275// media and "attach://file-%d-thumb" for thumbnails.
2276//
2277// It is expected to be used in conjunction with prepareInputMediaFile.
2278func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} {
2279	switch m := inputMedia.(type) {
2280	case InputMediaPhoto:
2281		if m.Media.NeedsUpload() {
2282			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2283		}
2284
2285		return m
2286	case InputMediaVideo:
2287		if m.Media.NeedsUpload() {
2288			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2289		}
2290
2291		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2292			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2293		}
2294
2295		return m
2296	case InputMediaAudio:
2297		if m.Media.NeedsUpload() {
2298			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2299		}
2300
2301		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2302			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2303		}
2304
2305		return m
2306	case InputMediaDocument:
2307		if m.Media.NeedsUpload() {
2308			m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
2309		}
2310
2311		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2312			m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
2313		}
2314
2315		return m
2316	}
2317
2318	return nil
2319}
2320
2321// prepareInputMediaFile generates an array of RequestFile to provide for
2322// Fileable's files method. It returns an array as a single InputMedia may have
2323// multiple files, for the primary media and a thumbnail.
2324//
2325// The idx parameter is used to generate file field names. It uses the names
2326// "file-%d" for the main file and "file-%d-thumb" for the thumbnail.
2327//
2328// It is expected to be used in conjunction with prepareInputMediaParam.
2329func prepareInputMediaFile(inputMedia interface{}, idx int) []RequestFile {
2330	files := []RequestFile{}
2331
2332	switch m := inputMedia.(type) {
2333	case InputMediaPhoto:
2334		if m.Media.NeedsUpload() {
2335			files = append(files, RequestFile{
2336				Name: fmt.Sprintf("file-%d", idx),
2337				Data: m.Media,
2338			})
2339		}
2340	case InputMediaVideo:
2341		if m.Media.NeedsUpload() {
2342			files = append(files, RequestFile{
2343				Name: fmt.Sprintf("file-%d", idx),
2344				Data: m.Media,
2345			})
2346		}
2347
2348		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2349			files = append(files, RequestFile{
2350				Name: fmt.Sprintf("file-%d", idx),
2351				Data: m.Thumb,
2352			})
2353		}
2354	case InputMediaDocument:
2355		if m.Media.NeedsUpload() {
2356			files = append(files, RequestFile{
2357				Name: fmt.Sprintf("file-%d", idx),
2358				Data: m.Media,
2359			})
2360		}
2361
2362		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2363			files = append(files, RequestFile{
2364				Name: fmt.Sprintf("file-%d", idx),
2365				Data: m.Thumb,
2366			})
2367		}
2368	case InputMediaAudio:
2369		if m.Media.NeedsUpload() {
2370			files = append(files, RequestFile{
2371				Name: fmt.Sprintf("file-%d", idx),
2372				Data: m.Media,
2373			})
2374		}
2375
2376		if m.Thumb != nil && m.Thumb.NeedsUpload() {
2377			files = append(files, RequestFile{
2378				Name: fmt.Sprintf("file-%d", idx),
2379				Data: m.Thumb,
2380			})
2381		}
2382	}
2383
2384	return files
2385}
2386
2387// prepareInputMediaForParams calls prepareInputMediaParam for each item
2388// provided and returns a new array with the correct params for a request.
2389//
2390// It is expected that files will get data from the associated function,
2391// prepareInputMediaForFiles.
2392func prepareInputMediaForParams(inputMedia []interface{}) []interface{} {
2393	newMedia := make([]interface{}, len(inputMedia))
2394	copy(newMedia, inputMedia)
2395
2396	for idx, media := range inputMedia {
2397		if param := prepareInputMediaParam(media, idx); param != nil {
2398			newMedia[idx] = param
2399		}
2400	}
2401
2402	return newMedia
2403}
2404
2405// prepareInputMediaForFiles calls prepareInputMediaFile for each item
2406// provided and returns a new array with the correct files for a request.
2407//
2408// It is expected that params will get data from the associated function,
2409// prepareInputMediaForParams.
2410func prepareInputMediaForFiles(inputMedia []interface{}) []RequestFile {
2411	files := []RequestFile{}
2412
2413	for idx, media := range inputMedia {
2414		if file := prepareInputMediaFile(media, idx); file != nil {
2415			files = append(files, file...)
2416		}
2417	}
2418
2419	return files
2420}