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	ParseMode string
248}
249
250// Params returns a map[string]string representation of PhotoConfig.
251func (config PhotoConfig) params() (map[string]string, error) {
252	params, _ := config.BaseFile.params()
253
254	if config.Caption != "" {
255		params["caption"] = config.Caption
256		if config.ParseMode != "" {
257			params["parse_mode"] = config.ParseMode
258		}
259	}
260
261	return params, nil
262}
263
264// Values returns a url.Values representation of PhotoConfig.
265func (config PhotoConfig) values() (url.Values, error) {
266	v, err := config.BaseChat.values()
267	if err != nil {
268		return v, err
269	}
270
271	v.Add(config.name(), config.FileID)
272	if config.Caption != "" {
273		v.Add("caption", config.Caption)
274		if config.ParseMode != "" {
275			v.Add("parse_mode", config.ParseMode)
276		}
277	}
278
279	return v, nil
280}
281
282// name returns the field name for the Photo.
283func (config PhotoConfig) name() string {
284	return "photo"
285}
286
287// method returns Telegram API method name for sending Photo.
288func (config PhotoConfig) method() string {
289	return "sendPhoto"
290}
291
292// AudioConfig contains information about a SendAudio request.
293type AudioConfig struct {
294	BaseFile
295	Caption   string
296	ParseMode string
297	Duration  int
298	Performer string
299	Title     string
300}
301
302// values returns a url.Values representation of AudioConfig.
303func (config AudioConfig) values() (url.Values, error) {
304	v, err := config.BaseChat.values()
305	if err != nil {
306		return v, err
307	}
308
309	v.Add(config.name(), config.FileID)
310	if config.Duration != 0 {
311		v.Add("duration", strconv.Itoa(config.Duration))
312	}
313
314	if config.Performer != "" {
315		v.Add("performer", config.Performer)
316	}
317	if config.Title != "" {
318		v.Add("title", config.Title)
319	}
320	if config.Caption != "" {
321		v.Add("caption", config.Caption)
322		if config.ParseMode != "" {
323			v.Add("parse_mode", config.ParseMode)
324		}
325	}
326
327	return v, nil
328}
329
330// params returns a map[string]string representation of AudioConfig.
331func (config AudioConfig) params() (map[string]string, error) {
332	params, _ := config.BaseFile.params()
333
334	if config.Duration != 0 {
335		params["duration"] = strconv.Itoa(config.Duration)
336	}
337
338	if config.Performer != "" {
339		params["performer"] = config.Performer
340	}
341	if config.Title != "" {
342		params["title"] = config.Title
343	}
344	if config.Caption != "" {
345		params["caption"] = config.Caption
346		if config.ParseMode != "" {
347			params["parse_mode"] = config.ParseMode
348		}
349	}
350
351	return params, nil
352}
353
354// name returns the field name for the Audio.
355func (config AudioConfig) name() string {
356	return "audio"
357}
358
359// method returns Telegram API method name for sending Audio.
360func (config AudioConfig) method() string {
361	return "sendAudio"
362}
363
364// DocumentConfig contains information about a SendDocument request.
365type DocumentConfig struct {
366	BaseFile
367	Caption   string
368	ParseMode string
369}
370
371// values returns a url.Values representation of DocumentConfig.
372func (config DocumentConfig) values() (url.Values, error) {
373	v, err := config.BaseChat.values()
374	if err != nil {
375		return v, err
376	}
377
378	v.Add(config.name(), config.FileID)
379	if config.Caption != "" {
380		v.Add("caption", config.Caption)
381		if config.ParseMode != "" {
382			v.Add("parse_mode", config.ParseMode)
383		}
384	}
385
386	return v, nil
387}
388
389// params returns a map[string]string representation of DocumentConfig.
390func (config DocumentConfig) params() (map[string]string, error) {
391	params, _ := config.BaseFile.params()
392
393	if config.Caption != "" {
394		params["caption"] = config.Caption
395		if config.ParseMode != "" {
396			params["parse_mode"] = config.ParseMode
397		}
398	}
399
400	return params, nil
401}
402
403// name returns the field name for the Document.
404func (config DocumentConfig) name() string {
405	return "document"
406}
407
408// method returns Telegram API method name for sending Document.
409func (config DocumentConfig) method() string {
410	return "sendDocument"
411}
412
413// StickerConfig contains information about a SendSticker request.
414type StickerConfig struct {
415	BaseFile
416}
417
418// values returns a url.Values representation of StickerConfig.
419func (config StickerConfig) values() (url.Values, error) {
420	v, err := config.BaseChat.values()
421	if err != nil {
422		return v, err
423	}
424
425	v.Add(config.name(), config.FileID)
426
427	return v, nil
428}
429
430// params returns a map[string]string representation of StickerConfig.
431func (config StickerConfig) params() (map[string]string, error) {
432	params, _ := config.BaseFile.params()
433
434	return params, nil
435}
436
437// name returns the field name for the Sticker.
438func (config StickerConfig) name() string {
439	return "sticker"
440}
441
442// method returns Telegram API method name for sending Sticker.
443func (config StickerConfig) method() string {
444	return "sendSticker"
445}
446
447// VideoConfig contains information about a SendVideo request.
448type VideoConfig struct {
449	BaseFile
450	Duration  int
451	Caption   string
452	ParseMode string
453}
454
455// values returns a url.Values representation of VideoConfig.
456func (config VideoConfig) values() (url.Values, error) {
457	v, err := config.BaseChat.values()
458	if err != nil {
459		return v, err
460	}
461
462	v.Add(config.name(), config.FileID)
463	if config.Duration != 0 {
464		v.Add("duration", strconv.Itoa(config.Duration))
465	}
466	if config.Caption != "" {
467		v.Add("caption", config.Caption)
468		if config.ParseMode != "" {
469			v.Add("parse_mode", config.ParseMode)
470		}
471	}
472
473	return v, nil
474}
475
476// params returns a map[string]string representation of VideoConfig.
477func (config VideoConfig) params() (map[string]string, error) {
478	params, _ := config.BaseFile.params()
479
480	if config.Caption != "" {
481		params["caption"] = config.Caption
482		if config.ParseMode != "" {
483			params["parse_mode"] = config.ParseMode
484		}
485	}
486
487	return params, nil
488}
489
490// name returns the field name for the Video.
491func (config VideoConfig) name() string {
492	return "video"
493}
494
495// method returns Telegram API method name for sending Video.
496func (config VideoConfig) method() string {
497	return "sendVideo"
498}
499
500// AnimationConfig contains information about a SendAnimation request.
501type AnimationConfig struct {
502	BaseFile
503	Duration  int
504	Caption   string
505	ParseMode string
506}
507
508// values returns a url.Values representation of AnimationConfig.
509func (config AnimationConfig) values() (url.Values, error) {
510	v, err := config.BaseChat.values()
511	if err != nil {
512		return v, err
513	}
514
515	v.Add(config.name(), config.FileID)
516	if config.Duration != 0 {
517		v.Add("duration", strconv.Itoa(config.Duration))
518	}
519	if config.Caption != "" {
520		v.Add("caption", config.Caption)
521		if config.ParseMode != "" {
522			v.Add("parse_mode", config.ParseMode)
523		}
524	}
525
526	return v, nil
527}
528
529// params returns a map[string]string representation of AnimationConfig.
530func (config AnimationConfig) params() (map[string]string, error) {
531	params, _ := config.BaseFile.params()
532
533	if config.Caption != "" {
534		params["caption"] = config.Caption
535		if config.ParseMode != "" {
536			params["parse_mode"] = config.ParseMode
537		}
538	}
539
540	return params, nil
541}
542
543// name returns the field name for the Animation.
544func (config AnimationConfig) name() string {
545	return "animation"
546}
547
548// method returns Telegram API method name for sending Animation.
549func (config AnimationConfig) method() string {
550	return "sendAnimation"
551}
552
553// VideoNoteConfig contains information about a SendVideoNote request.
554type VideoNoteConfig struct {
555	BaseFile
556	Duration int
557	Length   int
558}
559
560// values returns a url.Values representation of VideoNoteConfig.
561func (config VideoNoteConfig) values() (url.Values, error) {
562	v, err := config.BaseChat.values()
563	if err != nil {
564		return v, err
565	}
566
567	v.Add(config.name(), config.FileID)
568	if config.Duration != 0 {
569		v.Add("duration", strconv.Itoa(config.Duration))
570	}
571
572	// Telegram API seems to have a bug, if no length is provided or it is 0, it will send an error response
573	if config.Length != 0 {
574		v.Add("length", strconv.Itoa(config.Length))
575	}
576
577	return v, nil
578}
579
580// params returns a map[string]string representation of VideoNoteConfig.
581func (config VideoNoteConfig) params() (map[string]string, error) {
582	params, _ := config.BaseFile.params()
583
584	if config.Length != 0 {
585		params["length"] = strconv.Itoa(config.Length)
586	}
587	if config.Duration != 0 {
588		params["duration"] = strconv.Itoa(config.Duration)
589	}
590
591	return params, nil
592}
593
594// name returns the field name for the VideoNote.
595func (config VideoNoteConfig) name() string {
596	return "video_note"
597}
598
599// method returns Telegram API method name for sending VideoNote.
600func (config VideoNoteConfig) method() string {
601	return "sendVideoNote"
602}
603
604// VoiceConfig contains information about a SendVoice request.
605type VoiceConfig struct {
606	BaseFile
607	Caption   string
608	ParseMode string
609	Duration  int
610}
611
612// values returns a url.Values representation of VoiceConfig.
613func (config VoiceConfig) values() (url.Values, error) {
614	v, err := config.BaseChat.values()
615	if err != nil {
616		return v, err
617	}
618
619	v.Add(config.name(), config.FileID)
620	if config.Duration != 0 {
621		v.Add("duration", strconv.Itoa(config.Duration))
622	}
623	if config.Caption != "" {
624		v.Add("caption", config.Caption)
625		if config.ParseMode != "" {
626			v.Add("parse_mode", config.ParseMode)
627		}
628	}
629
630	return v, nil
631}
632
633// params returns a map[string]string representation of VoiceConfig.
634func (config VoiceConfig) params() (map[string]string, error) {
635	params, _ := config.BaseFile.params()
636
637	if config.Duration != 0 {
638		params["duration"] = strconv.Itoa(config.Duration)
639	}
640	if config.Caption != "" {
641		params["caption"] = config.Caption
642		if config.ParseMode != "" {
643			params["parse_mode"] = config.ParseMode
644		}
645	}
646
647	return params, nil
648}
649
650// name returns the field name for the Voice.
651func (config VoiceConfig) name() string {
652	return "voice"
653}
654
655// method returns Telegram API method name for sending Voice.
656func (config VoiceConfig) method() string {
657	return "sendVoice"
658}
659
660// MediaGroupConfig contains information about a sendMediaGroup request.
661type MediaGroupConfig struct {
662	BaseChat
663	InputMedia []interface{}
664}
665
666func (config MediaGroupConfig) values() (url.Values, error) {
667	v, err := config.BaseChat.values()
668	if err != nil {
669		return v, err
670	}
671
672	data, err := json.Marshal(config.InputMedia)
673	if err != nil {
674		return v, err
675	}
676
677	v.Add("media", string(data))
678
679	return v, nil
680}
681
682func (config MediaGroupConfig) method() string {
683	return "sendMediaGroup"
684}
685
686// LocationConfig contains information about a SendLocation request.
687type LocationConfig struct {
688	BaseChat
689	Latitude  float64 // required
690	Longitude float64 // required
691}
692
693// values returns a url.Values representation of LocationConfig.
694func (config LocationConfig) values() (url.Values, error) {
695	v, err := config.BaseChat.values()
696	if err != nil {
697		return v, err
698	}
699
700	v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
701	v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
702
703	return v, nil
704}
705
706// method returns Telegram API method name for sending Location.
707func (config LocationConfig) method() string {
708	return "sendLocation"
709}
710
711// VenueConfig contains information about a SendVenue request.
712type VenueConfig struct {
713	BaseChat
714	Latitude     float64 // required
715	Longitude    float64 // required
716	Title        string  // required
717	Address      string  // required
718	FoursquareID string
719}
720
721func (config VenueConfig) values() (url.Values, error) {
722	v, err := config.BaseChat.values()
723	if err != nil {
724		return v, err
725	}
726
727	v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
728	v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
729	v.Add("title", config.Title)
730	v.Add("address", config.Address)
731	if config.FoursquareID != "" {
732		v.Add("foursquare_id", config.FoursquareID)
733	}
734
735	return v, nil
736}
737
738func (config VenueConfig) method() string {
739	return "sendVenue"
740}
741
742// ContactConfig allows you to send a contact.
743type ContactConfig struct {
744	BaseChat
745	PhoneNumber string
746	FirstName   string
747	LastName    string
748}
749
750func (config ContactConfig) values() (url.Values, error) {
751	v, err := config.BaseChat.values()
752	if err != nil {
753		return v, err
754	}
755
756	v.Add("phone_number", config.PhoneNumber)
757	v.Add("first_name", config.FirstName)
758	v.Add("last_name", config.LastName)
759
760	return v, nil
761}
762
763func (config ContactConfig) method() string {
764	return "sendContact"
765}
766
767// GameConfig allows you to send a game.
768type GameConfig struct {
769	BaseChat
770	GameShortName string
771}
772
773func (config GameConfig) values() (url.Values, error) {
774	v, err := config.BaseChat.values()
775	if err != nil {
776		return v, err
777	}
778
779	v.Add("game_short_name", config.GameShortName)
780
781	return v, nil
782}
783
784func (config GameConfig) method() string {
785	return "sendGame"
786}
787
788// SetGameScoreConfig allows you to update the game score in a chat.
789type SetGameScoreConfig struct {
790	UserID             int
791	Score              int
792	Force              bool
793	DisableEditMessage bool
794	ChatID             int64
795	ChannelUsername    string
796	MessageID          int
797	InlineMessageID    string
798}
799
800func (config SetGameScoreConfig) values() (url.Values, error) {
801	v := url.Values{}
802
803	v.Add("user_id", strconv.Itoa(config.UserID))
804	v.Add("score", strconv.Itoa(config.Score))
805	if config.InlineMessageID == "" {
806		if config.ChannelUsername == "" {
807			v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
808		} else {
809			v.Add("chat_id", config.ChannelUsername)
810		}
811		v.Add("message_id", strconv.Itoa(config.MessageID))
812	} else {
813		v.Add("inline_message_id", config.InlineMessageID)
814	}
815	v.Add("disable_edit_message", strconv.FormatBool(config.DisableEditMessage))
816
817	return v, nil
818}
819
820func (config SetGameScoreConfig) method() string {
821	return "setGameScore"
822}
823
824// GetGameHighScoresConfig allows you to fetch the high scores for a game.
825type GetGameHighScoresConfig struct {
826	UserID          int
827	ChatID          int
828	ChannelUsername string
829	MessageID       int
830	InlineMessageID string
831}
832
833func (config GetGameHighScoresConfig) values() (url.Values, error) {
834	v := url.Values{}
835
836	v.Add("user_id", strconv.Itoa(config.UserID))
837	if config.InlineMessageID == "" {
838		if config.ChannelUsername == "" {
839			v.Add("chat_id", strconv.Itoa(config.ChatID))
840		} else {
841			v.Add("chat_id", config.ChannelUsername)
842		}
843		v.Add("message_id", strconv.Itoa(config.MessageID))
844	} else {
845		v.Add("inline_message_id", config.InlineMessageID)
846	}
847
848	return v, nil
849}
850
851func (config GetGameHighScoresConfig) method() string {
852	return "getGameHighScores"
853}
854
855// ChatActionConfig contains information about a SendChatAction request.
856type ChatActionConfig struct {
857	BaseChat
858	Action string // required
859}
860
861// values returns a url.Values representation of ChatActionConfig.
862func (config ChatActionConfig) values() (url.Values, error) {
863	v, err := config.BaseChat.values()
864	if err != nil {
865		return v, err
866	}
867	v.Add("action", config.Action)
868	return v, nil
869}
870
871// method returns Telegram API method name for sending ChatAction.
872func (config ChatActionConfig) method() string {
873	return "sendChatAction"
874}
875
876// EditMessageTextConfig allows you to modify the text in a message.
877type EditMessageTextConfig struct {
878	BaseEdit
879	Text                  string
880	ParseMode             string
881	DisableWebPagePreview bool
882}
883
884func (config EditMessageTextConfig) values() (url.Values, error) {
885	v, err := config.BaseEdit.values()
886	if err != nil {
887		return v, err
888	}
889
890	v.Add("text", config.Text)
891	v.Add("parse_mode", config.ParseMode)
892	v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
893
894	return v, nil
895}
896
897func (config EditMessageTextConfig) method() string {
898	return "editMessageText"
899}
900
901// EditMessageCaptionConfig allows you to modify the caption of a message.
902type EditMessageCaptionConfig struct {
903	BaseEdit
904	Caption   string
905	ParseMode string
906}
907
908func (config EditMessageCaptionConfig) values() (url.Values, error) {
909	v, _ := config.BaseEdit.values()
910
911	v.Add("caption", config.Caption)
912	if config.ParseMode != "" {
913		v.Add("parse_mode", config.ParseMode)
914	}
915
916	return v, nil
917}
918
919func (config EditMessageCaptionConfig) method() string {
920	return "editMessageCaption"
921}
922
923// EditMessageReplyMarkupConfig allows you to modify the reply markup
924// of a message.
925type EditMessageReplyMarkupConfig struct {
926	BaseEdit
927}
928
929func (config EditMessageReplyMarkupConfig) values() (url.Values, error) {
930	return config.BaseEdit.values()
931}
932
933func (config EditMessageReplyMarkupConfig) method() string {
934	return "editMessageReplyMarkup"
935}
936
937// UserProfilePhotosConfig contains information about a
938// GetUserProfilePhotos request.
939type UserProfilePhotosConfig struct {
940	UserID int
941	Offset int
942	Limit  int
943}
944
945// FileConfig has information about a file hosted on Telegram.
946type FileConfig struct {
947	FileID string
948}
949
950// UpdateConfig contains information about a GetUpdates request.
951type UpdateConfig struct {
952	Offset  int
953	Limit   int
954	Timeout int
955}
956
957// WebhookConfig contains information about a SetWebhook request.
958type WebhookConfig struct {
959	URL            *url.URL
960	Certificate    interface{}
961	MaxConnections int
962}
963
964// FileBytes contains information about a set of bytes to upload
965// as a File.
966type FileBytes struct {
967	Name  string
968	Bytes []byte
969}
970
971// FileReader contains information about a reader to upload as a File.
972// If Size is -1, it will read the entire Reader into memory to
973// calculate a Size.
974type FileReader struct {
975	Name   string
976	Reader io.Reader
977	Size   int64
978}
979
980// InlineConfig contains information on making an InlineQuery response.
981type InlineConfig struct {
982	InlineQueryID     string        `json:"inline_query_id"`
983	Results           []interface{} `json:"results"`
984	CacheTime         int           `json:"cache_time"`
985	IsPersonal        bool          `json:"is_personal"`
986	NextOffset        string        `json:"next_offset"`
987	SwitchPMText      string        `json:"switch_pm_text"`
988	SwitchPMParameter string        `json:"switch_pm_parameter"`
989}
990
991// CallbackConfig contains information on making a CallbackQuery response.
992type CallbackConfig struct {
993	CallbackQueryID string `json:"callback_query_id"`
994	Text            string `json:"text"`
995	ShowAlert       bool   `json:"show_alert"`
996	URL             string `json:"url"`
997	CacheTime       int    `json:"cache_time"`
998}
999
1000// ChatMemberConfig contains information about a user in a chat for use
1001// with administrative functions such as kicking or unbanning a user.
1002type ChatMemberConfig struct {
1003	ChatID             int64
1004	SuperGroupUsername string
1005	ChannelUsername    string
1006	UserID             int
1007}
1008
1009// KickChatMemberConfig contains extra fields to kick user
1010type KickChatMemberConfig struct {
1011	ChatMemberConfig
1012	UntilDate int64
1013}
1014
1015// RestrictChatMemberConfig contains fields to restrict members of chat
1016type RestrictChatMemberConfig struct {
1017	ChatMemberConfig
1018	UntilDate             int64
1019	CanSendMessages       *bool
1020	CanSendMediaMessages  *bool
1021	CanSendOtherMessages  *bool
1022	CanAddWebPagePreviews *bool
1023}
1024
1025// PromoteChatMemberConfig contains fields to promote members of chat
1026type PromoteChatMemberConfig struct {
1027	ChatMemberConfig
1028	CanChangeInfo      *bool
1029	CanPostMessages    *bool
1030	CanEditMessages    *bool
1031	CanDeleteMessages  *bool
1032	CanInviteUsers     *bool
1033	CanRestrictMembers *bool
1034	CanPinMessages     *bool
1035	CanPromoteMembers  *bool
1036}
1037
1038// ChatConfig contains information about getting information on a chat.
1039type ChatConfig struct {
1040	ChatID             int64
1041	SuperGroupUsername string
1042}
1043
1044// ChatConfigWithUser contains information about getting information on
1045// a specific user within a chat.
1046type ChatConfigWithUser struct {
1047	ChatID             int64
1048	SuperGroupUsername string
1049	UserID             int
1050}
1051
1052// InvoiceConfig contains information for sendInvoice request.
1053type InvoiceConfig struct {
1054	BaseChat
1055	Title               string          // required
1056	Description         string          // required
1057	Payload             string          // required
1058	ProviderToken       string          // required
1059	StartParameter      string          // required
1060	Currency            string          // required
1061	Prices              *[]LabeledPrice // required
1062	PhotoURL            string
1063	PhotoSize           int
1064	PhotoWidth          int
1065	PhotoHeight         int
1066	NeedName            bool
1067	NeedPhoneNumber     bool
1068	NeedEmail           bool
1069	NeedShippingAddress bool
1070	IsFlexible          bool
1071}
1072
1073func (config InvoiceConfig) values() (url.Values, error) {
1074	v, err := config.BaseChat.values()
1075	if err != nil {
1076		return v, err
1077	}
1078	v.Add("title", config.Title)
1079	v.Add("description", config.Description)
1080	v.Add("payload", config.Payload)
1081	v.Add("provider_token", config.ProviderToken)
1082	v.Add("start_parameter", config.StartParameter)
1083	v.Add("currency", config.Currency)
1084	data, err := json.Marshal(config.Prices)
1085	if err != nil {
1086		return v, err
1087	}
1088	v.Add("prices", string(data))
1089	if config.PhotoURL != "" {
1090		v.Add("photo_url", config.PhotoURL)
1091	}
1092	if config.PhotoSize != 0 {
1093		v.Add("photo_size", strconv.Itoa(config.PhotoSize))
1094	}
1095	if config.PhotoWidth != 0 {
1096		v.Add("photo_width", strconv.Itoa(config.PhotoWidth))
1097	}
1098	if config.PhotoHeight != 0 {
1099		v.Add("photo_height", strconv.Itoa(config.PhotoHeight))
1100	}
1101	if config.NeedName != false {
1102		v.Add("need_name", strconv.FormatBool(config.NeedName))
1103	}
1104	if config.NeedPhoneNumber != false {
1105		v.Add("need_phone_number", strconv.FormatBool(config.NeedPhoneNumber))
1106	}
1107	if config.NeedEmail != false {
1108		v.Add("need_email", strconv.FormatBool(config.NeedEmail))
1109	}
1110	if config.NeedShippingAddress != false {
1111		v.Add("need_shipping_address", strconv.FormatBool(config.NeedShippingAddress))
1112	}
1113	if config.IsFlexible != false {
1114		v.Add("is_flexible", strconv.FormatBool(config.IsFlexible))
1115	}
1116
1117	return v, nil
1118}
1119
1120func (config InvoiceConfig) method() string {
1121	return "sendInvoice"
1122}
1123
1124// ShippingConfig contains information for answerShippingQuery request.
1125type ShippingConfig struct {
1126	ShippingQueryID string // required
1127	OK              bool   // required
1128	ShippingOptions *[]ShippingOption
1129	ErrorMessage    string
1130}
1131
1132// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
1133type PreCheckoutConfig struct {
1134	PreCheckoutQueryID string // required
1135	OK                 bool   // required
1136	ErrorMessage       string
1137}
1138
1139// DeleteMessageConfig contains information of a message in a chat to delete.
1140type DeleteMessageConfig struct {
1141	ChatID    int64
1142	MessageID int
1143}
1144
1145func (config DeleteMessageConfig) method() string {
1146	return "deleteMessage"
1147}
1148
1149func (config DeleteMessageConfig) values() (url.Values, error) {
1150	v := url.Values{}
1151
1152	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1153	v.Add("message_id", strconv.Itoa(config.MessageID))
1154
1155	return v, nil
1156}
1157
1158// PinChatMessageConfig contains information of a message in a chat to pin.
1159type PinChatMessageConfig struct {
1160	ChatID              int64
1161	MessageID           int
1162	DisableNotification bool
1163}
1164
1165func (config PinChatMessageConfig) method() string {
1166	return "pinChatMessage"
1167}
1168
1169func (config PinChatMessageConfig) values() (url.Values, error) {
1170	v := url.Values{}
1171
1172	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1173	v.Add("message_id", strconv.Itoa(config.MessageID))
1174	v.Add("disable_notification", strconv.FormatBool(config.DisableNotification))
1175
1176	return v, nil
1177}
1178
1179// UnpinChatMessageConfig contains information of chat to unpin.
1180type UnpinChatMessageConfig struct {
1181	ChatID int64
1182}
1183
1184func (config UnpinChatMessageConfig) method() string {
1185	return "unpinChatMessage"
1186}
1187
1188func (config UnpinChatMessageConfig) values() (url.Values, error) {
1189	v := url.Values{}
1190
1191	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1192
1193	return v, nil
1194}
1195
1196// SetChatTitleConfig contains information for change chat title.
1197type SetChatTitleConfig struct {
1198	ChatID int64
1199	Title  string
1200}
1201
1202func (config SetChatTitleConfig) method() string {
1203	return "setChatTitle"
1204}
1205
1206func (config SetChatTitleConfig) values() (url.Values, error) {
1207	v := url.Values{}
1208
1209	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1210	v.Add("title", config.Title)
1211
1212	return v, nil
1213}
1214
1215// SetChatDescriptionConfig contains information for change chat description.
1216type SetChatDescriptionConfig struct {
1217	ChatID      int64
1218	Description string
1219}
1220
1221func (config SetChatDescriptionConfig) method() string {
1222	return "setChatDescription"
1223}
1224
1225func (config SetChatDescriptionConfig) values() (url.Values, error) {
1226	v := url.Values{}
1227
1228	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1229	v.Add("description", config.Description)
1230
1231	return v, nil
1232}
1233
1234// SetChatPhotoConfig contains information for change chat photo
1235type SetChatPhotoConfig struct {
1236	BaseFile
1237}
1238
1239// name returns the field name for the Photo.
1240func (config SetChatPhotoConfig) name() string {
1241	return "photo"
1242}
1243
1244// method returns Telegram API method name for sending Photo.
1245func (config SetChatPhotoConfig) method() string {
1246	return "setChatPhoto"
1247}
1248
1249// DeleteChatPhotoConfig contains information for delete chat photo.
1250type DeleteChatPhotoConfig struct {
1251	ChatID int64
1252}
1253
1254func (config DeleteChatPhotoConfig) method() string {
1255	return "deleteChatPhoto"
1256}
1257
1258func (config DeleteChatPhotoConfig) values() (url.Values, error) {
1259	v := url.Values{}
1260
1261	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1262
1263	return v, nil
1264}
1265
1266// GetStickerSetConfig contains information for get sticker set.
1267type GetStickerSetConfig struct {
1268	Name string
1269}
1270
1271func (config GetStickerSetConfig) method() string {
1272	return "getStickerSet"
1273}
1274
1275func (config GetStickerSetConfig) values() (url.Values, error) {
1276	v := url.Values{}
1277	v.Add("name", config.Name)
1278	return v, nil
1279}
1280