all repos — telegram-bot-api @ cea0df2dae12eccb41669acd95203f3a691da2b0

Golang bindings for the Telegram Bot API

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}