leobot

Simple Telegram Logging Bot
git clone git://bsandro.tech/leobot
Log | Files | Refs | README | LICENSE

configs.go (63985B)


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