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