all repos — telegram-bot-api @ 0d6825ebcc23bb24c6c80948ef095d9080184b8c

Golang bindings for the Telegram Bot API

configs.go (view raw)

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