all repos — telegram-bot-api @ 797f683a71269be25db71133e60c82e96c8e0725

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