all repos — telegram-bot-api @ 2e912ef4616e92b376e71a28e79f684692b31ad4

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