all repos — telegram-bot-api @ f7e326b02e008b78a79cd56f85786a5940d0939c

Golang bindings for the Telegram Bot API

configs.go (view raw)

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