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