all repos — telegram-bot-api @ 9e20459100a7dbf269c7d018373a5e376dd272e6

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