all repos — telegram-bot-api @ fb1de2fb48ddd996b71aac24ec4aa2f5d87a9c31

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