all repos — telegram-bot-api @ 8c46c3486831aeb42b07c9aa268ede3d06f090b8

Golang bindings for the Telegram Bot API

configs.go (view raw)

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