methods.go (view raw)
1package tgbotapi
2
3import (
4 "bytes"
5 "encoding/json"
6 "errors"
7 "io"
8 "io/ioutil"
9 "log"
10 "mime/multipart"
11 "net/http"
12 "net/url"
13 "os"
14 "strconv"
15)
16
17const (
18 CHAT_TYPING = "typing"
19 CHAT_UPLOAD_PHOTO = "upload_photo"
20 CHAT_RECORD_VIDEO = "record_video"
21 CHAT_UPLOAD_VIDEO = "upload_video"
22 CHAT_RECORD_AUDIO = "record_audio"
23 CHAT_UPLOAD_AUDIO = "upload_audio"
24 CHAT_UPLOAD_DOCUMENT = "upload_document"
25 CHAT_FIND_LOCATION = "find_location"
26)
27
28type MessageConfig struct {
29 ChatId int
30 Text string
31 DisableWebPagePreview bool
32 ReplyToMessageId int
33 ReplyMarkup interface{}
34}
35
36type ForwardConfig struct {
37 ChatId int
38 FromChatId int
39 MessageId int
40}
41
42type PhotoConfig struct {
43 ChatId int
44 Caption string
45 ReplyToMessageId int
46 ReplyMarkup interface{}
47 UseExistingPhoto bool
48 FilePath string
49 FileId string
50}
51
52type AudioConfig struct {
53 ChatId int
54 ReplyToMessageId int
55 ReplyMarkup interface{}
56 UseExistingAudio bool
57 FilePath string
58 FileId string
59}
60
61type DocumentConfig struct {
62 ChatId int
63 ReplyToMessageId int
64 ReplyMarkup interface{}
65 UseExistingDocument bool
66 FilePath string
67 FileId string
68}
69
70type StickerConfig struct {
71 ChatId int
72 ReplyToMessageId int
73 ReplyMarkup interface{}
74 UseExistingSticker bool
75 FilePath string
76 FileId string
77}
78
79type VideoConfig struct {
80 ChatId int
81 ReplyToMessageId int
82 ReplyMarkup interface{}
83 UseExistingVideo bool
84 FilePath string
85 FileId string
86}
87
88type LocationConfig struct {
89 ChatId int
90 Latitude float64
91 Longitude float64
92 ReplyToMessageId int
93 ReplyMarkup interface{}
94}
95
96type ChatActionConfig struct {
97 ChatId int
98 Action string
99}
100
101type UserProfilePhotosConfig struct {
102 UserId int
103 Offset int
104 Limit int
105}
106
107type UpdateConfig struct {
108 Offset int
109 Limit int
110 Timeout int
111}
112
113type WebhookConfig struct {
114 Clear bool
115 Url *url.URL
116}
117
118func (bot *BotApi) MakeRequest(endpoint string, params url.Values) (ApiResponse, error) {
119 resp, err := http.PostForm("https://api.telegram.org/bot"+bot.Token+"/"+endpoint, params)
120 defer resp.Body.Close()
121 if err != nil {
122 return ApiResponse{}, err
123 }
124
125 bytes, err := ioutil.ReadAll(resp.Body)
126 if err != nil {
127 return ApiResponse{}, err
128 }
129
130 if bot.Debug {
131 log.Println(endpoint, string(bytes))
132 }
133
134 var apiResp ApiResponse
135 json.Unmarshal(bytes, &apiResp)
136
137 if !apiResp.Ok {
138 return ApiResponse{}, errors.New(apiResp.Description)
139 }
140
141 return apiResp, nil
142}
143
144func (bot *BotApi) UploadFile(endpoint string, params map[string]string, fieldname string, filename string) (ApiResponse, error) {
145 var b bytes.Buffer
146 w := multipart.NewWriter(&b)
147
148 f, err := os.Open(filename)
149 if err != nil {
150 return ApiResponse{}, err
151 }
152
153 fw, err := w.CreateFormFile(fieldname, filename)
154 if err != nil {
155 return ApiResponse{}, err
156 }
157
158 if _, err = io.Copy(fw, f); err != nil {
159 return ApiResponse{}, err
160 }
161
162 for key, val := range params {
163 if fw, err = w.CreateFormField(key); err != nil {
164 return ApiResponse{}, err
165 }
166
167 if _, err = fw.Write([]byte(val)); err != nil {
168 return ApiResponse{}, err
169 }
170 }
171
172 w.Close()
173
174 req, err := http.NewRequest("POST", "https://api.telegram.org/bot"+bot.Token+"/"+endpoint, &b)
175 if err != nil {
176 return ApiResponse{}, err
177 }
178
179 req.Header.Set("Content-Type", w.FormDataContentType())
180
181 client := &http.Client{}
182 res, err := client.Do(req)
183 if err != nil {
184 return ApiResponse{}, err
185 }
186
187 bytes, err := ioutil.ReadAll(res.Body)
188 if err != nil {
189 return ApiResponse{}, err
190 }
191
192 if bot.Debug {
193 log.Println(string(bytes[:]))
194 }
195
196 var apiResp ApiResponse
197 json.Unmarshal(bytes, &apiResp)
198
199 return apiResp, nil
200}
201
202func (bot *BotApi) GetMe() (User, error) {
203 resp, err := bot.MakeRequest("getMe", nil)
204 if err != nil {
205 return User{}, err
206 }
207
208 var user User
209 json.Unmarshal(resp.Result, &user)
210
211 if bot.Debug {
212 log.Printf("getMe: %+v\n", user)
213 }
214
215 return user, nil
216}
217
218func (bot *BotApi) SendMessage(config MessageConfig) (Message, error) {
219 v := url.Values{}
220 v.Add("chat_id", strconv.Itoa(config.ChatId))
221 v.Add("text", config.Text)
222 v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
223 if config.ReplyToMessageId != 0 {
224 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
225 }
226 if config.ReplyMarkup != nil {
227 data, err := json.Marshal(config.ReplyMarkup)
228 if err != nil {
229 return Message{}, err
230 }
231
232 v.Add("reply_markup", string(data))
233 }
234
235 resp, err := bot.MakeRequest("SendMessage", v)
236 if err != nil {
237 return Message{}, err
238 }
239
240 var message Message
241 json.Unmarshal(resp.Result, &message)
242
243 if bot.Debug {
244 log.Printf("SendMessage req : %+v\n", v)
245 log.Printf("SendMessage resp: %+v\n", message)
246 }
247
248 return message, nil
249}
250
251func (bot *BotApi) ForwardMessage(config ForwardConfig) (Message, error) {
252 v := url.Values{}
253 v.Add("chat_id", strconv.Itoa(config.ChatId))
254 v.Add("from_chat_id", strconv.Itoa(config.FromChatId))
255 v.Add("message_id", strconv.Itoa(config.MessageId))
256
257 resp, err := bot.MakeRequest("forwardMessage", v)
258 if err != nil {
259 return Message{}, err
260 }
261
262 var message Message
263 json.Unmarshal(resp.Result, &message)
264
265 if bot.Debug {
266 log.Printf("forwardMessage req : %+v\n", v)
267 log.Printf("forwardMessage resp: %+v\n", message)
268 }
269
270 return message, nil
271}
272
273func (bot *BotApi) SendPhoto(config PhotoConfig) (Message, error) {
274 if config.UseExistingPhoto {
275 v := url.Values{}
276 v.Add("chat_id", strconv.Itoa(config.ChatId))
277 v.Add("photo", config.FileId)
278 if config.Caption != "" {
279 v.Add("caption", config.Caption)
280 }
281 if config.ReplyToMessageId != 0 {
282 v.Add("reply_to_message_id", strconv.Itoa(config.ChatId))
283 }
284 if config.ReplyMarkup != nil {
285 data, err := json.Marshal(config.ReplyMarkup)
286 if err != nil {
287 return Message{}, err
288 }
289
290 v.Add("reply_markup", string(data))
291 }
292
293 resp, err := bot.MakeRequest("SendPhoto", v)
294 if err != nil {
295 return Message{}, err
296 }
297
298 var message Message
299 json.Unmarshal(resp.Result, &message)
300
301 if bot.Debug {
302 log.Printf("SendPhoto req : %+v\n", v)
303 log.Printf("SendPhoto resp: %+v\n", message)
304 }
305
306 return message, nil
307 }
308
309 params := make(map[string]string)
310 params["chat_id"] = strconv.Itoa(config.ChatId)
311 if config.Caption != "" {
312 params["caption"] = config.Caption
313 }
314 if config.ReplyToMessageId != 0 {
315 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageId)
316 }
317 if config.ReplyMarkup != nil {
318 data, err := json.Marshal(config.ReplyMarkup)
319 if err != nil {
320 return Message{}, err
321 }
322
323 params["reply_markup"] = string(data)
324 }
325
326 resp, err := bot.UploadFile("SendPhoto", params, "photo", config.FilePath)
327 if err != nil {
328 return Message{}, err
329 }
330
331 var message Message
332 json.Unmarshal(resp.Result, &message)
333
334 if bot.Debug {
335 log.Printf("SendPhoto resp: %+v\n", message)
336 }
337
338 return message, nil
339}
340
341func (bot *BotApi) SendAudio(config AudioConfig) (Message, error) {
342 if config.UseExistingAudio {
343 v := url.Values{}
344 v.Add("chat_id", strconv.Itoa(config.ChatId))
345 v.Add("audio", config.FileId)
346 if config.ReplyToMessageId != 0 {
347 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
348 }
349 if config.ReplyMarkup != nil {
350 data, err := json.Marshal(config.ReplyMarkup)
351 if err != nil {
352 return Message{}, err
353 }
354
355 v.Add("reply_markup", string(data))
356 }
357
358 resp, err := bot.MakeRequest("sendAudio", v)
359 if err != nil {
360 return Message{}, err
361 }
362
363 var message Message
364 json.Unmarshal(resp.Result, &message)
365
366 if bot.Debug {
367 log.Printf("sendAudio req : %+v\n", v)
368 log.Printf("sendAudio resp: %+v\n", message)
369 }
370
371 return message, nil
372 }
373
374 params := make(map[string]string)
375
376 params["chat_id"] = strconv.Itoa(config.ChatId)
377 if config.ReplyToMessageId != 0 {
378 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageId)
379 }
380 if config.ReplyMarkup != nil {
381 data, err := json.Marshal(config.ReplyMarkup)
382 if err != nil {
383 return Message{}, err
384 }
385
386 params["reply_markup"] = string(data)
387 }
388
389 resp, err := bot.UploadFile("sendAudio", params, "audio", config.FilePath)
390 if err != nil {
391 return Message{}, err
392 }
393
394 var message Message
395 json.Unmarshal(resp.Result, &message)
396
397 if bot.Debug {
398 log.Printf("sendAudio resp: %+v\n", message)
399 }
400
401 return message, nil
402}
403
404func (bot *BotApi) SendDocument(config DocumentConfig) (Message, error) {
405 if config.UseExistingDocument {
406 v := url.Values{}
407 v.Add("chat_id", strconv.Itoa(config.ChatId))
408 v.Add("document", config.FileId)
409 if config.ReplyToMessageId != 0 {
410 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
411 }
412 if config.ReplyMarkup != nil {
413 data, err := json.Marshal(config.ReplyMarkup)
414 if err != nil {
415 return Message{}, err
416 }
417
418 v.Add("reply_markup", string(data))
419 }
420
421 resp, err := bot.MakeRequest("sendDocument", v)
422 if err != nil {
423 return Message{}, err
424 }
425
426 var message Message
427 json.Unmarshal(resp.Result, &message)
428
429 if bot.Debug {
430 log.Printf("sendDocument req : %+v\n", v)
431 log.Printf("sendDocument resp: %+v\n", message)
432 }
433
434 return message, nil
435 }
436
437 params := make(map[string]string)
438
439 params["chat_id"] = strconv.Itoa(config.ChatId)
440 if config.ReplyToMessageId != 0 {
441 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageId)
442 }
443 if config.ReplyMarkup != nil {
444 data, err := json.Marshal(config.ReplyMarkup)
445 if err != nil {
446 return Message{}, err
447 }
448
449 params["reply_markup"] = string(data)
450 }
451
452 resp, err := bot.UploadFile("sendDocument", params, "document", config.FilePath)
453 if err != nil {
454 return Message{}, err
455 }
456
457 var message Message
458 json.Unmarshal(resp.Result, &message)
459
460 if bot.Debug {
461 log.Printf("sendDocument resp: %+v\n", message)
462 }
463
464 return message, nil
465}
466
467func (bot *BotApi) SendSticker(config StickerConfig) (Message, error) {
468 if config.UseExistingSticker {
469 v := url.Values{}
470 v.Add("chat_id", strconv.Itoa(config.ChatId))
471 v.Add("sticker", config.FileId)
472 if config.ReplyToMessageId != 0 {
473 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
474 }
475 if config.ReplyMarkup != nil {
476 data, err := json.Marshal(config.ReplyMarkup)
477 if err != nil {
478 return Message{}, err
479 }
480
481 v.Add("reply_markup", string(data))
482 }
483
484 resp, err := bot.MakeRequest("sendSticker", v)
485 if err != nil {
486 return Message{}, err
487 }
488
489 var message Message
490 json.Unmarshal(resp.Result, &message)
491
492 if bot.Debug {
493 log.Printf("sendSticker req : %+v\n", v)
494 log.Printf("sendSticker resp: %+v\n", message)
495 }
496
497 return message, nil
498 }
499
500 params := make(map[string]string)
501
502 params["chat_id"] = strconv.Itoa(config.ChatId)
503 if config.ReplyToMessageId != 0 {
504 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageId)
505 }
506 if config.ReplyMarkup != nil {
507 data, err := json.Marshal(config.ReplyMarkup)
508 if err != nil {
509 return Message{}, err
510 }
511
512 params["reply_markup"] = string(data)
513 }
514
515 resp, err := bot.UploadFile("sendSticker", params, "sticker", config.FilePath)
516 if err != nil {
517 return Message{}, err
518 }
519
520 var message Message
521 json.Unmarshal(resp.Result, &message)
522
523 if bot.Debug {
524 log.Printf("sendSticker resp: %+v\n", message)
525 }
526
527 return message, nil
528}
529
530func (bot *BotApi) SendVideo(config VideoConfig) (Message, error) {
531 if config.UseExistingVideo {
532 v := url.Values{}
533 v.Add("chat_id", strconv.Itoa(config.ChatId))
534 v.Add("video", config.FileId)
535 if config.ReplyToMessageId != 0 {
536 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
537 }
538 if config.ReplyMarkup != nil {
539 data, err := json.Marshal(config.ReplyMarkup)
540 if err != nil {
541 return Message{}, err
542 }
543
544 v.Add("reply_markup", string(data))
545 }
546
547 resp, err := bot.MakeRequest("sendVideo", v)
548 if err != nil {
549 return Message{}, err
550 }
551
552 var message Message
553 json.Unmarshal(resp.Result, &message)
554
555 if bot.Debug {
556 log.Printf("sendVideo req : %+v\n", v)
557 log.Printf("sendVideo resp: %+v\n", message)
558 }
559
560 return message, nil
561 }
562
563 params := make(map[string]string)
564
565 params["chat_id"] = strconv.Itoa(config.ChatId)
566 if config.ReplyToMessageId != 0 {
567 params["reply_to_message_id"] = strconv.Itoa(config.ReplyToMessageId)
568 }
569 if config.ReplyMarkup != nil {
570 data, err := json.Marshal(config.ReplyMarkup)
571 if err != nil {
572 return Message{}, err
573 }
574
575 params["reply_markup"] = string(data)
576 }
577
578 resp, err := bot.UploadFile("sendVideo", params, "video", config.FilePath)
579 if err != nil {
580 return Message{}, err
581 }
582
583 var message Message
584 json.Unmarshal(resp.Result, &message)
585
586 if bot.Debug {
587 log.Printf("sendVideo resp: %+v\n", message)
588 }
589
590 return message, nil
591}
592
593func (bot *BotApi) SendLocation(config LocationConfig) (Message, error) {
594 v := url.Values{}
595 v.Add("chat_id", strconv.Itoa(config.ChatId))
596 v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
597 v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
598 if config.ReplyToMessageId != 0 {
599 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
600 }
601 if config.ReplyMarkup != nil {
602 data, err := json.Marshal(config.ReplyMarkup)
603 if err != nil {
604 return Message{}, err
605 }
606
607 v.Add("reply_markup", string(data))
608 }
609
610 resp, err := bot.MakeRequest("sendLocation", v)
611 if err != nil {
612 return Message{}, err
613 }
614
615 var message Message
616 json.Unmarshal(resp.Result, &message)
617
618 if bot.Debug {
619 log.Printf("sendLocation req : %+v\n", v)
620 log.Printf("sendLocation resp: %+v\n", message)
621 }
622
623 return message, nil
624}
625
626func (bot *BotApi) SendChatAction(config ChatActionConfig) error {
627 v := url.Values{}
628 v.Add("chat_id", strconv.Itoa(config.ChatId))
629 v.Add("action", config.Action)
630
631 _, err := bot.MakeRequest("sendChatAction", v)
632 if err != nil {
633 return err
634 }
635
636 return nil
637}
638
639func (bot *BotApi) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
640 v := url.Values{}
641 v.Add("user_id", strconv.Itoa(config.UserId))
642 if config.Offset != 0 {
643 v.Add("offset", strconv.Itoa(config.Offset))
644 }
645 if config.Limit != 0 {
646 v.Add("limit", strconv.Itoa(config.Limit))
647 }
648
649 resp, err := bot.MakeRequest("getUserProfilePhotos", v)
650 if err != nil {
651 return UserProfilePhotos{}, err
652 }
653
654 var profilePhotos UserProfilePhotos
655 json.Unmarshal(resp.Result, &profilePhotos)
656
657 if bot.Debug {
658 log.Printf("getUserProfilePhotos req : %+v\n", v)
659 log.Printf("getUserProfilePhotos resp: %+v\n", profilePhotos)
660 }
661
662 return profilePhotos, nil
663}
664
665func (bot *BotApi) GetUpdates(config UpdateConfig) ([]Update, error) {
666 v := url.Values{}
667 if config.Offset > 0 {
668 v.Add("offset", strconv.Itoa(config.Offset))
669 }
670 if config.Limit > 0 {
671 v.Add("limit", strconv.Itoa(config.Limit))
672 }
673 if config.Timeout > 0 {
674 v.Add("timeout", strconv.Itoa(config.Timeout))
675 }
676
677 resp, err := bot.MakeRequest("getUpdates", v)
678 if err != nil {
679 return []Update{}, err
680 }
681
682 var updates []Update
683 json.Unmarshal(resp.Result, &updates)
684
685 if bot.Debug {
686 log.Printf("getUpdates: %+v\n", updates)
687 }
688
689 return updates, nil
690}
691
692func (bot *BotApi) SetWebhook(config WebhookConfig) error {
693 v := url.Values{}
694 if !config.Clear {
695 v.Add("url", config.Url.String())
696 }
697
698 _, err := bot.MakeRequest("setWebhook", v)
699
700 return err
701}