methods.go (view raw)
1package main
2
3import (
4 "encoding/json"
5 "io/ioutil"
6 "log"
7 "net/http"
8 "net/url"
9 "strconv"
10)
11
12const (
13 CHAT_TYPING = "typing"
14 CHAT_UPLOAD_PHOTO = "upload_photo"
15 CHAT_RECORD_VIDEO = "record_video"
16 CHAT_UPLOAD_VIDEO = "upload_video"
17 CHAT_RECORD_AUDIO = "record_audio"
18 CHAT_UPLOAD_AUDIO = "upload_audio"
19 CHAT_UPLOAD_DOCUMENT = "upload_document"
20 CHAT_FIND_LOCATION = "find_location"
21)
22
23type BotConfig struct {
24 token string
25 debug bool
26}
27
28type BotApi struct {
29 config BotConfig
30}
31
32type ApiResponse struct {
33 Ok bool `json:"ok"`
34 Result json.RawMessage `json:"result"`
35}
36
37type Update struct {
38 UpdateId int `json:"update_id"`
39 Message Message `json:"message"`
40}
41
42type User struct {
43 Id int `json:"id"`
44 FirstName string `json:"first_name"`
45 LastName string `json:"last_name"`
46 UserName string `json:"username"`
47}
48
49type GroupChat struct {
50 Id int `json:"id"`
51 Title string `json:"title"`
52}
53
54type UserOrGroupChat struct {
55 Id int `json:"id"`
56 FirstName string `json:"first_name"`
57 LastName string `json:"last_name"`
58 UserName string `json:"username"`
59 Title string `json:"title"`
60}
61
62type Message struct {
63 MessageId int `json:"message_id"`
64 From User `json:"from"`
65 Date int `json:"date"`
66 Chat UserOrGroupChat `json:"chat"`
67 ForwardFrom User `json:"forward_from"`
68 ForwardDate int `json:"forward_date"`
69 ReplyToMessage *Message `json:"reply_to_message"`
70 Text string `json:"text"`
71 Audio Audio `json:"audio"`
72 Document Document `json:"document"`
73 Photo []PhotoSize `json:"photo"`
74 Sticker Sticker `json:"sticker"`
75 Video Video `json:"video"`
76 Contact Contact `json:"contact"`
77 Location Location `json:"location"`
78 NewChatParticipant User `json:"new_chat_participant"`
79 LeftChatParticipant User `json:"left_chat_participant"`
80 NewChatTitle string `json:"new_chat_title"`
81 NewChatPhoto string `json:"new_chat_photo"`
82 DeleteChatPhoto bool `json:"delete_chat_photo"`
83 GroupChatCreated bool `json:"group_chat_created"`
84}
85
86type PhotoSize struct {
87 FileId string `json:"file_id"`
88 Width int `json:"width"`
89 Height int `json:"height"`
90 FileSize int `json:"file_size"`
91}
92
93type Audio struct {
94 FileId string `json:"file_id"`
95 Duration int `json:"duration"`
96 MimeType string `json:"mime_type"`
97 FileSize int `json:"file_size"`
98}
99
100type Document struct {
101 FileId string `json:"file_id"`
102 Thumb PhotoSize `json:"thumb"`
103 FileName string `json:"file_name"`
104 MimeType string `json:"mime_type"`
105 FileSize int `json:"file_size"`
106}
107
108type Sticker struct {
109 FileId string `json:"file_id"`
110 Width int `json:"width"`
111 Height int `json:"height"`
112 Thumb PhotoSize `json:"thumb"`
113 FileSize int `json:"file_size"`
114}
115
116type Video struct {
117 FileId string `json:"file_id"`
118 Width int `json:"width"`
119 Height int `json:"height"`
120 Duration int `json:"duration"`
121 Thumb PhotoSize `json:"thumb"`
122 MimeType string `json:"mime_type"`
123 FileSize int `json:"file_size"`
124 Caption string `json:"caption"`
125}
126
127type Contact struct {
128 PhoneNumber string `json:"phone_number"`
129 FirstName string `json:"first_name"`
130 LastName string `json:"last_name"`
131 UserId string `json:"user_id"`
132}
133
134type Location struct {
135 Longitude float32 `json:"longitude"`
136 Latitude float32 `json:"latitude"`
137}
138
139type UserProfilePhotos struct {
140 TotalCount int `json:"total_count"`
141 Photos []PhotoSize `json:"photos"`
142}
143
144type ReplyKeyboardMarkup struct {
145 Keyboard map[string]map[string]string `json:"keyboard"`
146 ResizeKeyboard bool `json:"resize_keyboard"`
147 OneTimeKeyboard bool `json:"one_time_keyboard"`
148 Selective bool `json:"selective"`
149}
150
151type ReplyKeyboardHide struct {
152 HideKeyboard bool `json:"hide_keyboard"`
153 Selective bool `json:"selective"`
154}
155
156type ForceReply struct {
157 ForceReply bool `json:"force_reply"`
158 Selective bool `json:"force_reply"`
159}
160
161type UpdateConfig struct {
162 Offset int
163 Limit int
164 Timeout int
165}
166
167type MessageConfig struct {
168 ChatId int
169 Text string
170 DisableWebPagePreview bool
171 ReplyToMessageId int
172}
173
174type ForwardConfig struct {
175 ChatId int
176 FromChatId int
177 MessageId int
178}
179
180type LocationConfig struct {
181 ChatId int
182 Latitude float64
183 Longitude float64
184 ReplyToMessageId int
185 ReplyMarkup interface{}
186}
187
188type ChatActionConfig struct {
189 ChatId int
190 Action string
191}
192
193type UserProfilePhotosConfig struct {
194 UserId int
195 Offset int
196 Limit int
197}
198
199func NewBotApi(config BotConfig) *BotApi {
200 return &BotApi{
201 config: config,
202 }
203}
204
205func (bot *BotApi) makeRequest(endpoint string, params url.Values) (ApiResponse, error) {
206 resp, err := http.PostForm("https://api.telegram.org/bot"+bot.config.token+"/"+endpoint, params)
207 defer resp.Body.Close()
208 if err != nil {
209 return ApiResponse{}, err
210 }
211
212 bytes, err := ioutil.ReadAll(resp.Body)
213 if err != nil {
214 return ApiResponse{}, nil
215 }
216
217 if bot.config.debug {
218 log.Println(string(bytes[:]))
219 }
220
221 var apiResp ApiResponse
222 json.Unmarshal(bytes, &apiResp)
223
224 return apiResp, nil
225}
226
227func (bot *BotApi) getMe() (User, error) {
228 resp, err := bot.makeRequest("getMe", nil)
229 if err != nil {
230 return User{}, err
231 }
232
233 var user User
234 json.Unmarshal(resp.Result, &user)
235
236 if bot.config.debug {
237 log.Printf("getMe: %+v\n", user)
238 }
239
240 return user, nil
241}
242
243func (bot *BotApi) sendMessage(config MessageConfig) (Message, error) {
244 v := url.Values{}
245 v.Add("chat_id", strconv.Itoa(config.ChatId))
246 v.Add("text", config.Text)
247 v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
248 if config.ReplyToMessageId != 0 {
249 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
250 }
251
252 resp, err := bot.makeRequest("sendMessage", v)
253 if err != nil {
254 return Message{}, err
255 }
256
257 var message Message
258 json.Unmarshal(resp.Result, &message)
259
260 if bot.config.debug {
261 log.Printf("sendMessage req : %+v\n", v)
262 log.Printf("sendMessage resp: %+v\n", message)
263 }
264
265 return message, nil
266}
267
268func (bot *BotApi) forwardMessage(config ForwardConfig) (Message, error) {
269 v := url.Values{}
270 v.Add("chat_id", strconv.Itoa(config.ChatId))
271 v.Add("from_chat_id", strconv.Itoa(config.FromChatId))
272 v.Add("message_id", strconv.Itoa(config.MessageId))
273
274 resp, err := bot.makeRequest("forwardMessage", v)
275 if err != nil {
276 return Message{}, err
277 }
278
279 var message Message
280 json.Unmarshal(resp.Result, &message)
281
282 if bot.config.debug {
283 log.Printf("forwardMessage req : %+v\n", v)
284 log.Printf("forwardMessage resp: %+v\n", message)
285 }
286
287 return message, nil
288}
289
290func (bot *BotApi) sendLocation(config LocationConfig) (Message, error) {
291 v := url.Values{}
292 v.Add("chat_id", strconv.Itoa(config.ChatId))
293 v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
294 v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
295 if config.ReplyToMessageId != 0 {
296 v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
297 }
298 if config.ReplyMarkup != nil {
299 data, err := json.Marshal(config.ReplyMarkup)
300 if err != nil {
301 return Message{}, err
302 }
303
304 v.Add("reply_markup", string(data))
305 }
306
307 resp, err := bot.makeRequest("sendLocation", v)
308 if err != nil {
309 return Message{}, err
310 }
311
312 var message Message
313 json.Unmarshal(resp.Result, &message)
314
315 if bot.config.debug {
316 log.Printf("sendLocation req : %+v\n", v)
317 log.Printf("sendLocation resp: %+v\n", message)
318 }
319
320 return message, nil
321}
322
323func (bot *BotApi) sendChatAction(config ChatActionConfig) error {
324 v := url.Values{}
325 v.Add("chat_id", strconv.Itoa(config.ChatId))
326 v.Add("action", config.Action)
327
328 _, err := bot.makeRequest("sendChatAction", v)
329 if err != nil {
330 return err
331 }
332
333 return nil
334}
335
336func (bot *BotApi) getUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
337 v := url.Values{}
338 v.Add("user_id", strconv.Itoa(config.UserId))
339 if config.Offset != 0 {
340 v.Add("offset", strconv.Itoa(config.Offset))
341 }
342 if config.Limit != 0 {
343 v.Add("limit", strconv.Itoa(config.Limit))
344 }
345
346 resp, err := bot.makeRequest("getUserProfilePhotos", v)
347 if err != nil {
348 return UserProfilePhotos{}, err
349 }
350
351 var profilePhotos UserProfilePhotos
352 json.Unmarshal(resp.Result, &profilePhotos)
353
354 if bot.config.debug {
355 log.Printf("getUserProfilePhotos req : %+v\n", v)
356 log.Printf("getUserProfilePhotos resp: %+v\n", profilePhotos)
357 }
358
359 return profilePhotos, nil
360}
361
362func (bot *BotApi) getUpdates(config UpdateConfig) ([]Update, error) {
363 v := url.Values{}
364 if config.Offset > 0 {
365 v.Add("offset", strconv.Itoa(config.Offset))
366 }
367 if config.Limit > 0 {
368 v.Add("limit", strconv.Itoa(config.Limit))
369 }
370 if config.Timeout > 0 {
371 v.Add("timeout", strconv.Itoa(config.Timeout))
372 }
373
374 resp, err := bot.makeRequest("getUpdates", v)
375 if err != nil {
376 return []Update{}, err
377 }
378
379 var updates []Update
380 json.Unmarshal(resp.Result, &updates)
381
382 if bot.config.debug {
383 log.Printf("getUpdates: %+v\n", updates)
384 }
385
386 return updates, nil
387}
388
389func (bot *BotApi) setWebhook(v url.Values) error {
390 _, err := bot.makeRequest("setWebhook", v)
391
392 return err
393}
394
395func NewMessage(chatId int, text string) MessageConfig {
396 return MessageConfig{
397 ChatId: chatId,
398 Text: text,
399 DisableWebPagePreview: false,
400 ReplyToMessageId: 0,
401 }
402}
403
404func NewForward(chatId int, fromChatId int, messageId int) ForwardConfig {
405 return ForwardConfig{
406 ChatId: chatId,
407 FromChatId: fromChatId,
408 MessageId: messageId,
409 }
410}
411
412func NewLocation(chatId int, latitude float64, longitude float64) LocationConfig {
413 return LocationConfig{
414 ChatId: chatId,
415 Latitude: latitude,
416 Longitude: longitude,
417 ReplyToMessageId: 0,
418 ReplyMarkup: nil,
419 }
420}
421
422func NewChatAction(chatId int, action string) ChatActionConfig {
423 return ChatActionConfig{
424 ChatId: chatId,
425 Action: action,
426 }
427}
428
429func NewUserProfilePhotos(userId int) UserProfilePhotosConfig {
430 return UserProfilePhotosConfig{
431 UserId: userId,
432 Offset: 0,
433 Limit: 0,
434 }
435}
436
437func NewUpdate(offset int) UpdateConfig {
438 return UpdateConfig{
439 Offset: offset,
440 Limit: 0,
441 Timeout: 0,
442 }
443}