configs.go (view raw)
1package tgbotapi
2
3import (
4 "encoding/json"
5 "io"
6 "net/url"
7 "strconv"
8)
9
10// Telegram constants
11const (
12 // APIEndpoint is the endpoint for all API methods,
13 // with formatting for Sprintf.
14 APIEndpoint = "https://api.telegram.org/bot%s/%s"
15 // FileEndpoint is the endpoint for downloading a file from Telegram.
16 FileEndpoint = "https://api.telegram.org/file/bot%s/%s"
17)
18
19// Constant values for ChatActions
20const (
21 ChatTyping = "typing"
22 ChatUploadPhoto = "upload_photo"
23 ChatRecordVideo = "record_video"
24 ChatUploadVideo = "upload_video"
25 ChatRecordAudio = "record_audio"
26 ChatUploadAudio = "upload_audio"
27 ChatUploadDocument = "upload_document"
28 ChatFindLocation = "find_location"
29)
30
31// API errors
32const (
33 // ErrAPIForbidden happens when a token is bad
34 ErrAPIForbidden = "forbidden"
35)
36
37// Constant values for ParseMode in MessageConfig
38const (
39 ModeMarkdown = "Markdown"
40 ModeHTML = "HTML"
41)
42
43// Library errors
44const (
45 // ErrBadFileType happens when you pass an unknown type
46 ErrBadFileType = "bad file type"
47 ErrBadURL = "bad or empty url"
48)
49
50// Chattable is any config type that can be sent.
51type Chattable interface {
52 values() (url.Values, error)
53 method() string
54}
55
56// Fileable is any config type that can be sent that includes a file.
57type Fileable interface {
58 Chattable
59 params() (map[string]string, error)
60 name() string
61 getFile() interface{}
62 useExistingFile() bool
63}
64
65// BaseChat is base type for all chat config types.
66type BaseChat struct {
67 ChatID int64 // required
68 ChannelUsername string
69 ReplyToMessageID int
70 ReplyMarkup interface{}
71 DisableNotification bool
72}
73
74// values returns url.Values representation of BaseChat
75func (chat *BaseChat) values() (url.Values, error) {
76 v := url.Values{}
77 if chat.ChannelUsername != "" {
78 v.Add("chat_id", chat.ChannelUsername)
79 } else {
80 v.Add("chat_id", strconv.FormatInt(chat.ChatID, 10))
81 }
82
83 if chat.ReplyToMessageID != 0 {
84 v.Add("reply_to_message_id", strconv.Itoa(chat.ReplyToMessageID))
85 }
86
87 if chat.ReplyMarkup != nil {
88 data, err := json.Marshal(chat.ReplyMarkup)
89 if err != nil {
90 return v, err
91 }
92
93 v.Add("reply_markup", string(data))
94 }
95
96 v.Add("disable_notification", strconv.FormatBool(chat.DisableNotification))
97
98 return v, nil
99}
100
101// BaseFile is a base type for all file config types.
102type BaseFile struct {
103 BaseChat
104 File interface{}
105 FileID string
106 UseExisting bool
107 MimeType string
108 FileSize int
109}
110
111// params returns a map[string]string representation of BaseFile.
112func (file BaseFile) params() (map[string]string, error) {
113 params := make(map[string]string)
114
115 if file.ChannelUsername != "" {
116 params["chat_id"] = file.ChannelUsername
117 } else {
118 params["chat_id"] = strconv.FormatInt(file.ChatID, 10)
119 }
120
121 if file.ReplyToMessageID != 0 {
122 params["reply_to_message_id"] = strconv.Itoa(file.ReplyToMessageID)
123 }
124
125 if file.ReplyMarkup != nil {
126 data, err := json.Marshal(file.ReplyMarkup)
127 if err != nil {
128 return params, err
129 }
130
131 params["reply_markup"] = string(data)
132 }
133
134 if file.MimeType != "" {
135 params["mime_type"] = file.MimeType
136 }
137
138 if file.FileSize > 0 {
139 params["file_size"] = strconv.Itoa(file.FileSize)
140 }
141
142 params["disable_notification"] = strconv.FormatBool(file.DisableNotification)
143
144 return params, nil
145}
146
147// getFile returns the file.
148func (file BaseFile) getFile() interface{} {
149 return file.File
150}
151
152// useExistingFile returns if the BaseFile has already been uploaded.
153func (file BaseFile) useExistingFile() bool {
154 return file.UseExisting
155}
156
157// BaseEdit is base type of all chat edits.
158type BaseEdit struct {
159 ChatID int64
160 ChannelUsername string
161 MessageID int
162 InlineMessageID string
163 ReplyMarkup *InlineKeyboardMarkup
164}
165
166func (edit BaseEdit) values() (url.Values, error) {
167 v := url.Values{}
168
169 if edit.InlineMessageID == "" {
170 if edit.ChannelUsername != "" {
171 v.Add("chat_id", edit.ChannelUsername)
172 } else {
173 v.Add("chat_id", strconv.FormatInt(edit.ChatID, 10))
174 }
175 v.Add("message_id", strconv.Itoa(edit.MessageID))
176 } else {
177 v.Add("inline_message_id", edit.InlineMessageID)
178 }
179
180 if edit.ReplyMarkup != nil {
181 data, err := json.Marshal(edit.ReplyMarkup)
182 if err != nil {
183 return v, err
184 }
185 v.Add("reply_markup", string(data))
186 }
187
188 return v, nil
189}
190
191// MessageConfig contains information about a SendMessage request.
192type MessageConfig struct {
193 BaseChat
194 Text string
195 ParseMode string
196 DisableWebPagePreview bool
197}
198
199// values returns a url.Values representation of MessageConfig.
200func (config MessageConfig) values() (url.Values, error) {
201 v, err := config.BaseChat.values()
202 if err != nil {
203 data := url.Values{}
204 return data, err
205 }
206 v.Add("text", config.Text)
207 v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
208 if config.ParseMode != "" {
209 v.Add("parse_mode", config.ParseMode)
210 }
211
212 return v, nil
213}
214
215// method returns Telegram API method name for sending Message.
216func (config MessageConfig) method() string {
217 return "sendMessage"
218}
219
220// ForwardConfig contains information about a ForwardMessage request.
221type ForwardConfig struct {
222 BaseChat
223 FromChatID int64 // required
224 FromChannelUsername string
225 MessageID int // required
226}
227
228// values returns a url.Values representation of ForwardConfig.
229func (config ForwardConfig) values() (url.Values, error) {
230 v, err := config.BaseChat.values()
231 if err != nil {
232 data := url.Values{}
233 return data, err
234 }
235 v.Add("from_chat_id", strconv.FormatInt(config.FromChatID, 10))
236 v.Add("message_id", strconv.Itoa(config.MessageID))
237 return v, nil
238}
239
240// method returns Telegram API method name for sending Forward.
241func (config ForwardConfig) method() string {
242 return "forwardMessage"
243}
244
245// PhotoConfig contains information about a SendPhoto request.
246type PhotoConfig struct {
247 BaseFile
248 Caption string
249}
250
251// Params returns a map[string]string representation of PhotoConfig.
252func (config PhotoConfig) params() (map[string]string, error) {
253 params, _ := config.BaseFile.params()
254
255 if config.Caption != "" {
256 params["caption"] = config.Caption
257 }
258
259 return params, nil
260}
261
262// Values returns a url.Values representation of PhotoConfig.
263func (config PhotoConfig) values() (url.Values, error) {
264 v, _ := config.BaseChat.values()
265
266 v.Add(config.name(), config.FileID)
267 if config.Caption != "" {
268 v.Add("caption", config.Caption)
269 }
270 return v, nil
271}
272
273// name returns the field name for the Photo.
274func (config PhotoConfig) name() string {
275 return "photo"
276}
277
278// method returns Telegram API method name for sending Photo.
279func (config PhotoConfig) method() string {
280 return "sendPhoto"
281}
282
283// AudioConfig contains information about a SendAudio request.
284type AudioConfig struct {
285 BaseFile
286 Caption string
287 Duration int
288 Performer string
289 Title string
290}
291
292// values returns a url.Values representation of AudioConfig.
293func (config AudioConfig) values() (url.Values, error) {
294 v, err := config.BaseChat.values()
295 if err != nil {
296 data := url.Values{}
297 return data, err
298 }
299
300 v.Add(config.name(), config.FileID)
301 if config.Duration != 0 {
302 v.Add("duration", strconv.Itoa(config.Duration))
303 }
304
305 if config.Performer != "" {
306 v.Add("performer", config.Performer)
307 }
308 if config.Title != "" {
309 v.Add("title", config.Title)
310 }
311 if config.Caption != "" {
312 v.Add("caption", config.Caption)
313 }
314
315 return v, nil
316}
317
318// params returns a map[string]string representation of AudioConfig.
319func (config AudioConfig) params() (map[string]string, error) {
320 params, _ := config.BaseFile.params()
321
322 if config.Duration != 0 {
323 params["duration"] = strconv.Itoa(config.Duration)
324 }
325
326 if config.Performer != "" {
327 params["performer"] = config.Performer
328 }
329 if config.Title != "" {
330 params["title"] = config.Title
331 }
332 if config.Caption != "" {
333 params["caption"] = config.Caption
334 }
335
336 return params, nil
337}
338
339// name returns the field name for the Audio.
340func (config AudioConfig) name() string {
341 return "audio"
342}
343
344// method returns Telegram API method name for sending Audio.
345func (config AudioConfig) method() string {
346 return "sendAudio"
347}
348
349// DocumentConfig contains information about a SendDocument request.
350type DocumentConfig struct {
351 BaseFile
352}
353
354// values returns a url.Values representation of DocumentConfig.
355func (config DocumentConfig) values() (url.Values, error) {
356 v, err := config.BaseChat.values()
357 if err != nil {
358 data := url.Values{}
359 return data, err
360 }
361
362 v.Add(config.name(), config.FileID)
363
364 return v, nil
365}
366
367// params returns a map[string]string representation of DocumentConfig.
368func (config DocumentConfig) params() (map[string]string, error) {
369 params, _ := config.BaseFile.params()
370
371 return params, nil
372}
373
374// name returns the field name for the Document.
375func (config DocumentConfig) name() string {
376 return "document"
377}
378
379// method returns Telegram API method name for sending Document.
380func (config DocumentConfig) method() string {
381 return "sendDocument"
382}
383
384// StickerConfig contains information about a SendSticker request.
385type StickerConfig struct {
386 BaseFile
387}
388
389// values returns a url.Values representation of StickerConfig.
390func (config StickerConfig) values() (url.Values, error) {
391 v, err := config.BaseChat.values()
392 if err != nil {
393 data := url.Values{}
394 return data, err
395 }
396
397 v.Add(config.name(), config.FileID)
398
399 return v, nil
400}
401
402// params returns a map[string]string representation of StickerConfig.
403func (config StickerConfig) params() (map[string]string, error) {
404 params, _ := config.BaseFile.params()
405
406 return params, nil
407}
408
409// name returns the field name for the Sticker.
410func (config StickerConfig) name() string {
411 return "sticker"
412}
413
414// method returns Telegram API method name for sending Sticker.
415func (config StickerConfig) method() string {
416 return "sendSticker"
417}
418
419// VideoConfig contains information about a SendVideo request.
420type VideoConfig struct {
421 BaseFile
422 Duration int
423 Caption string
424}
425
426// values returns a url.Values representation of VideoConfig.
427func (config VideoConfig) values() (url.Values, error) {
428 v, err := config.BaseChat.values()
429 if err != nil {
430 data := url.Values{}
431 return data, err
432 }
433
434 v.Add(config.name(), config.FileID)
435 if config.Duration != 0 {
436 v.Add("duration", strconv.Itoa(config.Duration))
437 }
438 if config.Caption != "" {
439 v.Add("caption", config.Caption)
440 }
441
442 return v, nil
443}
444
445// params returns a map[string]string representation of VideoConfig.
446func (config VideoConfig) params() (map[string]string, error) {
447 params, _ := config.BaseFile.params()
448
449 return params, nil
450}
451
452// name returns the field name for the Video.
453func (config VideoConfig) name() string {
454 return "video"
455}
456
457// method returns Telegram API method name for sending Video.
458func (config VideoConfig) method() string {
459 return "sendVideo"
460}
461
462// VoiceConfig contains information about a SendVoice request.
463type VoiceConfig struct {
464 BaseFile
465 Caption string
466 Duration int
467}
468
469// values returns a url.Values representation of VoiceConfig.
470func (config VoiceConfig) values() (url.Values, error) {
471 v, err := config.BaseChat.values()
472 if err != nil {
473 data := url.Values{}
474 return data, err
475 }
476
477 v.Add(config.name(), config.FileID)
478 if config.Duration != 0 {
479 v.Add("duration", strconv.Itoa(config.Duration))
480 }
481
482 return v, nil
483}
484
485// params returns a map[string]string representation of VoiceConfig.
486func (config VoiceConfig) params() (map[string]string, error) {
487 params, _ := config.BaseFile.params()
488
489 if config.Duration != 0 {
490 params["duration"] = strconv.Itoa(config.Duration)
491 }
492
493 return params, nil
494}
495
496// name returns the field name for the Voice.
497func (config VoiceConfig) name() string {
498 return "voice"
499}
500
501// method returns Telegram API method name for sending Voice.
502func (config VoiceConfig) method() string {
503 return "sendVoice"
504}
505
506// LocationConfig contains information about a SendLocation request.
507type LocationConfig struct {
508 BaseChat
509 Latitude float64 // required
510 Longitude float64 // required
511}
512
513// values returns a url.Values representation of LocationConfig.
514func (config LocationConfig) values() (url.Values, error) {
515 v, err := config.BaseChat.values()
516 if err != nil {
517 data := url.Values{}
518 return data, err
519 }
520
521 v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
522 v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
523
524 return v, nil
525}
526
527// method returns Telegram API method name for sending Location.
528func (config LocationConfig) method() string {
529 return "sendLocation"
530}
531
532// VenueConfig contains information about a SendVenue request.
533type VenueConfig struct {
534 BaseChat
535 Latitude float64 // required
536 Longitude float64 // required
537 Title string // required
538 Address string // required
539 FoursquareID string
540}
541
542func (config VenueConfig) values() (url.Values, error) {
543 v, err := config.BaseChat.values()
544 if err != nil {
545 data := url.Values{}
546 return data, err
547 }
548
549 v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
550 v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
551 v.Add("title", config.Title)
552 v.Add("address", config.Address)
553 if config.FoursquareID != "" {
554 v.Add("foursquare_id", config.FoursquareID)
555 }
556
557 return v, nil
558}
559
560func (config VenueConfig) method() string {
561 return "sendVenue"
562}
563
564// ContactConfig allows you to send a contact.
565type ContactConfig struct {
566 BaseChat
567 PhoneNumber string
568 FirstName string
569 LastName string
570}
571
572func (config ContactConfig) values() (url.Values, error) {
573 v, err := config.BaseChat.values()
574 if err != nil {
575 data := url.Values{}
576 return data, err
577 }
578
579 v.Add("phone_number", config.PhoneNumber)
580 v.Add("first_name", config.FirstName)
581 v.Add("last_name", config.LastName)
582
583 return v, nil
584}
585
586func (config ContactConfig) method() string {
587 return "sendContact"
588}
589
590// GameConfig allows you to send a game.
591type GameConfig struct {
592 BaseChat
593 GameShortName string
594}
595
596func (config GameConfig) values() (url.Values, error) {
597 v, err := config.BaseChat.values()
598 if err != nil {
599 data := url.Values{}
600 return data, err
601 }
602
603 v.Add("game_short_name", config.GameShortName)
604
605 return v, nil
606}
607
608func (config GameConfig) method() string {
609 return "sendGame"
610}
611
612// SetGameScoreConfig allows you to update the game score in a chat.
613type SetGameScoreConfig struct {
614 UserID int
615 Score int
616 Force bool
617 DisableEditMessage bool
618 ChatID int
619 ChannelUsername string
620 MessageID int
621 InlineMessageID string
622}
623
624func (config SetGameScoreConfig) values() (url.Values, error) {
625 v := url.Values{}
626
627 v.Add("user_id", strconv.Itoa(config.UserID))
628 v.Add("score", strconv.Itoa(config.Score))
629 if config.InlineMessageID == "" {
630 if config.ChannelUsername == "" {
631 v.Add("chat_id", strconv.Itoa(config.ChatID))
632 } else {
633 v.Add("chat_id", config.ChannelUsername)
634 }
635 v.Add("message_id", strconv.Itoa(config.MessageID))
636 } else {
637 v.Add("inline_message_id", config.InlineMessageID)
638 }
639 v.Add("disable_edit_message", strconv.FormatBool(config.DisableEditMessage))
640
641 return v, nil
642}
643
644func (config SetGameScoreConfig) method() string {
645 return "setGameScore"
646}
647
648// GetGameHighScoresConfig allows you to fetch the high scores for a game.
649type GetGameHighScoresConfig struct {
650 UserID int
651 ChatID int
652 ChannelUsername string
653 MessageID int
654 InlineMessageID string
655}
656
657func (config GetGameHighScoresConfig) values() (url.Values, error) {
658 v := url.Values{}
659
660 v.Add("user_id", strconv.Itoa(config.UserID))
661 if config.InlineMessageID == "" {
662 if config.ChannelUsername == "" {
663 v.Add("chat_id", strconv.Itoa(config.ChatID))
664 } else {
665 v.Add("chat_id", config.ChannelUsername)
666 }
667 v.Add("message_id", strconv.Itoa(config.MessageID))
668 } else {
669 v.Add("inline_message_id", config.InlineMessageID)
670 }
671
672 return v, nil
673}
674
675func (config GetGameHighScoresConfig) method() string {
676 return "getGameHighScores"
677}
678
679// ChatActionConfig contains information about a SendChatAction request.
680type ChatActionConfig struct {
681 BaseChat
682 Action string // required
683}
684
685// values returns a url.Values representation of ChatActionConfig.
686func (config ChatActionConfig) values() (url.Values, error) {
687 v, err := config.BaseChat.values()
688 if err != nil {
689 data := url.Values{}
690 return data, err
691 }
692 v.Add("action", config.Action)
693 return v, nil
694}
695
696// method returns Telegram API method name for sending ChatAction.
697func (config ChatActionConfig) method() string {
698 return "sendChatAction"
699}
700
701// EditMessageTextConfig allows you to modify the text in a message.
702type EditMessageTextConfig struct {
703 BaseEdit
704 Text string
705 ParseMode string
706 DisableWebPagePreview bool
707}
708
709func (config EditMessageTextConfig) values() (url.Values, error) {
710 v, err := config.BaseEdit.values()
711 if err != nil {
712 data := url.Values{}
713 return data, err
714 }
715
716 v.Add("text", config.Text)
717 v.Add("parse_mode", config.ParseMode)
718 v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
719
720 return v, nil
721}
722
723func (config EditMessageTextConfig) method() string {
724 return "editMessageText"
725}
726
727// EditMessageCaptionConfig allows you to modify the caption of a message.
728type EditMessageCaptionConfig struct {
729 BaseEdit
730 Caption string
731}
732
733func (config EditMessageCaptionConfig) values() (url.Values, error) {
734 v, _ := config.BaseEdit.values()
735
736 v.Add("caption", config.Caption)
737
738 return v, nil
739}
740
741func (config EditMessageCaptionConfig) method() string {
742 return "editMessageCaption"
743}
744
745// EditMessageReplyMarkupConfig allows you to modify the reply markup
746// of a message.
747type EditMessageReplyMarkupConfig struct {
748 BaseEdit
749}
750
751func (config EditMessageReplyMarkupConfig) values() (url.Values, error) {
752 return config.BaseEdit.values()
753}
754
755func (config EditMessageReplyMarkupConfig) method() string {
756 return "editMessageReplyMarkup"
757}
758
759// UserProfilePhotosConfig contains information about a
760// GetUserProfilePhotos request.
761type UserProfilePhotosConfig struct {
762 UserID int
763 Offset int
764 Limit int
765}
766
767// FileConfig has information about a file hosted on Telegram.
768type FileConfig struct {
769 FileID string
770}
771
772// UpdateConfig contains information about a GetUpdates request.
773type UpdateConfig struct {
774 Offset int
775 Limit int
776 Timeout int
777}
778
779// WebhookConfig contains information about a SetWebhook request.
780type WebhookConfig struct {
781 URL *url.URL
782 Certificate interface{}
783}
784
785// FileBytes contains information about a set of bytes to upload
786// as a File.
787type FileBytes struct {
788 Name string
789 Bytes []byte
790}
791
792// FileReader contains information about a reader to upload as a File.
793// If Size is -1, it will read the entire Reader into memory to
794// calculate a Size.
795type FileReader struct {
796 Name string
797 Reader io.Reader
798 Size int64
799}
800
801// InlineConfig contains information on making an InlineQuery response.
802type InlineConfig struct {
803 InlineQueryID string `json:"inline_query_id"`
804 Results []interface{} `json:"results"`
805 CacheTime int `json:"cache_time"`
806 IsPersonal bool `json:"is_personal"`
807 NextOffset string `json:"next_offset"`
808 SwitchPMText string `json:"switch_pm_text"`
809 SwitchPMParameter string `json:"switch_pm_parameter"`
810}
811
812// CallbackConfig contains information on making a CallbackQuery response.
813type CallbackConfig struct {
814 CallbackQueryID string `json:"callback_query_id"`
815 Text string `json:"text"`
816 ShowAlert bool `json:"show_alert"`
817 URL string `json:"url"`
818 CacheTime int `json:"cache_time"`
819}
820
821// ChatMemberConfig contains information about a user in a chat for use
822// with administrative functions such as kicking or unbanning a user.
823type ChatMemberConfig struct {
824 ChatID int64
825 SuperGroupUsername string
826 UserID int
827}
828
829// ChatConfig contains information about getting information on a chat.
830type ChatConfig struct {
831 ChatID int64
832 SuperGroupUsername string
833}
834
835// ChatConfigWithUser contains information about getting information on
836// a specific user within a chat.
837type ChatConfigWithUser struct {
838 ChatID int64
839 SuperGroupUsername string
840 UserID int
841}