methods.go (view raw)
1package tgbotapi
2
3import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "io/ioutil"
8 "log"
9 "net/http"
10 "net/url"
11 "os"
12 "strconv"
13
14 "github.com/technoweenie/multipartstreamer"
15)
16
17// Telegram constants
18const (
19 // APIEndpoint is the endpoint for all API methods, with formatting for Sprintf
20 APIEndpoint = "https://api.telegram.org/bot%s/%s"
21)
22
23// Constant values for ChatActions
24const (
25 ChatTyping = "typing"
26 ChatUploadPhoto = "upload_photo"
27 ChatRecordVideo = "record_video"
28 ChatUploadVideo = "upload_video"
29 ChatRecordAudio = "record_audio"
30 ChatUploadAudio = "upload_audio"
31 ChatUploadDocument = "upload_document"
32 ChatFindLocation = "find_location"
33)
34
35// API errors
36const (
37 // APIForbidden happens when a token is bad
38 APIForbidden = "forbidden"
39)
40
41// MessageConfig contains information about a SendMessage request.
42type MessageConfig struct {
43 ChatID int
44 Text string
45 DisableWebPagePreview bool
46 ReplyToMessageID int
47 ReplyMarkup interface{}
48}
49
50// ForwardConfig contains information about a ForwardMessage request.
51type ForwardConfig struct {
52 ChatID int
53 FromChatID int
54 MessageID int
55}
56
57// PhotoConfig contains information about a SendPhoto request.
58type PhotoConfig struct {
59 ChatID int
60 Caption string
61 ReplyToMessageID int
62 ReplyMarkup interface{}
63 UseExistingPhoto bool
64 FilePath string
65 FileID string
66}
67
68// AudioConfig contains information about a SendAudio request.
69type AudioConfig struct {
70 ChatID int
71 Duration int
72 Performer string
73 Title string
74 ReplyToMessageID int
75 ReplyMarkup interface{}
76 UseExistingAudio bool
77 FilePath string
78 FileID string
79}
80
81// DocumentConfig contains information about a SendDocument request.
82type DocumentConfig struct {
83 ChatID int
84 ReplyToMessageID int
85 ReplyMarkup interface{}
86 UseExistingDocument bool
87 FilePath string
88 FileID string
89}
90
91// StickerConfig contains information about a SendSticker request.
92type StickerConfig struct {
93 ChatID int
94 ReplyToMessageID int
95 ReplyMarkup interface{}
96 UseExistingSticker bool
97 FilePath string
98 FileID string
99}
100
101// VideoConfig contains information about a SendVideo request.
102type VideoConfig struct {
103 ChatID int
104 Duration int
105 Caption string
106 ReplyToMessageID int
107 ReplyMarkup interface{}
108 UseExistingVideo bool
109 FilePath string
110 FileID string
111}
112
113// VoiceConfig contains information about a SendVoice request.
114type VoiceConfig struct {
115 ChatID int
116 Duration int
117 ReplyToMessageID int
118 ReplyMarkup interface{}
119 UseExistingVoice bool
120 FilePath string
121 FileID string
122}
123
124// LocationConfig contains information about a SendLocation request.
125type LocationConfig struct {
126 ChatID int
127 Latitude float64
128 Longitude float64
129 ReplyToMessageID int
130 ReplyMarkup interface{}
131}
132
133// ChatActionConfig contains information about a SendChatAction request.
134type ChatActionConfig struct {
135 ChatID int
136 Action string
137}
138
139// UserProfilePhotosConfig contains information about a GetUserProfilePhotos request.
140type UserProfilePhotosConfig struct {
141 UserID int
142 Offset int
143 Limit int
144}
145
146// UpdateConfig contains information about a GetUpdates request.
147type UpdateConfig struct {
148 Offset int
149 Limit int
150 Timeout int
151}
152
153// WebhookConfig contains information about a SetWebhook request.
154type WebhookConfig struct {
155 Clear bool
156 URL *url.URL
157}
158
159// MakeRequest makes a request to a specific endpoint with our token.
160// All requests are POSTs because Telegram doesn't care, and it's easier.
161func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, error) {
162 resp, err := bot.Client.PostForm(fmt.Sprintf(APIEndpoint, bot.Token, endpoint), params)
163 if err != nil {
164 return APIResponse{}, err
165 }
166 defer resp.Body.Close()
167
168 if resp.StatusCode == http.StatusForbidden {
169 return APIResponse{}, errors.New(APIForbidden)
170 }
171
172 bytes, err := ioutil.ReadAll(resp.Body)
173 if err != nil {
174 return APIResponse{}, err
175 }
176
177 if bot.Debug {
178 log.Println(endpoint, string(bytes))
179 }
180
181 var apiResp APIResponse
182 json.Unmarshal(bytes, &apiResp)
183
184 if !apiResp.Ok {
185 return APIResponse{}, errors.New(apiResp.Description)
186 }
187
188 return apiResp, nil
189}
190
191// UploadFile makes a request to the API with a file.
192//
193// Requires the parameter to hold the file not be in the params.
194func (bot *BotAPI) UploadFile(endpoint string, params map[string]string, fieldname string, filename string) (APIResponse, error) {
195 f, err := os.Open(filename)
196 if err != nil {
197 return APIResponse{}, err
198 }
199 defer f.Close()
200
201 fi, err := os.Stat(filename)
202 if err != nil {
203 return APIResponse{}, err
204 }
205
206 ms := multipartstreamer.New()
207 ms.WriteFields(params)
208 ms.WriteReader(fieldname, f.Name(), fi.Size(), f)
209
210 req, err := http.NewRequest("POST", fmt.Sprintf(APIEndpoint, bot.Token, endpoint), nil)
211 ms.SetupRequest(req)
212 if err != nil {
213 return APIResponse{}, err
214 }
215
216 res, err := bot.Client.Do(req)
217 if err != nil {
218 return APIResponse{}, err
219 }
220 defer res.Body.Close()
221
222 bytes, err := ioutil.ReadAll(res.Body)
223 if err != nil {
224 return APIResponse{}, err
225 }
226
227 if bot.Debug {
228 log.Println(string(bytes[:]))
229 }
230
231 var apiResp APIResponse
232 json.Unmarshal(bytes, &apiResp)
233
234 return apiResp, nil
235}
236
237// GetMe fetches the currently authenticated bot.
238//
239// There are no parameters for this method.
240func (bot *BotAPI) GetMe() (User, error) {
241 resp, err := bot.MakeRequest("getMe", nil)
242 if err != nil {
243 return User{}, err
244 }
245
246 var user User
247 json.Unmarshal(resp.Result, &user)
248
249 if bot.Debug {
250 log.Printf("getMe: %+v\n", user)
251 }
252
253 return user, nil
254}
255
256// SendMessage sends a Message to a chat.
257//
258// Requires ChatID and Text.
259// DisableWebPagePreview, ReplyToMessageID, and ReplyMarkup are optional.
260func (bot *BotAPI) SendMessage(config MessageConfig) (Message, error) {
261 v := url.Values{}
262 v.Add("chat_id", strconv.Itoa(config.ChatID))
263 v.Add("text", config.Text)
264 v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
265 if config.ReplyToMessageID != 0 {
266 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageID))
267 }
268 if config.ReplyMarkup != nil {
269 data, err := json.Marshal(config.ReplyMarkup)
270 if err != nil {
271 return Message{}, err
272 }
273
274 v.Add("reply_markup", string(data))
275 }
276
277 resp, err := bot.MakeRequest("SendMessage", v)
278 if err != nil {
279 return Message{}, err
280 }
281
282 var message Message
283 json.Unmarshal(resp.Result, &message)
284
285 if bot.Debug {
286 log.Printf("SendMessage req : %+v\n", v)
287 log.Printf("SendMessage resp: %+v\n", message)
288 }
289
290 return message, nil
291}
292
293// ForwardMessage forwards a message from one chat to another.
294//
295// Requires ChatID (destination), FromChatID (source), and MessageID.
296func (bot *BotAPI) ForwardMessage(config ForwardConfig) (Message, error) {
297 v := url.Values{}
298 v.Add("chat_id", strconv.Itoa(config.ChatID))
299 v.Add("from_chat_id", strconv.Itoa(config.FromChatID))
300 v.Add("message_id", strconv.Itoa(config.MessageID))
301
302 resp, err := bot.MakeRequest("forwardMessage", v)
303 if err != nil {
304 return Message{}, err
305 }
306
307 var message Message
308 json.Unmarshal(resp.Result, &message)
309
310 if bot.Debug {
311 log.Printf("forwardMessage req : %+v\n", v)
312 log.Printf("forwardMessage resp: %+v\n", message)
313 }
314
315 return message, nil
316}
317
318// SendPhoto sends or uploads a photo to a chat.
319//
320// Requires ChatID and FileID OR FilePath.
321// Caption, ReplyToMessageID, and ReplyMarkup are optional.
322func (bot *BotAPI) SendPhoto(config PhotoConfig) (Message, error) {
323 if config.UseExistingPhoto {
324 v := url.Values{}
325 v.Add("chat_id", strconv.Itoa(config.ChatID))
326 v.Add("photo", config.FileID)
327 if config.Caption != "" {
328 v.Add("caption", config.Caption)
329 }
330 if config.ReplyToMessageID != 0 {
331 v.Add("reply_to_message_id", strconv.Itoa(config.ChatID))
332 }
333 if config.ReplyMarkup != nil {
334 data, err := json.Marshal(config.ReplyMarkup)
335 if err != nil {
336 return Message{}, err
337 }
338
339 v.Add("reply_markup", string(data))
340 }
341
342 resp, err := bot.MakeRequest("SendPhoto", v)
343 if err != nil {
344 return Message{}, err
345 }
346
347 var message Message
348 json.Unmarshal(resp.Result, &message)
349
350 if bot.Debug {
351 log.Printf("SendPhoto req : %+v\n", v)
352 log.Printf("SendPhoto resp: %+v\n", message)
353 }
354
355 return message, nil
356 }
357
358 params := make(map[string]string)
359 params["chat_id"] = strconv.Itoa(config.ChatID)
360 if config.Caption != "" {
361 params["caption"] = config.Caption
362 }
363 if config.ReplyToMessageID != 0 {
364 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageID)
365 }
366 if config.ReplyMarkup != nil {
367 data, err := json.Marshal(config.ReplyMarkup)
368 if err != nil {
369 return Message{}, err
370 }
371
372 params["reply_markup"] = string(data)
373 }
374
375 resp, err := bot.UploadFile("SendPhoto", params, "photo", config.FilePath)
376 if err != nil {
377 return Message{}, err
378 }
379
380 var message Message
381 json.Unmarshal(resp.Result, &message)
382
383 if bot.Debug {
384 log.Printf("SendPhoto resp: %+v\n", message)
385 }
386
387 return message, nil
388}
389
390// SendAudio sends or uploads an audio clip to a chat.
391// If using a file, the file must be in the .mp3 format.
392//
393// when the fields title and performer are both empty
394// and the mime-type of the file to be sent is not audio/mpeg,
395// the file must be in an .ogg file encoded with OPUS.
396// You may use the tgutils.EncodeAudio func to assist you with this, if needed.
397//
398// Requires ChatID and FileID OR FilePath.
399// ReplyToMessageID and ReplyMarkup are optional.
400func (bot *BotAPI) SendAudio(config AudioConfig) (Message, error) {
401 if config.UseExistingAudio {
402 v := url.Values{}
403 v.Add("chat_id", strconv.Itoa(config.ChatID))
404 v.Add("audio", config.FileID)
405 if config.ReplyToMessageID != 0 {
406 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageID))
407 }
408 if config.Duration != 0 {
409 v.Add("duration", strconv.Itoa(config.Duration))
410 }
411 if config.ReplyMarkup != nil {
412 data, err := json.Marshal(config.ReplyMarkup)
413 if err != nil {
414 return Message{}, err
415 }
416
417 v.Add("reply_markup", string(data))
418 }
419 if config.Performer != "" {
420 v.Add("performer", config.Performer)
421 }
422 if config.Title != "" {
423 v.Add("title", config.Title)
424 }
425
426 resp, err := bot.MakeRequest("sendAudio", v)
427 if err != nil {
428 return Message{}, err
429 }
430
431 var message Message
432 json.Unmarshal(resp.Result, &message)
433
434 if bot.Debug {
435 log.Printf("sendAudio req : %+v\n", v)
436 log.Printf("sendAudio resp: %+v\n", message)
437 }
438
439 return message, nil
440 }
441
442 params := make(map[string]string)
443
444 params["chat_id"] = strconv.Itoa(config.ChatID)
445 if config.ReplyToMessageID != 0 {
446 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageID)
447 }
448 if config.Duration != 0 {
449 params["duration"] = strconv.Itoa(config.Duration)
450 }
451 if config.ReplyMarkup != nil {
452 data, err := json.Marshal(config.ReplyMarkup)
453 if err != nil {
454 return Message{}, err
455 }
456
457 params["reply_markup"] = string(data)
458 }
459 if config.Performer != "" {
460 params["performer"] = config.Performer
461 }
462 if config.Title != "" {
463 params["title"] = config.Title
464 }
465
466 resp, err := bot.UploadFile("sendAudio", params, "audio", config.FilePath)
467 if err != nil {
468 return Message{}, err
469 }
470
471 var message Message
472 json.Unmarshal(resp.Result, &message)
473
474 if bot.Debug {
475 log.Printf("sendAudio resp: %+v\n", message)
476 }
477
478 return message, nil
479}
480
481// SendDocument sends or uploads a document to a chat.
482//
483// Requires ChatID and FileID OR FilePath.
484// ReplyToMessageID and ReplyMarkup are optional.
485func (bot *BotAPI) SendDocument(config DocumentConfig) (Message, error) {
486 if config.UseExistingDocument {
487 v := url.Values{}
488 v.Add("chat_id", strconv.Itoa(config.ChatID))
489 v.Add("document", config.FileID)
490 if config.ReplyToMessageID != 0 {
491 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageID))
492 }
493 if config.ReplyMarkup != nil {
494 data, err := json.Marshal(config.ReplyMarkup)
495 if err != nil {
496 return Message{}, err
497 }
498
499 v.Add("reply_markup", string(data))
500 }
501
502 resp, err := bot.MakeRequest("sendDocument", v)
503 if err != nil {
504 return Message{}, err
505 }
506
507 var message Message
508 json.Unmarshal(resp.Result, &message)
509
510 if bot.Debug {
511 log.Printf("sendDocument req : %+v\n", v)
512 log.Printf("sendDocument resp: %+v\n", message)
513 }
514
515 return message, nil
516 }
517
518 params := make(map[string]string)
519
520 params["chat_id"] = strconv.Itoa(config.ChatID)
521 if config.ReplyToMessageID != 0 {
522 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageID)
523 }
524 if config.ReplyMarkup != nil {
525 data, err := json.Marshal(config.ReplyMarkup)
526 if err != nil {
527 return Message{}, err
528 }
529
530 params["reply_markup"] = string(data)
531 }
532
533 resp, err := bot.UploadFile("sendDocument", params, "document", config.FilePath)
534 if err != nil {
535 return Message{}, err
536 }
537
538 var message Message
539 json.Unmarshal(resp.Result, &message)
540
541 if bot.Debug {
542 log.Printf("sendDocument resp: %+v\n", message)
543 }
544
545 return message, nil
546}
547
548// SendVoice sends or uploads a playable voice to a chat.
549// If using a file, the file must be encoded as an .ogg with OPUS.
550// You may use the tgutils.EncodeAudio func to assist you with this, if needed.
551//
552// Requires ChatID and FileID OR FilePath.
553// ReplyToMessageID and ReplyMarkup are optional.
554func (bot *BotAPI) SendVoice(config VoiceConfig) (Message, error) {
555 if config.UseExistingVoice {
556 v := url.Values{}
557 v.Add("chat_id", strconv.Itoa(config.ChatID))
558 v.Add("voice", config.FileID)
559 if config.ReplyToMessageID != 0 {
560 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageID))
561 }
562 if config.Duration != 0 {
563 v.Add("duration", strconv.Itoa(config.Duration))
564 }
565 if config.ReplyMarkup != nil {
566 data, err := json.Marshal(config.ReplyMarkup)
567 if err != nil {
568 return Message{}, err
569 }
570
571 v.Add("reply_markup", string(data))
572 }
573
574 resp, err := bot.MakeRequest("sendVoice", v)
575 if err != nil {
576 return Message{}, err
577 }
578
579 var message Message
580 json.Unmarshal(resp.Result, &message)
581
582 if bot.Debug {
583 log.Printf("SendVoice req : %+v\n", v)
584 log.Printf("SendVoice resp: %+v\n", message)
585 }
586
587 return message, nil
588 }
589
590 params := make(map[string]string)
591
592 params["chat_id"] = strconv.Itoa(config.ChatID)
593 if config.ReplyToMessageID != 0 {
594 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageID)
595 }
596 if config.Duration != 0 {
597 params["duration"] = strconv.Itoa(config.Duration)
598 }
599 if config.ReplyMarkup != nil {
600 data, err := json.Marshal(config.ReplyMarkup)
601 if err != nil {
602 return Message{}, err
603 }
604
605 params["reply_markup"] = string(data)
606 }
607
608 resp, err := bot.UploadFile("SendVoice", params, "voice", config.FilePath)
609 if err != nil {
610 return Message{}, err
611 }
612
613 var message Message
614 json.Unmarshal(resp.Result, &message)
615
616 if bot.Debug {
617 log.Printf("SendVoice resp: %+v\n", message)
618 }
619
620 return message, nil
621}
622
623// SendSticker sends or uploads a sticker to a chat.
624//
625// Requires ChatID and FileID OR FilePath.
626// ReplyToMessageID and ReplyMarkup are optional.
627func (bot *BotAPI) SendSticker(config StickerConfig) (Message, error) {
628 if config.UseExistingSticker {
629 v := url.Values{}
630 v.Add("chat_id", strconv.Itoa(config.ChatID))
631 v.Add("sticker", config.FileID)
632 if config.ReplyToMessageID != 0 {
633 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageID))
634 }
635 if config.ReplyMarkup != nil {
636 data, err := json.Marshal(config.ReplyMarkup)
637 if err != nil {
638 return Message{}, err
639 }
640
641 v.Add("reply_markup", string(data))
642 }
643
644 resp, err := bot.MakeRequest("sendSticker", v)
645 if err != nil {
646 return Message{}, err
647 }
648
649 var message Message
650 json.Unmarshal(resp.Result, &message)
651
652 if bot.Debug {
653 log.Printf("sendSticker req : %+v\n", v)
654 log.Printf("sendSticker resp: %+v\n", message)
655 }
656
657 return message, nil
658 }
659
660 params := make(map[string]string)
661
662 params["chat_id"] = strconv.Itoa(config.ChatID)
663 if config.ReplyToMessageID != 0 {
664 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageID)
665 }
666 if config.ReplyMarkup != nil {
667 data, err := json.Marshal(config.ReplyMarkup)
668 if err != nil {
669 return Message{}, err
670 }
671
672 params["reply_markup"] = string(data)
673 }
674
675 resp, err := bot.UploadFile("sendSticker", params, "sticker", config.FilePath)
676 if err != nil {
677 return Message{}, err
678 }
679
680 var message Message
681 json.Unmarshal(resp.Result, &message)
682
683 if bot.Debug {
684 log.Printf("sendSticker resp: %+v\n", message)
685 }
686
687 return message, nil
688}
689
690// SendVideo sends or uploads a video to a chat.
691//
692// Requires ChatID and FileID OR FilePath.
693// ReplyToMessageID and ReplyMarkup are optional.
694func (bot *BotAPI) SendVideo(config VideoConfig) (Message, error) {
695 if config.UseExistingVideo {
696 v := url.Values{}
697 v.Add("chat_id", strconv.Itoa(config.ChatID))
698 v.Add("video", config.FileID)
699 if config.ReplyToMessageID != 0 {
700 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageID))
701 }
702 if config.Duration != 0 {
703 v.Add("duration", strconv.Itoa(config.Duration))
704 }
705 if config.Caption != "" {
706 v.Add("caption", config.Caption)
707 }
708 if config.ReplyMarkup != nil {
709 data, err := json.Marshal(config.ReplyMarkup)
710 if err != nil {
711 return Message{}, err
712 }
713
714 v.Add("reply_markup", string(data))
715 }
716
717 resp, err := bot.MakeRequest("sendVideo", v)
718 if err != nil {
719 return Message{}, err
720 }
721
722 var message Message
723 json.Unmarshal(resp.Result, &message)
724
725 if bot.Debug {
726 log.Printf("sendVideo req : %+v\n", v)
727 log.Printf("sendVideo resp: %+v\n", message)
728 }
729
730 return message, nil
731 }
732
733 params := make(map[string]string)
734
735 params["chat_id"] = strconv.Itoa(config.ChatID)
736 if config.ReplyToMessageID != 0 {
737 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageID)
738 }
739 if config.ReplyMarkup != nil {
740 data, err := json.Marshal(config.ReplyMarkup)
741 if err != nil {
742 return Message{}, err
743 }
744
745 params["reply_markup"] = string(data)
746 }
747
748 resp, err := bot.UploadFile("sendVideo", params, "video", config.FilePath)
749 if err != nil {
750 return Message{}, err
751 }
752
753 var message Message
754 json.Unmarshal(resp.Result, &message)
755
756 if bot.Debug {
757 log.Printf("sendVideo resp: %+v\n", message)
758 }
759
760 return message, nil
761}
762
763// SendLocation sends a location to a chat.
764//
765// Requires ChatID, Latitude, and Longitude.
766// ReplyToMessageID and ReplyMarkup are optional.
767func (bot *BotAPI) SendLocation(config LocationConfig) (Message, error) {
768 v := url.Values{}
769 v.Add("chat_id", strconv.Itoa(config.ChatID))
770 v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
771 v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
772 if config.ReplyToMessageID != 0 {
773 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageID))
774 }
775 if config.ReplyMarkup != nil {
776 data, err := json.Marshal(config.ReplyMarkup)
777 if err != nil {
778 return Message{}, err
779 }
780
781 v.Add("reply_markup", string(data))
782 }
783
784 resp, err := bot.MakeRequest("sendLocation", v)
785 if err != nil {
786 return Message{}, err
787 }
788
789 var message Message
790 json.Unmarshal(resp.Result, &message)
791
792 if bot.Debug {
793 log.Printf("sendLocation req : %+v\n", v)
794 log.Printf("sendLocation resp: %+v\n", message)
795 }
796
797 return message, nil
798}
799
800// SendChatAction sets a current action in a chat.
801//
802// Requires ChatID and a valid Action (see Chat constants).
803func (bot *BotAPI) SendChatAction(config ChatActionConfig) error {
804 v := url.Values{}
805 v.Add("chat_id", strconv.Itoa(config.ChatID))
806 v.Add("action", config.Action)
807
808 _, err := bot.MakeRequest("sendChatAction", v)
809 if err != nil {
810 return err
811 }
812
813 return nil
814}
815
816// GetUserProfilePhotos gets a user's profile photos.
817//
818// Requires UserID.
819// Offset and Limit are optional.
820func (bot *BotAPI) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
821 v := url.Values{}
822 v.Add("user_id", strconv.Itoa(config.UserID))
823 if config.Offset != 0 {
824 v.Add("offset", strconv.Itoa(config.Offset))
825 }
826 if config.Limit != 0 {
827 v.Add("limit", strconv.Itoa(config.Limit))
828 }
829
830 resp, err := bot.MakeRequest("getUserProfilePhotos", v)
831 if err != nil {
832 return UserProfilePhotos{}, err
833 }
834
835 var profilePhotos UserProfilePhotos
836 json.Unmarshal(resp.Result, &profilePhotos)
837
838 if bot.Debug {
839 log.Printf("getUserProfilePhotos req : %+v\n", v)
840 log.Printf("getUserProfilePhotos resp: %+v\n", profilePhotos)
841 }
842
843 return profilePhotos, nil
844}
845
846// GetUpdates fetches updates.
847// If a WebHook is set, this will not return any data!
848//
849// Offset, Limit, and Timeout are optional.
850// To not get old items, set Offset to one higher than the previous item.
851// Set Timeout to a large number to reduce requests and get responses instantly.
852func (bot *BotAPI) GetUpdates(config UpdateConfig) ([]Update, error) {
853 v := url.Values{}
854 if config.Offset > 0 {
855 v.Add("offset", strconv.Itoa(config.Offset))
856 }
857 if config.Limit > 0 {
858 v.Add("limit", strconv.Itoa(config.Limit))
859 }
860 if config.Timeout > 0 {
861 v.Add("timeout", strconv.Itoa(config.Timeout))
862 }
863
864 resp, err := bot.MakeRequest("getUpdates", v)
865 if err != nil {
866 return []Update{}, err
867 }
868
869 var updates []Update
870 json.Unmarshal(resp.Result, &updates)
871
872 if bot.Debug {
873 log.Printf("getUpdates: %+v\n", updates)
874 }
875
876 return updates, nil
877}
878
879// SetWebhook sets a webhook.
880// If this is set, GetUpdates will not get any data!
881//
882// Requires Url OR to set Clear to true.
883func (bot *BotAPI) SetWebhook(config WebhookConfig) error {
884 v := url.Values{}
885 if !config.Clear {
886 v.Add("url", config.URL.String())
887 }
888
889 _, err := bot.MakeRequest("setWebhook", v)
890
891 return err
892}