all repos — telegram-bot-api @ a45216f441cd4adc8bda63ea430a24ffa778ab6f

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	ChatRecordAudio     = "record_audio"
  26	ChatUploadAudio     = "upload_audio"
  27	ChatUploadDocument  = "upload_document"
  28	ChatFindLocation    = "find_location"
  29	ChatRecordVideoNote = "record_video_note"
  30	ChatUploadVideoNote = "upload_video_note"
  31)
  32
  33// API errors
  34const (
  35	// ErrAPIForbidden happens when a token is bad
  36	ErrAPIForbidden = "forbidden"
  37)
  38
  39// Constant values for ParseMode in MessageConfig
  40const (
  41	ModeMarkdown   = "Markdown"
  42	ModeMarkdownV2 = "MarkdownV2"
  43	ModeHTML       = "HTML"
  44)
  45
  46// Library errors
  47const (
  48	// ErrBadFileType happens when you pass an unknown type
  49	ErrBadFileType = "bad file type"
  50	ErrBadURL      = "bad or empty url"
  51)
  52
  53// Chattable is any config type that can be sent.
  54type Chattable interface {
  55	params() (Params, error)
  56	method() string
  57}
  58
  59// RequestFile represents a file associated with a request. May involve
  60// uploading a file, or passing an existing ID.
  61type RequestFile struct {
  62	// The multipart upload field name.
  63	Name string
  64	// The file to upload.
  65	File interface{}
  66}
  67
  68// Fileable is any config type that can be sent that includes a file.
  69type Fileable interface {
  70	Chattable
  71	files() []RequestFile
  72}
  73
  74// BaseChat is base type for all chat config types.
  75type BaseChat struct {
  76	ChatID              int64 // required
  77	ChannelUsername     string
  78	ReplyToMessageID    int
  79	ReplyMarkup         interface{}
  80	DisableNotification bool
  81}
  82
  83func (chat *BaseChat) params() (Params, error) {
  84	params := make(Params)
  85
  86	params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername)
  87	params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID)
  88	params.AddBool("disable_notification", chat.DisableNotification)
  89
  90	err := params.AddInterface("reply_markup", chat.ReplyMarkup)
  91
  92	return params, err
  93}
  94
  95// BaseFile is a base type for all file config types.
  96type BaseFile struct {
  97	BaseChat
  98	File interface{}
  99}
 100
 101func (file BaseFile) params() (Params, error) {
 102	return file.BaseChat.params()
 103}
 104
 105// BaseEdit is base type of all chat edits.
 106type BaseEdit struct {
 107	ChatID          int64
 108	ChannelUsername string
 109	MessageID       int
 110	InlineMessageID string
 111	ReplyMarkup     *InlineKeyboardMarkup
 112}
 113
 114func (edit BaseEdit) params() (Params, error) {
 115	params := make(Params)
 116
 117	if edit.InlineMessageID != "" {
 118		params["inline_message_id"] = edit.InlineMessageID
 119	} else {
 120		params.AddFirstValid("chat_id", edit.ChatID, edit.ChannelUsername)
 121		params.AddNonZero("message_id", edit.MessageID)
 122	}
 123
 124	err := params.AddInterface("reply_markup", edit.ReplyMarkup)
 125
 126	return params, err
 127}
 128
 129// MessageConfig contains information about a SendMessage request.
 130type MessageConfig struct {
 131	BaseChat
 132	Text                  string
 133	ParseMode             string
 134	DisableWebPagePreview bool
 135}
 136
 137func (config MessageConfig) params() (Params, error) {
 138	params, err := config.BaseChat.params()
 139	if err != nil {
 140		return params, err
 141	}
 142
 143	params.AddNonEmpty("text", config.Text)
 144	params.AddBool("disable_web_page_preview", config.DisableWebPagePreview)
 145	params.AddNonEmpty("parse_mode", config.ParseMode)
 146
 147	return params, nil
 148}
 149
 150func (config MessageConfig) method() string {
 151	return "sendMessage"
 152}
 153
 154// ForwardConfig contains information about a ForwardMessage request.
 155type ForwardConfig struct {
 156	BaseChat
 157	FromChatID          int64 // required
 158	FromChannelUsername string
 159	MessageID           int // required
 160}
 161
 162func (config ForwardConfig) params() (Params, error) {
 163	params, err := config.BaseChat.params()
 164	if err != nil {
 165		return params, err
 166	}
 167
 168	params.AddNonZero64("from_chat_id", config.FromChatID)
 169	params.AddNonZero("message_id", config.MessageID)
 170
 171	return params, nil
 172}
 173
 174func (config ForwardConfig) method() string {
 175	return "forwardMessage"
 176}
 177
 178// PhotoConfig contains information about a SendPhoto request.
 179type PhotoConfig struct {
 180	BaseFile
 181	Thumb     interface{}
 182	Caption   string
 183	ParseMode string
 184}
 185
 186func (config PhotoConfig) params() (Params, error) {
 187	params, err := config.BaseFile.params()
 188
 189	params.AddNonEmpty("caption", config.Caption)
 190	params.AddNonEmpty("parse_mode", config.ParseMode)
 191
 192	return params, err
 193}
 194
 195func (config PhotoConfig) method() string {
 196	return "sendPhoto"
 197}
 198
 199func (config PhotoConfig) files() []RequestFile {
 200	files := []RequestFile{{
 201		Name: "photo",
 202		File: config.File,
 203	}}
 204
 205	if config.Thumb != nil {
 206		files = append(files, RequestFile{
 207			Name: "thumb",
 208			File: config.Thumb,
 209		})
 210	}
 211
 212	return files
 213}
 214
 215// AudioConfig contains information about a SendAudio request.
 216type AudioConfig struct {
 217	BaseFile
 218	Thumb     interface{}
 219	Caption   string
 220	ParseMode string
 221	Duration  int
 222	Performer string
 223	Title     string
 224}
 225
 226func (config AudioConfig) params() (Params, error) {
 227	params, err := config.BaseChat.params()
 228	if err != nil {
 229		return params, err
 230	}
 231
 232	params.AddNonZero("duration", config.Duration)
 233	params.AddNonEmpty("performer", config.Performer)
 234	params.AddNonEmpty("title", config.Title)
 235	params.AddNonEmpty("caption", config.Caption)
 236	params.AddNonEmpty("parse_mode", config.ParseMode)
 237
 238	return params, nil
 239}
 240
 241func (config AudioConfig) method() string {
 242	return "sendAudio"
 243}
 244
 245func (config AudioConfig) files() []RequestFile {
 246	files := []RequestFile{{
 247		Name: "audio",
 248		File: config.File,
 249	}}
 250
 251	if config.Thumb != nil {
 252		files = append(files, RequestFile{
 253			Name: "thumb",
 254			File: config.Thumb,
 255		})
 256	}
 257
 258	return files
 259}
 260
 261// DocumentConfig contains information about a SendDocument request.
 262type DocumentConfig struct {
 263	BaseFile
 264	Thumb     interface{}
 265	Caption   string
 266	ParseMode string
 267}
 268
 269func (config DocumentConfig) params() (Params, error) {
 270	params, err := config.BaseFile.params()
 271
 272	params.AddNonEmpty("caption", config.Caption)
 273	params.AddNonEmpty("parse_mode", config.ParseMode)
 274
 275	return params, err
 276}
 277
 278func (config DocumentConfig) method() string {
 279	return "sendDocument"
 280}
 281
 282func (config DocumentConfig) files() []RequestFile {
 283	files := []RequestFile{{
 284		Name: "document",
 285		File: config.File,
 286	}}
 287
 288	if config.Thumb != nil {
 289		files = append(files, RequestFile{
 290			Name: "thumb",
 291			File: config.Thumb,
 292		})
 293	}
 294
 295	return files
 296}
 297
 298// StickerConfig contains information about a SendSticker request.
 299type StickerConfig struct {
 300	BaseFile
 301}
 302
 303func (config StickerConfig) params() (Params, error) {
 304	return config.BaseChat.params()
 305}
 306
 307func (config StickerConfig) method() string {
 308	return "sendSticker"
 309}
 310
 311func (config StickerConfig) files() []RequestFile {
 312	return []RequestFile{{
 313		Name: "sticker",
 314		File: config.File,
 315	}}
 316}
 317
 318// VideoConfig contains information about a SendVideo request.
 319type VideoConfig struct {
 320	BaseFile
 321	Thumb             interface{}
 322	Duration          int
 323	Caption           string
 324	ParseMode         string
 325	SupportsStreaming bool
 326}
 327
 328func (config VideoConfig) params() (Params, error) {
 329	params, err := config.BaseChat.params()
 330
 331	params.AddNonZero("duration", config.Duration)
 332	params.AddNonEmpty("caption", config.Caption)
 333	params.AddNonEmpty("parse_mode", config.ParseMode)
 334	params.AddBool("supports_streaming", config.SupportsStreaming)
 335
 336	return params, err
 337}
 338
 339func (config VideoConfig) method() string {
 340	return "sendVideo"
 341}
 342
 343func (config VideoConfig) files() []RequestFile {
 344	files := []RequestFile{{
 345		Name: "video",
 346		File: config.File,
 347	}}
 348
 349	if config.Thumb != nil {
 350		files = append(files, RequestFile{
 351			Name: "thumb",
 352			File: config.Thumb,
 353		})
 354	}
 355
 356	return files
 357}
 358
 359// AnimationConfig contains information about a SendAnimation request.
 360type AnimationConfig struct {
 361	BaseFile
 362	Duration  int
 363	Thumb     interface{}
 364	Caption   string
 365	ParseMode string
 366}
 367
 368func (config AnimationConfig) params() (Params, error) {
 369	params, err := config.BaseChat.params()
 370
 371	params.AddNonZero("duration", config.Duration)
 372	params.AddNonEmpty("caption", config.Caption)
 373	params.AddNonEmpty("parse_mode", config.ParseMode)
 374
 375	return params, err
 376}
 377
 378func (config AnimationConfig) name() string {
 379	return "animation"
 380}
 381
 382func (config AnimationConfig) method() string {
 383	return "sendAnimation"
 384}
 385
 386func (config AnimationConfig) files() []RequestFile {
 387	files := []RequestFile{{
 388		Name: "animation",
 389		File: config.File,
 390	}}
 391
 392	if config.Thumb != nil {
 393		files = append(files, RequestFile{
 394			Name: "thumb",
 395			File: config.Thumb,
 396		})
 397	}
 398
 399	return files
 400}
 401
 402// VideoNoteConfig contains information about a SendVideoNote request.
 403type VideoNoteConfig struct {
 404	BaseFile
 405	Thumb    interface{}
 406	Duration int
 407	Length   int
 408}
 409
 410func (config VideoNoteConfig) params() (Params, error) {
 411	params, err := config.BaseChat.params()
 412
 413	params.AddNonZero("duration", config.Duration)
 414	params.AddNonZero("length", config.Length)
 415
 416	return params, err
 417}
 418
 419func (config VideoNoteConfig) method() string {
 420	return "sendVideoNote"
 421}
 422
 423func (config VideoNoteConfig) files() []RequestFile {
 424	files := []RequestFile{{
 425		Name: "video_note",
 426		File: config.File,
 427	}}
 428
 429	if config.Thumb != nil {
 430		files = append(files, RequestFile{
 431			Name: "thumb",
 432			File: config.Thumb,
 433		})
 434	}
 435
 436	return files
 437}
 438
 439// VoiceConfig contains information about a SendVoice request.
 440type VoiceConfig struct {
 441	BaseFile
 442	Thumb     interface{}
 443	Caption   string
 444	ParseMode string
 445	Duration  int
 446}
 447
 448func (config VoiceConfig) params() (Params, error) {
 449	params, err := config.BaseChat.params()
 450
 451	params.AddNonZero("duration", config.Duration)
 452	params.AddNonEmpty("caption", config.Caption)
 453	params.AddNonEmpty("parse_mode", config.ParseMode)
 454
 455	return params, err
 456}
 457
 458func (config VoiceConfig) method() string {
 459	return "sendVoice"
 460}
 461
 462func (config VoiceConfig) files() []RequestFile {
 463	files := []RequestFile{{
 464		Name: "voice",
 465		File: config.File,
 466	}}
 467
 468	if config.Thumb != nil {
 469		files = append(files, RequestFile{
 470			Name: "thumb",
 471			File: config.Thumb,
 472		})
 473	}
 474
 475	return files
 476}
 477
 478// LocationConfig contains information about a SendLocation request.
 479type LocationConfig struct {
 480	BaseChat
 481	Latitude   float64 // required
 482	Longitude  float64 // required
 483	LivePeriod int     // optional
 484}
 485
 486func (config LocationConfig) params() (Params, error) {
 487	params, err := config.BaseChat.params()
 488
 489	params.AddNonZeroFloat("latitude", config.Latitude)
 490	params.AddNonZeroFloat("longitude", config.Longitude)
 491	params.AddNonZero("live_period", config.LivePeriod)
 492
 493	return params, err
 494}
 495
 496func (config LocationConfig) method() string {
 497	return "sendLocation"
 498}
 499
 500// EditMessageLiveLocationConfig allows you to update a live location.
 501type EditMessageLiveLocationConfig struct {
 502	BaseEdit
 503	Latitude  float64 // required
 504	Longitude float64 // required
 505}
 506
 507func (config EditMessageLiveLocationConfig) params() (Params, error) {
 508	params, err := config.BaseEdit.params()
 509
 510	params.AddNonZeroFloat("latitude", config.Latitude)
 511	params.AddNonZeroFloat("longitude", config.Longitude)
 512
 513	return params, err
 514}
 515
 516func (config EditMessageLiveLocationConfig) method() string {
 517	return "editMessageLiveLocation"
 518}
 519
 520// StopMessageLiveLocationConfig stops updating a live location.
 521type StopMessageLiveLocationConfig struct {
 522	BaseEdit
 523}
 524
 525func (config StopMessageLiveLocationConfig) params() (Params, error) {
 526	return config.BaseEdit.params()
 527}
 528
 529func (config StopMessageLiveLocationConfig) method() string {
 530	return "stopMessageLiveLocation"
 531}
 532
 533// VenueConfig contains information about a SendVenue request.
 534type VenueConfig struct {
 535	BaseChat
 536	Latitude     float64 // required
 537	Longitude    float64 // required
 538	Title        string  // required
 539	Address      string  // required
 540	FoursquareID string
 541}
 542
 543func (config VenueConfig) params() (Params, error) {
 544	params, err := config.BaseChat.params()
 545
 546	params.AddNonZeroFloat("latitude", config.Latitude)
 547	params.AddNonZeroFloat("longitude", config.Longitude)
 548	params["title"] = config.Title
 549	params["address"] = config.Address
 550	params.AddNonEmpty("foursquare_id", config.FoursquareID)
 551
 552	return params, err
 553}
 554
 555func (config VenueConfig) method() string {
 556	return "sendVenue"
 557}
 558
 559// ContactConfig allows you to send a contact.
 560type ContactConfig struct {
 561	BaseChat
 562	PhoneNumber string
 563	FirstName   string
 564	LastName    string
 565	VCard       string
 566}
 567
 568func (config ContactConfig) params() (Params, error) {
 569	params, err := config.BaseChat.params()
 570
 571	params["phone_number"] = config.PhoneNumber
 572	params["first_name"] = config.FirstName
 573
 574	params.AddNonEmpty("last_name", config.LastName)
 575	params.AddNonEmpty("vcard", config.VCard)
 576
 577	return params, err
 578}
 579
 580func (config ContactConfig) method() string {
 581	return "sendContact"
 582}
 583
 584// SendPollConfig allows you to send a poll.
 585type SendPollConfig struct {
 586	BaseChat
 587	Question              string
 588	Options               []string
 589	IsAnonymous           bool
 590	Type                  string
 591	AllowsMultipleAnswers bool
 592	CorrectOptionID       int64
 593	Explanation           string
 594	ExplanationParseMode  string
 595	OpenPeriod            int
 596	CloseDate             int
 597	IsClosed              bool
 598}
 599
 600func (config SendPollConfig) params() (Params, error) {
 601	params, err := config.BaseChat.params()
 602	if err != nil {
 603		return params, err
 604	}
 605
 606	params["question"] = config.Question
 607	err = params.AddInterface("options", config.Options)
 608	params["is_anonymous"] = strconv.FormatBool(config.IsAnonymous)
 609	params.AddNonEmpty("type", config.Type)
 610	params["allows_multiple_answers"] = strconv.FormatBool(config.AllowsMultipleAnswers)
 611	params["correct_option_id"] = strconv.FormatInt(config.CorrectOptionID, 10)
 612	params.AddBool("is_closed", config.IsClosed)
 613	params.AddNonEmpty("explanation", config.Explanation)
 614	params.AddNonEmpty("explanation_parse_mode", config.ExplanationParseMode)
 615	params.AddNonZero("open_period", config.OpenPeriod)
 616	params.AddNonZero("close_date", config.CloseDate)
 617
 618	return params, err
 619}
 620
 621func (SendPollConfig) method() string {
 622	return "sendPoll"
 623}
 624
 625// GameConfig allows you to send a game.
 626type GameConfig struct {
 627	BaseChat
 628	GameShortName string
 629}
 630
 631func (config GameConfig) params() (Params, error) {
 632	params, err := config.BaseChat.params()
 633
 634	params["game_short_name"] = config.GameShortName
 635
 636	return params, err
 637}
 638
 639func (config GameConfig) method() string {
 640	return "sendGame"
 641}
 642
 643// SetGameScoreConfig allows you to update the game score in a chat.
 644type SetGameScoreConfig struct {
 645	UserID             int
 646	Score              int
 647	Force              bool
 648	DisableEditMessage bool
 649	ChatID             int64
 650	ChannelUsername    string
 651	MessageID          int
 652	InlineMessageID    string
 653}
 654
 655func (config SetGameScoreConfig) params() (Params, error) {
 656	params := make(Params)
 657
 658	params.AddNonZero("user_id", config.UserID)
 659	params.AddNonZero("scrore", config.Score)
 660	params.AddBool("disable_edit_message", config.DisableEditMessage)
 661
 662	if config.InlineMessageID != "" {
 663		params["inline_message_id"] = config.InlineMessageID
 664	} else {
 665		params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
 666		params.AddNonZero("message_id", config.MessageID)
 667	}
 668
 669	return params, nil
 670}
 671
 672func (config SetGameScoreConfig) method() string {
 673	return "setGameScore"
 674}
 675
 676// GetGameHighScoresConfig allows you to fetch the high scores for a game.
 677type GetGameHighScoresConfig struct {
 678	UserID          int
 679	ChatID          int
 680	ChannelUsername string
 681	MessageID       int
 682	InlineMessageID string
 683}
 684
 685func (config GetGameHighScoresConfig) params() (Params, error) {
 686	params := make(Params)
 687
 688	params.AddNonZero("user_id", config.UserID)
 689
 690	if config.InlineMessageID != "" {
 691		params["inline_message_id"] = config.InlineMessageID
 692	} else {
 693		params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
 694		params.AddNonZero("message_id", config.MessageID)
 695	}
 696
 697	return params, nil
 698}
 699
 700func (config GetGameHighScoresConfig) method() string {
 701	return "getGameHighScores"
 702}
 703
 704// ChatActionConfig contains information about a SendChatAction request.
 705type ChatActionConfig struct {
 706	BaseChat
 707	Action string // required
 708}
 709
 710func (config ChatActionConfig) params() (Params, error) {
 711	params, err := config.BaseChat.params()
 712
 713	params["action"] = config.Action
 714
 715	return params, err
 716}
 717
 718func (config ChatActionConfig) method() string {
 719	return "sendChatAction"
 720}
 721
 722// EditMessageTextConfig allows you to modify the text in a message.
 723type EditMessageTextConfig struct {
 724	BaseEdit
 725	Text                  string
 726	ParseMode             string
 727	DisableWebPagePreview bool
 728}
 729
 730func (config EditMessageTextConfig) params() (Params, error) {
 731	params, err := config.BaseEdit.params()
 732
 733	params["text"] = config.Text
 734	params.AddNonEmpty("parse_mode", config.ParseMode)
 735	params.AddBool("disable_web_page_preview", config.DisableWebPagePreview)
 736
 737	return params, err
 738}
 739
 740func (config EditMessageTextConfig) method() string {
 741	return "editMessageText"
 742}
 743
 744// EditMessageCaptionConfig allows you to modify the caption of a message.
 745type EditMessageCaptionConfig struct {
 746	BaseEdit
 747	Caption   string
 748	ParseMode string
 749}
 750
 751func (config EditMessageCaptionConfig) params() (Params, error) {
 752	params, err := config.BaseEdit.params()
 753
 754	params["caption"] = config.Caption
 755	params.AddNonEmpty("parse_mode", config.ParseMode)
 756
 757	return params, err
 758}
 759
 760func (config EditMessageCaptionConfig) method() string {
 761	return "editMessageCaption"
 762}
 763
 764// EditMessageMediaConfig allows you to make an editMessageMedia request.
 765type EditMessageMediaConfig struct {
 766	BaseEdit
 767
 768	Media interface{}
 769}
 770
 771func (EditMessageMediaConfig) method() string {
 772	return "editMessageMedia"
 773}
 774
 775func (config EditMessageMediaConfig) params() (Params, error) {
 776	params, err := config.BaseEdit.params()
 777	if err != nil {
 778		return params, err
 779	}
 780
 781	err = params.AddInterface("media", prepareInputMediaParam(config.Media, 0))
 782
 783	return params, err
 784}
 785
 786func (config EditMessageMediaConfig) files() []RequestFile {
 787	return prepareInputMediaFile(config.Media, 0)
 788}
 789
 790// EditMessageReplyMarkupConfig allows you to modify the reply markup
 791// of a message.
 792type EditMessageReplyMarkupConfig struct {
 793	BaseEdit
 794}
 795
 796func (config EditMessageReplyMarkupConfig) params() (Params, error) {
 797	return config.BaseEdit.params()
 798}
 799
 800func (config EditMessageReplyMarkupConfig) method() string {
 801	return "editMessageReplyMarkup"
 802}
 803
 804// StopPollConfig allows you to stop a poll sent by the bot.
 805type StopPollConfig struct {
 806	BaseEdit
 807}
 808
 809func (config StopPollConfig) params() (Params, error) {
 810	return config.BaseEdit.params()
 811}
 812
 813func (StopPollConfig) method() string {
 814	return "stopPoll"
 815}
 816
 817// UserProfilePhotosConfig contains information about a
 818// GetUserProfilePhotos request.
 819type UserProfilePhotosConfig struct {
 820	UserID int
 821	Offset int
 822	Limit  int
 823}
 824
 825func (UserProfilePhotosConfig) method() string {
 826	return "getUserProfilePhotos"
 827}
 828
 829func (config UserProfilePhotosConfig) params() (Params, error) {
 830	params := make(Params)
 831
 832	params.AddNonZero("user_id", config.UserID)
 833	params.AddNonZero("offset", config.Offset)
 834	params.AddNonZero("limit", config.Limit)
 835
 836	return params, nil
 837}
 838
 839// FileConfig has information about a file hosted on Telegram.
 840type FileConfig struct {
 841	FileID string
 842}
 843
 844func (FileConfig) method() string {
 845	return "getFile"
 846}
 847
 848func (config FileConfig) params() (Params, error) {
 849	params := make(Params)
 850
 851	params["file_id"] = config.FileID
 852
 853	return params, nil
 854}
 855
 856// UpdateConfig contains information about a GetUpdates request.
 857type UpdateConfig struct {
 858	Offset  int
 859	Limit   int
 860	Timeout int
 861}
 862
 863func (UpdateConfig) method() string {
 864	return "getUpdates"
 865}
 866
 867func (config UpdateConfig) params() (Params, error) {
 868	params := make(Params)
 869
 870	params.AddNonZero("offset", config.Offset)
 871	params.AddNonZero("limit", config.Limit)
 872	params.AddNonZero("timeout", config.Timeout)
 873
 874	return params, nil
 875}
 876
 877// WebhookConfig contains information about a SetWebhook request.
 878type WebhookConfig struct {
 879	URL            *url.URL
 880	Certificate    interface{}
 881	MaxConnections int
 882	AllowedUpdates []string
 883}
 884
 885func (config WebhookConfig) method() string {
 886	return "setWebhook"
 887}
 888
 889func (config WebhookConfig) params() (Params, error) {
 890	params := make(Params)
 891
 892	if config.URL != nil {
 893		params["url"] = config.URL.String()
 894	}
 895
 896	params.AddNonZero("max_connections", config.MaxConnections)
 897	err := params.AddInterface("allowed_updates", config.AllowedUpdates)
 898
 899	return params, err
 900}
 901
 902func (config WebhookConfig) name() string {
 903	return "certificate"
 904}
 905
 906// RemoveWebhookConfig is a helper to remove a webhook.
 907type RemoveWebhookConfig struct {
 908}
 909
 910func (config RemoveWebhookConfig) method() string {
 911	return "setWebhook"
 912}
 913
 914func (config RemoveWebhookConfig) params() (Params, error) {
 915	return nil, nil
 916}
 917
 918// FileBytes contains information about a set of bytes to upload
 919// as a File.
 920type FileBytes struct {
 921	Name  string
 922	Bytes []byte
 923}
 924
 925// FileReader contains information about a reader to upload as a File.
 926// If Size is -1, it will read the entire Reader into memory to
 927// calculate a Size.
 928type FileReader struct {
 929	Name   string
 930	Reader io.Reader
 931	Size   int64
 932}
 933
 934// FileURL is a URL to use as a file for a request.
 935type FileURL string
 936
 937// FileID is an ID of a file already uploaded to Telegram.
 938type FileID string
 939
 940// InlineConfig contains information on making an InlineQuery response.
 941type InlineConfig struct {
 942	InlineQueryID     string        `json:"inline_query_id"`
 943	Results           []interface{} `json:"results"`
 944	CacheTime         int           `json:"cache_time"`
 945	IsPersonal        bool          `json:"is_personal"`
 946	NextOffset        string        `json:"next_offset"`
 947	SwitchPMText      string        `json:"switch_pm_text"`
 948	SwitchPMParameter string        `json:"switch_pm_parameter"`
 949}
 950
 951func (config InlineConfig) method() string {
 952	return "answerInlineQuery"
 953}
 954
 955func (config InlineConfig) params() (Params, error) {
 956	params := make(Params)
 957
 958	params["inline_query_id"] = config.InlineQueryID
 959	params.AddNonZero("cache_time", config.CacheTime)
 960	params.AddBool("is_personal", config.IsPersonal)
 961	params.AddNonEmpty("next_offset", config.NextOffset)
 962	params.AddNonEmpty("switch_pm_text", config.SwitchPMText)
 963	params.AddNonEmpty("switch_pm_parameter", config.SwitchPMParameter)
 964
 965	if err := params.AddInterface("results", config.Results); err != nil {
 966		return params, err
 967	}
 968
 969	return params, nil
 970}
 971
 972// CallbackConfig contains information on making a CallbackQuery response.
 973type CallbackConfig struct {
 974	CallbackQueryID string `json:"callback_query_id"`
 975	Text            string `json:"text"`
 976	ShowAlert       bool   `json:"show_alert"`
 977	URL             string `json:"url"`
 978	CacheTime       int    `json:"cache_time"`
 979}
 980
 981func (config CallbackConfig) method() string {
 982	return "answerCallbackQuery"
 983}
 984
 985func (config CallbackConfig) params() (Params, error) {
 986	params := make(Params)
 987
 988	params["callback_query_id"] = config.CallbackQueryID
 989	params.AddNonEmpty("text", config.Text)
 990	params.AddBool("show_alert", config.ShowAlert)
 991	params.AddNonEmpty("url", config.URL)
 992	params.AddNonZero("cache_time", config.CacheTime)
 993
 994	return params, nil
 995}
 996
 997// ChatMemberConfig contains information about a user in a chat for use
 998// with administrative functions such as kicking or unbanning a user.
 999type ChatMemberConfig struct {
1000	ChatID             int64
1001	SuperGroupUsername string
1002	ChannelUsername    string
1003	UserID             int
1004}
1005
1006// UnbanChatMemberConfig allows you to unban a user.
1007type UnbanChatMemberConfig struct {
1008	ChatMemberConfig
1009}
1010
1011func (config UnbanChatMemberConfig) method() string {
1012	return "unbanChatMember"
1013}
1014
1015func (config UnbanChatMemberConfig) params() (Params, error) {
1016	params := make(Params)
1017
1018	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1019	params.AddNonZero("user_id", config.UserID)
1020
1021	return params, nil
1022}
1023
1024// KickChatMemberConfig contains extra fields to kick user
1025type KickChatMemberConfig struct {
1026	ChatMemberConfig
1027	UntilDate int64
1028}
1029
1030func (config KickChatMemberConfig) method() string {
1031	return "kickChatMember"
1032}
1033
1034func (config KickChatMemberConfig) params() (Params, error) {
1035	params := make(Params)
1036
1037	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1038	params.AddNonZero("user_id", config.UserID)
1039	params.AddNonZero64("until_date", config.UntilDate)
1040
1041	return params, nil
1042}
1043
1044// RestrictChatMemberConfig contains fields to restrict members of chat
1045type RestrictChatMemberConfig struct {
1046	ChatMemberConfig
1047	UntilDate   int64
1048	Permissions *ChatPermissions
1049}
1050
1051func (config RestrictChatMemberConfig) method() string {
1052	return "restrictChatMember"
1053}
1054
1055func (config RestrictChatMemberConfig) params() (Params, error) {
1056	params := make(Params)
1057
1058	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1059	params.AddNonZero("user_id", config.UserID)
1060
1061	if err := params.AddInterface("permissions", config.Permissions); err != nil {
1062		return params, err
1063	}
1064	params.AddNonZero64("until_date", config.UntilDate)
1065
1066	return params, nil
1067}
1068
1069// PromoteChatMemberConfig contains fields to promote members of chat
1070type PromoteChatMemberConfig struct {
1071	ChatMemberConfig
1072	CanChangeInfo      bool
1073	CanPostMessages    bool
1074	CanEditMessages    bool
1075	CanDeleteMessages  bool
1076	CanInviteUsers     bool
1077	CanRestrictMembers bool
1078	CanPinMessages     bool
1079	CanPromoteMembers  bool
1080}
1081
1082func (config PromoteChatMemberConfig) method() string {
1083	return "promoteChatMember"
1084}
1085
1086func (config PromoteChatMemberConfig) params() (Params, error) {
1087	params := make(Params)
1088
1089	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1090	params.AddNonZero("user_id", config.UserID)
1091
1092	params.AddBool("can_change_info", config.CanChangeInfo)
1093	params.AddBool("can_post_messages", config.CanPostMessages)
1094	params.AddBool("can_edit_messages", config.CanEditMessages)
1095	params.AddBool("can_delete_messages", config.CanDeleteMessages)
1096	params.AddBool("can_invite_users", config.CanInviteUsers)
1097	params.AddBool("can_restrict_members", config.CanRestrictMembers)
1098	params.AddBool("can_pin_messages", config.CanPinMessages)
1099	params.AddBool("can_promote_members", config.CanPromoteMembers)
1100
1101	return params, nil
1102}
1103
1104// SetChatAdministratorCustomTitle sets the title of an administrative user
1105// promoted by the bot for a chat.
1106type SetChatAdministratorCustomTitle struct {
1107	ChatMemberConfig
1108	CustomTitle string
1109}
1110
1111func (SetChatAdministratorCustomTitle) method() string {
1112	return "setChatAdministratorCustomTitle"
1113}
1114
1115func (config SetChatAdministratorCustomTitle) params() (Params, error) {
1116	params := make(Params)
1117
1118	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
1119	params.AddNonZero("user_id", config.UserID)
1120	params.AddNonEmpty("custom_title", config.CustomTitle)
1121
1122	return params, nil
1123}
1124
1125// ChatConfig contains information about getting information on a chat.
1126type ChatConfig struct {
1127	ChatID             int64
1128	SuperGroupUsername string
1129}
1130
1131func (config ChatConfig) params() (Params, error) {
1132	params := make(Params)
1133
1134	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1135
1136	return params, nil
1137}
1138
1139// ChatInfoConfig contains information about getting chat information.
1140type ChatInfoConfig struct {
1141	ChatConfig
1142}
1143
1144func (ChatInfoConfig) method() string {
1145	return "getChat"
1146}
1147
1148// ChatMemberCountConfig contains information about getting the number of users in a chat.
1149type ChatMemberCountConfig struct {
1150	ChatConfig
1151}
1152
1153func (ChatMemberCountConfig) method() string {
1154	return "getChatMembersCount"
1155}
1156
1157// ChatAdministratorsConfig contains information about getting chat administrators.
1158type ChatAdministratorsConfig struct {
1159	ChatConfig
1160}
1161
1162func (ChatAdministratorsConfig) method() string {
1163	return "getChatAdministrators"
1164}
1165
1166// SetChatPermissionsConfig allows you to set default permissions for the
1167// members in a group. The bot must be an administrator and have rights to
1168// restrict members.
1169type SetChatPermissionsConfig struct {
1170	ChatConfig
1171	Permissions *ChatPermissions
1172}
1173
1174func (SetChatPermissionsConfig) method() string {
1175	return "setChatPermissions"
1176}
1177
1178func (config SetChatPermissionsConfig) params() (Params, error) {
1179	params := make(Params)
1180
1181	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1182	err := params.AddInterface("permissions", config.Permissions)
1183
1184	return params, err
1185}
1186
1187// ChatInviteLinkConfig contains information about getting a chat link.
1188//
1189// Note that generating a new link will revoke any previous links.
1190type ChatInviteLinkConfig struct {
1191	ChatConfig
1192}
1193
1194func (ChatInviteLinkConfig) method() string {
1195	return "exportChatInviteLink"
1196}
1197
1198func (config ChatInviteLinkConfig) params() (Params, error) {
1199	params := make(Params)
1200
1201	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1202
1203	return params, nil
1204}
1205
1206// LeaveChatConfig allows you to leave a chat.
1207type LeaveChatConfig struct {
1208	ChatID          int64
1209	ChannelUsername string
1210}
1211
1212func (config LeaveChatConfig) method() string {
1213	return "leaveChat"
1214}
1215
1216func (config LeaveChatConfig) params() (Params, error) {
1217	params := make(Params)
1218
1219	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1220
1221	return params, nil
1222}
1223
1224// ChatConfigWithUser contains information about a chat and a user.
1225type ChatConfigWithUser struct {
1226	ChatID             int64
1227	SuperGroupUsername string
1228	UserID             int
1229}
1230
1231func (config ChatConfigWithUser) params() (Params, error) {
1232	params := make(Params)
1233
1234	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1235	params.AddNonZero("user_id", config.UserID)
1236
1237	return params, nil
1238}
1239
1240// GetChatMemberConfig is information about getting a specific member in a chat.
1241type GetChatMemberConfig struct {
1242	ChatConfigWithUser
1243}
1244
1245func (GetChatMemberConfig) method() string {
1246	return "getChatMember"
1247}
1248
1249// InvoiceConfig contains information for sendInvoice request.
1250type InvoiceConfig struct {
1251	BaseChat
1252	Title                     string         // required
1253	Description               string         // required
1254	Payload                   string         // required
1255	ProviderToken             string         // required
1256	StartParameter            string         // required
1257	Currency                  string         // required
1258	Prices                    []LabeledPrice // required
1259	ProviderData              string
1260	PhotoURL                  string
1261	PhotoSize                 int
1262	PhotoWidth                int
1263	PhotoHeight               int
1264	NeedName                  bool
1265	NeedPhoneNumber           bool
1266	NeedEmail                 bool
1267	NeedShippingAddress       bool
1268	SendPhoneNumberToProvider bool
1269	SendEmailToProvider       bool
1270	IsFlexible                bool
1271}
1272
1273func (config InvoiceConfig) params() (Params, error) {
1274	params, err := config.BaseChat.params()
1275	if err != nil {
1276		return params, err
1277	}
1278
1279	params["title"] = config.Title
1280	params["description"] = config.Description
1281	params["payload"] = config.Payload
1282	params["provider_token"] = config.ProviderToken
1283	params["start_parameter"] = config.StartParameter
1284	params["currency"] = config.Currency
1285
1286	if err = params.AddInterface("prices", config.Prices); err != nil {
1287		return params, err
1288	}
1289
1290	params.AddNonEmpty("provider_data", config.ProviderData)
1291	params.AddNonEmpty("photo_url", config.PhotoURL)
1292	params.AddNonZero("photo_size", config.PhotoSize)
1293	params.AddNonZero("photo_width", config.PhotoWidth)
1294	params.AddNonZero("photo_height", config.PhotoHeight)
1295	params.AddBool("need_name", config.NeedName)
1296	params.AddBool("need_phone_number", config.NeedPhoneNumber)
1297	params.AddBool("need_email", config.NeedEmail)
1298	params.AddBool("need_shipping_address", config.NeedShippingAddress)
1299	params.AddBool("is_flexible", config.IsFlexible)
1300	params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider)
1301	params.AddBool("send_email_to_provider", config.SendEmailToProvider)
1302
1303	return params, nil
1304}
1305
1306func (config InvoiceConfig) method() string {
1307	return "sendInvoice"
1308}
1309
1310// ShippingConfig contains information for answerShippingQuery request.
1311type ShippingConfig struct {
1312	ShippingQueryID string // required
1313	OK              bool   // required
1314	ShippingOptions []ShippingOption
1315	ErrorMessage    string
1316}
1317
1318// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
1319type PreCheckoutConfig struct {
1320	PreCheckoutQueryID string // required
1321	OK                 bool   // required
1322	ErrorMessage       string
1323}
1324
1325// DeleteMessageConfig contains information of a message in a chat to delete.
1326type DeleteMessageConfig struct {
1327	ChannelUsername string
1328	ChatID          int64
1329	MessageID       int
1330}
1331
1332func (config DeleteMessageConfig) method() string {
1333	return "deleteMessage"
1334}
1335
1336func (config DeleteMessageConfig) params() (Params, error) {
1337	params := make(Params)
1338
1339	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1340	params.AddNonZero("message_id", config.MessageID)
1341
1342	return params, nil
1343}
1344
1345// PinChatMessageConfig contains information of a message in a chat to pin.
1346type PinChatMessageConfig struct {
1347	ChatID              int64
1348	ChannelUsername     string
1349	MessageID           int
1350	DisableNotification bool
1351}
1352
1353func (config PinChatMessageConfig) method() string {
1354	return "pinChatMessage"
1355}
1356
1357func (config PinChatMessageConfig) params() (Params, error) {
1358	params := make(Params)
1359
1360	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1361	params.AddNonZero("message_id", config.MessageID)
1362	params.AddBool("disable_notification", config.DisableNotification)
1363
1364	return params, nil
1365}
1366
1367// UnpinChatMessageConfig contains information of chat to unpin.
1368type UnpinChatMessageConfig struct {
1369	ChatID          int64
1370	ChannelUsername string
1371}
1372
1373func (config UnpinChatMessageConfig) method() string {
1374	return "unpinChatMessage"
1375}
1376
1377func (config UnpinChatMessageConfig) params() (Params, error) {
1378	params := make(Params)
1379
1380	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1381
1382	return params, nil
1383}
1384
1385// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.
1386type SetChatPhotoConfig struct {
1387	BaseFile
1388}
1389
1390func (config SetChatPhotoConfig) method() string {
1391	return "setChatPhoto"
1392}
1393
1394func (config SetChatPhotoConfig) files() []RequestFile {
1395	return []RequestFile{{
1396		Name: "photo",
1397		File: config.File,
1398	}}
1399}
1400
1401// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
1402type DeleteChatPhotoConfig struct {
1403	ChatID          int64
1404	ChannelUsername string
1405}
1406
1407func (config DeleteChatPhotoConfig) method() string {
1408	return "deleteChatPhoto"
1409}
1410
1411func (config DeleteChatPhotoConfig) params() (Params, error) {
1412	params := make(Params)
1413
1414	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1415
1416	return params, nil
1417}
1418
1419// SetChatTitleConfig allows you to set the title of something other than a private chat.
1420type SetChatTitleConfig struct {
1421	ChatID          int64
1422	ChannelUsername string
1423
1424	Title string
1425}
1426
1427func (config SetChatTitleConfig) method() string {
1428	return "setChatTitle"
1429}
1430
1431func (config SetChatTitleConfig) params() (Params, error) {
1432	params := make(Params)
1433
1434	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1435	params["title"] = config.Title
1436
1437	return params, nil
1438}
1439
1440// SetChatDescriptionConfig allows you to set the description of a supergroup or channel.
1441type SetChatDescriptionConfig struct {
1442	ChatID          int64
1443	ChannelUsername string
1444
1445	Description string
1446}
1447
1448func (config SetChatDescriptionConfig) method() string {
1449	return "setChatDescription"
1450}
1451
1452func (config SetChatDescriptionConfig) params() (Params, error) {
1453	params := make(Params)
1454
1455	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1456	params["description"] = config.Description
1457
1458	return params, nil
1459}
1460
1461// GetStickerSetConfig allows you to get the stickers in a set.
1462type GetStickerSetConfig struct {
1463	Name string
1464}
1465
1466func (config GetStickerSetConfig) method() string {
1467	return "getStickerSet"
1468}
1469
1470func (config GetStickerSetConfig) params() (Params, error) {
1471	params := make(Params)
1472
1473	params["name"] = config.Name
1474
1475	return params, nil
1476}
1477
1478// UploadStickerConfig allows you to upload a sticker for use in a set later.
1479type UploadStickerConfig struct {
1480	UserID     int64
1481	PNGSticker interface{}
1482}
1483
1484func (config UploadStickerConfig) method() string {
1485	return "uploadStickerFile"
1486}
1487
1488func (config UploadStickerConfig) params() (Params, error) {
1489	params := make(Params)
1490
1491	params.AddNonZero64("user_id", config.UserID)
1492
1493	return params, nil
1494}
1495
1496func (config UploadStickerConfig) files() []RequestFile {
1497	return []RequestFile{{
1498		Name: "png_sticker",
1499		File: config.PNGSticker,
1500	}}
1501}
1502
1503// NewStickerSetConfig allows creating a new sticker set.
1504//
1505// You must set either PNGSticker or TGSSticker.
1506type NewStickerSetConfig struct {
1507	UserID        int64
1508	Name          string
1509	Title         string
1510	PNGSticker    interface{}
1511	TGSSticker    interface{}
1512	Emojis        string
1513	ContainsMasks bool
1514	MaskPosition  *MaskPosition
1515}
1516
1517func (config NewStickerSetConfig) method() string {
1518	return "createNewStickerSet"
1519}
1520
1521func (config NewStickerSetConfig) params() (Params, error) {
1522	params := make(Params)
1523
1524	params.AddNonZero64("user_id", config.UserID)
1525	params["name"] = config.Name
1526	params["title"] = config.Title
1527
1528	params["emojis"] = config.Emojis
1529
1530	params.AddBool("contains_masks", config.ContainsMasks)
1531
1532	err := params.AddInterface("mask_position", config.MaskPosition)
1533
1534	return params, err
1535}
1536
1537func (config NewStickerSetConfig) files() []RequestFile {
1538	if config.PNGSticker != nil {
1539		return []RequestFile{{
1540			Name: "png_sticker",
1541			File: config.PNGSticker,
1542		}}
1543	}
1544
1545	return []RequestFile{{
1546		Name: "tgs_sticker",
1547		File: config.TGSSticker,
1548	}}
1549}
1550
1551// AddStickerConfig allows you to add a sticker to a set.
1552type AddStickerConfig struct {
1553	UserID       int64
1554	Name         string
1555	PNGSticker   interface{}
1556	TGSSticker   interface{}
1557	Emojis       string
1558	MaskPosition *MaskPosition
1559}
1560
1561func (config AddStickerConfig) method() string {
1562	return "addStickerToSet"
1563}
1564
1565func (config AddStickerConfig) params() (Params, error) {
1566	params := make(Params)
1567
1568	params.AddNonZero64("user_id", config.UserID)
1569	params["name"] = config.Name
1570	params["emojis"] = config.Emojis
1571
1572	err := params.AddInterface("mask_position", config.MaskPosition)
1573
1574	return params, err
1575}
1576
1577func (config AddStickerConfig) files() []RequestFile {
1578	if config.PNGSticker != nil {
1579		return []RequestFile{{
1580			Name: "png_sticker",
1581			File: config.PNGSticker,
1582		}}
1583	}
1584
1585	return []RequestFile{{
1586		Name: "tgs_sticker",
1587		File: config.TGSSticker,
1588	}}
1589
1590}
1591
1592// SetStickerPositionConfig allows you to change the position of a sticker in a set.
1593type SetStickerPositionConfig struct {
1594	Sticker  string
1595	Position int
1596}
1597
1598func (config SetStickerPositionConfig) method() string {
1599	return "setStickerPositionInSet"
1600}
1601
1602func (config SetStickerPositionConfig) params() (Params, error) {
1603	params := make(Params)
1604
1605	params["sticker"] = config.Sticker
1606	params.AddNonZero("position", config.Position)
1607
1608	return params, nil
1609}
1610
1611// DeleteStickerConfig allows you to delete a sticker from a set.
1612type DeleteStickerConfig struct {
1613	Sticker string
1614}
1615
1616func (config DeleteStickerConfig) method() string {
1617	return "deleteStickerFromSet"
1618}
1619
1620func (config DeleteStickerConfig) params() (Params, error) {
1621	params := make(Params)
1622
1623	params["sticker"] = config.Sticker
1624
1625	return params, nil
1626}
1627
1628// SetStickerSetThumbConfig allows you to set the thumbnail for a sticker set.
1629type SetStickerSetThumbConfig struct {
1630	Name   string
1631	UserID int
1632	Thumb  interface{}
1633}
1634
1635func (config SetStickerSetThumbConfig) method() string {
1636	return "setStickerSetThumb"
1637}
1638
1639func (config SetStickerSetThumbConfig) params() (Params, error) {
1640	params := make(Params)
1641
1642	params["name"] = config.Name
1643	params.AddNonZero("user_id", config.UserID)
1644
1645	if thumb, ok := config.Thumb.(string); ok {
1646		params["thumb"] = thumb
1647	}
1648
1649	return params, nil
1650}
1651
1652func (config SetStickerSetThumbConfig) name() string {
1653	return "thumb"
1654}
1655
1656// SetChatStickerSetConfig allows you to set the sticker set for a supergroup.
1657type SetChatStickerSetConfig struct {
1658	ChatID             int64
1659	SuperGroupUsername string
1660
1661	StickerSetName string
1662}
1663
1664func (config SetChatStickerSetConfig) method() string {
1665	return "setChatStickerSet"
1666}
1667
1668func (config SetChatStickerSetConfig) params() (Params, error) {
1669	params := make(Params)
1670
1671	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1672	params["sticker_set_name"] = config.StickerSetName
1673
1674	return params, nil
1675}
1676
1677// DeleteChatStickerSetConfig allows you to remove a supergroup's sticker set.
1678type DeleteChatStickerSetConfig struct {
1679	ChatID             int64
1680	SuperGroupUsername string
1681}
1682
1683func (config DeleteChatStickerSetConfig) method() string {
1684	return "deleteChatStickerSet"
1685}
1686
1687func (config DeleteChatStickerSetConfig) params() (Params, error) {
1688	params := make(Params)
1689
1690	params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
1691
1692	return params, nil
1693}
1694
1695// MediaGroupConfig allows you to send a group of media.
1696//
1697// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo).
1698type MediaGroupConfig struct {
1699	ChatID          int64
1700	ChannelUsername string
1701
1702	Media               []interface{}
1703	DisableNotification bool
1704	ReplyToMessageID    int
1705}
1706
1707func (config MediaGroupConfig) method() string {
1708	return "sendMediaGroup"
1709}
1710
1711func (config MediaGroupConfig) params() (Params, error) {
1712	params := make(Params)
1713
1714	params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
1715	params.AddBool("disable_notification", config.DisableNotification)
1716	params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
1717
1718	err := params.AddInterface("media", prepareInputMediaForParams(config.Media))
1719
1720	return params, err
1721}
1722
1723func (config MediaGroupConfig) files() []RequestFile {
1724	return prepareInputMediaForFiles(config.Media)
1725}
1726
1727// DiceConfig allows you to send a random dice roll to Telegram.
1728//
1729// Emoji may be one of the following: 🎲 (1-6), 🎯 (1-6), 🏀 (1-5).
1730type DiceConfig struct {
1731	BaseChat
1732
1733	Emoji string
1734}
1735
1736func (config DiceConfig) method() string {
1737	return "sendDice"
1738}
1739
1740func (config DiceConfig) params() (Params, error) {
1741	params, err := config.BaseChat.params()
1742	if err != nil {
1743		return params, err
1744	}
1745
1746	params.AddNonEmpty("emoji", config.Emoji)
1747
1748	return params, err
1749}
1750
1751// GetMyCommandsConfig gets a list of the currently registered commands.
1752type GetMyCommandsConfig struct{}
1753
1754func (config GetMyCommandsConfig) method() string {
1755	return "getMyCommands"
1756}
1757
1758func (config GetMyCommandsConfig) params() (Params, error) {
1759	return make(Params), nil
1760}
1761
1762// SetMyCommandsConfig sets a list of commands the bot understands.
1763type SetMyCommandsConfig struct {
1764	commands []BotCommand
1765}
1766
1767func (config SetMyCommandsConfig) method() string {
1768	return "setMyCommands"
1769}
1770
1771func (config SetMyCommandsConfig) params() (Params, error) {
1772	params := make(Params)
1773
1774	err := params.AddInterface("commands", config.commands)
1775
1776	return params, err
1777}
1778
1779// prepareInputMediaParam evaluates a single InputMedia and determines if it
1780// needs to be modified for a successful upload. If it returns nil, then the
1781// value does not need to be included in the params. Otherwise, it will return
1782// the same type as was originally provided.
1783//
1784// The idx is used to calculate the file field name. If you only have a single
1785// file, 0 may be used. It is formatted into "attach://file-%d" for the primary
1786// media and "attach://file-%d-thumb" for thumbnails.
1787//
1788// It is expected to be used in conjunction with prepareInputMediaFile.
1789func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} {
1790	switch m := inputMedia.(type) {
1791	case InputMediaPhoto:
1792		switch m.Media.(type) {
1793		case string, FileBytes, FileReader:
1794			m.Media = fmt.Sprintf("attach://file-%d", idx)
1795		}
1796
1797		return m
1798	case InputMediaVideo:
1799		switch m.Media.(type) {
1800		case string, FileBytes, FileReader:
1801			m.Media = fmt.Sprintf("attach://file-%d", idx)
1802		}
1803
1804		switch m.Thumb.(type) {
1805		case string, FileBytes, FileReader:
1806			m.Thumb = fmt.Sprintf("attach://file-%d-thumb", idx)
1807		}
1808
1809		return m
1810	}
1811
1812	return nil
1813}
1814
1815// prepareInputMediaFile generates an array of RequestFile to provide for
1816// Fileable's files method. It returns an array as a single InputMedia may have
1817// multiple files, for the primary media and a thumbnail.
1818//
1819// The idx parameter is used to generate file field names. It uses the names
1820// "file-%d" for the main file and "file-%d-thumb" for the thumbnail.
1821//
1822// It is expected to be used in conjunction with prepareInputMediaParam.
1823func prepareInputMediaFile(inputMedia interface{}, idx int) []RequestFile {
1824	files := []RequestFile{}
1825
1826	switch m := inputMedia.(type) {
1827	case InputMediaPhoto:
1828		switch f := m.Media.(type) {
1829		case string, FileBytes, FileReader:
1830			files = append(files, RequestFile{
1831				Name: fmt.Sprintf("file-%d", idx),
1832				File: f,
1833			})
1834		}
1835	case InputMediaVideo:
1836		switch f := m.Media.(type) {
1837		case string, FileBytes, FileReader:
1838			files = append(files, RequestFile{
1839				Name: fmt.Sprintf("file-%d", idx),
1840				File: f,
1841			})
1842		}
1843
1844		switch f := m.Thumb.(type) {
1845		case string, FileBytes, FileReader:
1846			files = append(files, RequestFile{
1847				Name: fmt.Sprintf("file-%d-thumb", idx),
1848				File: f,
1849			})
1850		}
1851	}
1852
1853	return files
1854}
1855
1856// prepareInputMediaForParams calls prepareInputMediaParam for each item
1857// provided and returns a new array with the correct params for a request.
1858//
1859// It is expected that files will get data from the associated function,
1860// prepareInputMediaForFiles.
1861func prepareInputMediaForParams(inputMedia []interface{}) []interface{} {
1862	newMedia := make([]interface{}, len(inputMedia))
1863	copy(newMedia, inputMedia)
1864
1865	for idx, media := range inputMedia {
1866		if param := prepareInputMediaParam(media, idx); param != nil {
1867			newMedia[idx] = param
1868		}
1869	}
1870
1871	return newMedia
1872}
1873
1874// prepareInputMediaForFiles calls prepareInputMediaFile for each item
1875// provided and returns a new array with the correct files for a request.
1876//
1877// It is expected that params will get data from the associated function,
1878// prepareInputMediaForParams.
1879func prepareInputMediaForFiles(inputMedia []interface{}) []RequestFile {
1880	files := []RequestFile{}
1881
1882	for idx, media := range inputMedia {
1883		if file := prepareInputMediaFile(media, idx); file != nil {
1884			files = append(files, file...)
1885		}
1886	}
1887
1888	return files
1889}