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 return v, err
204 }
205 v.Add("text", config.Text)
206 v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
207 if config.ParseMode != "" {
208 v.Add("parse_mode", config.ParseMode)
209 }
210
211 return v, nil
212}
213
214// method returns Telegram API method name for sending Message.
215func (config MessageConfig) method() string {
216 return "sendMessage"
217}
218
219// ForwardConfig contains information about a ForwardMessage request.
220type ForwardConfig struct {
221 BaseChat
222 FromChatID int64 // required
223 FromChannelUsername string
224 MessageID int // required
225}
226
227// values returns a url.Values representation of ForwardConfig.
228func (config ForwardConfig) values() (url.Values, error) {
229 v, err := config.BaseChat.values()
230 if err != nil {
231 return v, err
232 }
233 v.Add("from_chat_id", strconv.FormatInt(config.FromChatID, 10))
234 v.Add("message_id", strconv.Itoa(config.MessageID))
235 return v, nil
236}
237
238// method returns Telegram API method name for sending Forward.
239func (config ForwardConfig) method() string {
240 return "forwardMessage"
241}
242
243// PhotoConfig contains information about a SendPhoto request.
244type PhotoConfig struct {
245 BaseFile
246 Caption string
247}
248
249// Params returns a map[string]string representation of PhotoConfig.
250func (config PhotoConfig) params() (map[string]string, error) {
251 params, _ := config.BaseFile.params()
252
253 if config.Caption != "" {
254 params["caption"] = config.Caption
255 }
256
257 return params, nil
258}
259
260// Values returns a url.Values representation of PhotoConfig.
261func (config PhotoConfig) values() (url.Values, error) {
262 v, err := config.BaseChat.values()
263 if err != nil {
264 return v, err
265 }
266
267 v.Add(config.name(), config.FileID)
268 if config.Caption != "" {
269 v.Add("caption", config.Caption)
270 }
271 return v, nil
272}
273
274// name returns the field name for the Photo.
275func (config PhotoConfig) name() string {
276 return "photo"
277}
278
279// method returns Telegram API method name for sending Photo.
280func (config PhotoConfig) method() string {
281 return "sendPhoto"
282}
283
284// AudioConfig contains information about a SendAudio request.
285type AudioConfig struct {
286 BaseFile
287 Caption string
288 Duration int
289 Performer string
290 Title string
291}
292
293// values returns a url.Values representation of AudioConfig.
294func (config AudioConfig) values() (url.Values, error) {
295 v, err := config.BaseChat.values()
296 if err != nil {
297 return v, 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 return v, err
359 }
360
361 v.Add(config.name(), config.FileID)
362
363 return v, nil
364}
365
366// params returns a map[string]string representation of DocumentConfig.
367func (config DocumentConfig) params() (map[string]string, error) {
368 params, _ := config.BaseFile.params()
369
370 return params, nil
371}
372
373// name returns the field name for the Document.
374func (config DocumentConfig) name() string {
375 return "document"
376}
377
378// method returns Telegram API method name for sending Document.
379func (config DocumentConfig) method() string {
380 return "sendDocument"
381}
382
383// StickerConfig contains information about a SendSticker request.
384type StickerConfig struct {
385 BaseFile
386}
387
388// values returns a url.Values representation of StickerConfig.
389func (config StickerConfig) values() (url.Values, error) {
390 v, err := config.BaseChat.values()
391 if err != nil {
392 return v, err
393 }
394
395 v.Add(config.name(), config.FileID)
396
397 return v, nil
398}
399
400// params returns a map[string]string representation of StickerConfig.
401func (config StickerConfig) params() (map[string]string, error) {
402 params, _ := config.BaseFile.params()
403
404 return params, nil
405}
406
407// name returns the field name for the Sticker.
408func (config StickerConfig) name() string {
409 return "sticker"
410}
411
412// method returns Telegram API method name for sending Sticker.
413func (config StickerConfig) method() string {
414 return "sendSticker"
415}
416
417// VideoConfig contains information about a SendVideo request.
418type VideoConfig struct {
419 BaseFile
420 Duration int
421 Caption string
422}
423
424// values returns a url.Values representation of VideoConfig.
425func (config VideoConfig) values() (url.Values, error) {
426 v, err := config.BaseChat.values()
427 if err != nil {
428 return v, err
429 }
430
431 v.Add(config.name(), config.FileID)
432 if config.Duration != 0 {
433 v.Add("duration", strconv.Itoa(config.Duration))
434 }
435 if config.Caption != "" {
436 v.Add("caption", config.Caption)
437 }
438
439 return v, nil
440}
441
442// params returns a map[string]string representation of VideoConfig.
443func (config VideoConfig) params() (map[string]string, error) {
444 params, _ := config.BaseFile.params()
445
446 return params, nil
447}
448
449// name returns the field name for the Video.
450func (config VideoConfig) name() string {
451 return "video"
452}
453
454// method returns Telegram API method name for sending Video.
455func (config VideoConfig) method() string {
456 return "sendVideo"
457}
458
459// VoiceConfig contains information about a SendVoice request.
460type VoiceConfig struct {
461 BaseFile
462 Caption string
463 Duration int
464}
465
466// values returns a url.Values representation of VoiceConfig.
467func (config VoiceConfig) values() (url.Values, error) {
468 v, err := config.BaseChat.values()
469 if err != nil {
470 return v, err
471 }
472
473 v.Add(config.name(), config.FileID)
474 if config.Duration != 0 {
475 v.Add("duration", strconv.Itoa(config.Duration))
476 }
477 if config.Caption != "" {
478 v.Add("caption", config.Caption)
479 }
480
481 return v, nil
482}
483
484// params returns a map[string]string representation of VoiceConfig.
485func (config VoiceConfig) params() (map[string]string, error) {
486 params, _ := config.BaseFile.params()
487
488 if config.Duration != 0 {
489 params["duration"] = strconv.Itoa(config.Duration)
490 }
491 if config.Caption != "" {
492 params["caption"] = config.Caption
493 }
494
495 return params, nil
496}
497
498// name returns the field name for the Voice.
499func (config VoiceConfig) name() string {
500 return "voice"
501}
502
503// method returns Telegram API method name for sending Voice.
504func (config VoiceConfig) method() string {
505 return "sendVoice"
506}
507
508// LocationConfig contains information about a SendLocation request.
509type LocationConfig struct {
510 BaseChat
511 Latitude float64 // required
512 Longitude float64 // required
513}
514
515// values returns a url.Values representation of LocationConfig.
516func (config LocationConfig) values() (url.Values, error) {
517 v, err := config.BaseChat.values()
518 if err != nil {
519 return v, err
520 }
521
522 v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
523 v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
524
525 return v, nil
526}
527
528// method returns Telegram API method name for sending Location.
529func (config LocationConfig) method() string {
530 return "sendLocation"
531}
532
533// VenueConfig contains information about a SendVenue request.
534type VenueConfig struct {
535 BaseChat
536 Latitude float64 // required
537 Longitude float64 // required
538 Title string // required
539 Address string // required
540 FoursquareID string
541}
542
543func (config VenueConfig) values() (url.Values, error) {
544 v, err := config.BaseChat.values()
545 if err != nil {
546 return v, 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 return v, err
576 }
577
578 v.Add("phone_number", config.PhoneNumber)
579 v.Add("first_name", config.FirstName)
580 v.Add("last_name", config.LastName)
581
582 return v, nil
583}
584
585func (config ContactConfig) method() string {
586 return "sendContact"
587}
588
589// GameConfig allows you to send a game.
590type GameConfig struct {
591 BaseChat
592 GameShortName string
593}
594
595func (config GameConfig) values() (url.Values, error) {
596 v, err := config.BaseChat.values()
597 if err != nil {
598 return v, err
599 }
600
601 v.Add("game_short_name", config.GameShortName)
602
603 return v, nil
604}
605
606func (config GameConfig) method() string {
607 return "sendGame"
608}
609
610// SetGameScoreConfig allows you to update the game score in a chat.
611type SetGameScoreConfig struct {
612 UserID int
613 Score int
614 Force bool
615 DisableEditMessage bool
616 ChatID int
617 ChannelUsername string
618 MessageID int
619 InlineMessageID string
620}
621
622func (config SetGameScoreConfig) values() (url.Values, error) {
623 v := url.Values{}
624
625 v.Add("user_id", strconv.Itoa(config.UserID))
626 v.Add("score", strconv.Itoa(config.Score))
627 if config.InlineMessageID == "" {
628 if config.ChannelUsername == "" {
629 v.Add("chat_id", strconv.Itoa(config.ChatID))
630 } else {
631 v.Add("chat_id", config.ChannelUsername)
632 }
633 v.Add("message_id", strconv.Itoa(config.MessageID))
634 } else {
635 v.Add("inline_message_id", config.InlineMessageID)
636 }
637 v.Add("disable_edit_message", strconv.FormatBool(config.DisableEditMessage))
638
639 return v, nil
640}
641
642func (config SetGameScoreConfig) method() string {
643 return "setGameScore"
644}
645
646// GetGameHighScoresConfig allows you to fetch the high scores for a game.
647type GetGameHighScoresConfig struct {
648 UserID int
649 ChatID int
650 ChannelUsername string
651 MessageID int
652 InlineMessageID string
653}
654
655func (config GetGameHighScoresConfig) values() (url.Values, error) {
656 v := url.Values{}
657
658 v.Add("user_id", strconv.Itoa(config.UserID))
659 if config.InlineMessageID == "" {
660 if config.ChannelUsername == "" {
661 v.Add("chat_id", strconv.Itoa(config.ChatID))
662 } else {
663 v.Add("chat_id", config.ChannelUsername)
664 }
665 v.Add("message_id", strconv.Itoa(config.MessageID))
666 } else {
667 v.Add("inline_message_id", config.InlineMessageID)
668 }
669
670 return v, nil
671}
672
673func (config GetGameHighScoresConfig) method() string {
674 return "getGameHighScores"
675}
676
677// ChatActionConfig contains information about a SendChatAction request.
678type ChatActionConfig struct {
679 BaseChat
680 Action string // required
681}
682
683// values returns a url.Values representation of ChatActionConfig.
684func (config ChatActionConfig) values() (url.Values, error) {
685 v, err := config.BaseChat.values()
686 if err != nil {
687 return v, err
688 }
689 v.Add("action", config.Action)
690 return v, nil
691}
692
693// method returns Telegram API method name for sending ChatAction.
694func (config ChatActionConfig) method() string {
695 return "sendChatAction"
696}
697
698// EditMessageTextConfig allows you to modify the text in a message.
699type EditMessageTextConfig struct {
700 BaseEdit
701 Text string
702 ParseMode string
703 DisableWebPagePreview bool
704}
705
706func (config EditMessageTextConfig) values() (url.Values, error) {
707 v, err := config.BaseEdit.values()
708 if err != nil {
709 return v, err
710 }
711
712 v.Add("text", config.Text)
713 v.Add("parse_mode", config.ParseMode)
714 v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
715
716 return v, nil
717}
718
719func (config EditMessageTextConfig) method() string {
720 return "editMessageText"
721}
722
723// EditMessageCaptionConfig allows you to modify the caption of a message.
724type EditMessageCaptionConfig struct {
725 BaseEdit
726 Caption string
727}
728
729func (config EditMessageCaptionConfig) values() (url.Values, error) {
730 v, _ := config.BaseEdit.values()
731
732 v.Add("caption", config.Caption)
733
734 return v, nil
735}
736
737func (config EditMessageCaptionConfig) method() string {
738 return "editMessageCaption"
739}
740
741// EditMessageReplyMarkupConfig allows you to modify the reply markup
742// of a message.
743type EditMessageReplyMarkupConfig struct {
744 BaseEdit
745}
746
747func (config EditMessageReplyMarkupConfig) values() (url.Values, error) {
748 return config.BaseEdit.values()
749}
750
751func (config EditMessageReplyMarkupConfig) method() string {
752 return "editMessageReplyMarkup"
753}
754
755// UserProfilePhotosConfig contains information about a
756// GetUserProfilePhotos request.
757type UserProfilePhotosConfig struct {
758 UserID int
759 Offset int
760 Limit int
761}
762
763// FileConfig has information about a file hosted on Telegram.
764type FileConfig struct {
765 FileID string
766}
767
768// UpdateConfig contains information about a GetUpdates request.
769type UpdateConfig struct {
770 Offset int
771 Limit int
772 Timeout int
773}
774
775// WebhookConfig contains information about a SetWebhook request.
776type WebhookConfig struct {
777 URL *url.URL
778 Certificate interface{}
779}
780
781// FileBytes contains information about a set of bytes to upload
782// as a File.
783type FileBytes struct {
784 Name string
785 Bytes []byte
786}
787
788// FileReader contains information about a reader to upload as a File.
789// If Size is -1, it will read the entire Reader into memory to
790// calculate a Size.
791type FileReader struct {
792 Name string
793 Reader io.Reader
794 Size int64
795}
796
797// InlineConfig contains information on making an InlineQuery response.
798type InlineConfig struct {
799 InlineQueryID string `json:"inline_query_id"`
800 Results []interface{} `json:"results"`
801 CacheTime int `json:"cache_time"`
802 IsPersonal bool `json:"is_personal"`
803 NextOffset string `json:"next_offset"`
804 SwitchPMText string `json:"switch_pm_text"`
805 SwitchPMParameter string `json:"switch_pm_parameter"`
806}
807
808// CallbackConfig contains information on making a CallbackQuery response.
809type CallbackConfig struct {
810 CallbackQueryID string `json:"callback_query_id"`
811 Text string `json:"text"`
812 ShowAlert bool `json:"show_alert"`
813 URL string `json:"url"`
814 CacheTime int `json:"cache_time"`
815}
816
817// ChatMemberConfig contains information about a user in a chat for use
818// with administrative functions such as kicking or unbanning a user.
819type ChatMemberConfig struct {
820 ChatID int64
821 SuperGroupUsername string
822 UserID int
823}
824
825// ChatConfig contains information about getting information on a chat.
826type ChatConfig struct {
827 ChatID int64
828 SuperGroupUsername string
829}
830
831// ChatConfigWithUser contains information about getting information on
832// a specific user within a chat.
833type ChatConfigWithUser struct {
834 ChatID int64
835 SuperGroupUsername string
836 UserID int
837}