types.go (view raw)
1package tgbotapi
2
3import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "net/url"
8 "strings"
9 "time"
10)
11
12// APIResponse is a response from the Telegram API with the result
13// stored raw.
14type APIResponse struct {
15 Ok bool `json:"ok"`
16 Result json.RawMessage `json:"result"`
17 ErrorCode int `json:"error_code"`
18 Description string `json:"description"`
19}
20
21// Update is an update response, from GetUpdates.
22type Update struct {
23 UpdateID int `json:"update_id"`
24 Message *Message `json:"message"`
25 EditedMessage *Message `json:"edited_message"`
26 InlineQuery *InlineQuery `json:"inline_query"`
27 ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"`
28 CallbackQuery *CallbackQuery `json:"callback_query"`
29}
30
31// User is a user on Telegram.
32type User struct {
33 ID int `json:"id"`
34 FirstName string `json:"first_name"`
35 LastName string `json:"last_name"` // optional
36 UserName string `json:"username"` // optional
37}
38
39// String displays a simple text version of a user.
40//
41// It is normally a user's username, but falls back to a first/last
42// name as available.
43func (u *User) String() string {
44 if u.UserName != "" {
45 return u.UserName
46 }
47
48 name := u.FirstName
49 if u.LastName != "" {
50 name += " " + u.LastName
51 }
52
53 return name
54}
55
56// GroupChat is a group chat.
57type GroupChat struct {
58 ID int `json:"id"`
59 Title string `json:"title"`
60}
61
62// Chat contains information about the place a message was sent.
63type Chat struct {
64 ID int64 `json:"id"`
65 Type string `json:"type"`
66 Title string `json:"title"` // optional
67 UserName string `json:"username"` // optional
68 FirstName string `json:"first_name"` // optional
69 LastName string `json:"last_name"` // optional
70}
71
72// IsPrivate returns if the Chat is a private conversation.
73func (c *Chat) IsPrivate() bool {
74 return c.Type == "private"
75}
76
77// IsGroup returns if the Chat is a group.
78func (c *Chat) IsGroup() bool {
79 return c.Type == "group"
80}
81
82// IsSuperGroup returns if the Chat is a supergroup.
83func (c *Chat) IsSuperGroup() bool {
84 return c.Type == "supergroup"
85}
86
87// IsChannel returns if the Chat is a channel.
88func (c *Chat) IsChannel() bool {
89 return c.Type == "channel"
90}
91
92// Message is returned by almost every request, and contains data about
93// almost anything.
94type Message struct {
95 MessageID int `json:"message_id"`
96 From *User `json:"from"` // optional
97 Date int `json:"date"`
98 Chat *Chat `json:"chat"`
99 ForwardFrom *User `json:"forward_from"` // optional
100 ForwardFromChat *Chat `json:"forward_from_chat"` // optional
101 ForwardDate int `json:"forward_date"` // optional
102 ReplyToMessage *Message `json:"reply_to_message"` // optional
103 EditDate int `json:"edit_date"` // optional
104 Text string `json:"text"` // optional
105 Entities *[]MessageEntity `json:"entities"` // optional
106 Audio *Audio `json:"audio"` // optional
107 Document *Document `json:"document"` // optional
108 Photo *[]PhotoSize `json:"photo"` // optional
109 Sticker *Sticker `json:"sticker"` // optional
110 Video *Video `json:"video"` // optional
111 Voice *Voice `json:"voice"` // optional
112 Caption string `json:"caption"` // optional
113 Contact *Contact `json:"contact"` // optional
114 Location *Location `json:"location"` // optional
115 Venue *Venue `json:"venue"` // optional
116 NewChatMember *User `json:"new_chat_member"` // optional
117 LeftChatMember *User `json:"left_chat_member"` // optional
118 NewChatTitle string `json:"new_chat_title"` // optional
119 NewChatPhoto *[]PhotoSize `json:"new_chat_photo"` // optional
120 DeleteChatPhoto bool `json:"delete_chat_photo"` // optional
121 GroupChatCreated bool `json:"group_chat_created"` // optional
122 SuperGroupChatCreated bool `json:"supergroup_chat_created"` // optional
123 ChannelChatCreated bool `json:"channel_chat_created"` // optional
124 MigrateToChatID int64 `json:"migrate_to_chat_id"` // optional
125 MigrateFromChatID int64 `json:"migrate_from_chat_id"` // optional
126 PinnedMessage *Message `json:"pinned_message"` // optional
127}
128
129// Time converts the message timestamp into a Time.
130func (m *Message) Time() time.Time {
131 return time.Unix(int64(m.Date), 0)
132}
133
134// IsCommand returns true if message starts with '/'.
135func (m *Message) IsCommand() bool {
136 return m.Text != "" && m.Text[0] == '/'
137}
138
139// Command checks if the message was a command and if it was, returns the
140// command. If the Message was not a command, it returns an empty string.
141//
142// If the command contains the at bot syntax, it removes the bot name.
143func (m *Message) Command() string {
144 if !m.IsCommand() {
145 return ""
146 }
147
148 command := strings.SplitN(m.Text, " ", 2)[0][1:]
149
150 if i := strings.Index(command, "@"); i != -1 {
151 command = command[:i]
152 }
153
154 return command
155}
156
157// CommandArguments checks if the message was a command and if it was,
158// returns all text after the command name. If the Message was not a
159// command, it returns an empty string.
160func (m *Message) CommandArguments() string {
161 if !m.IsCommand() {
162 return ""
163 }
164
165 split := strings.SplitN(m.Text, " ", 2)
166 if len(split) != 2 {
167 return ""
168 }
169
170 return strings.SplitN(m.Text, " ", 2)[1]
171}
172
173// MessageEntity contains information about data in a Message.
174type MessageEntity struct {
175 Type string `json:"type"`
176 Offset int `json:"offset"`
177 Length int `json:"length"`
178 URL string `json:"url"` // optional
179 User *User `json:"user"` // optional
180}
181
182// ParseURL attempts to parse a URL contained within a MessageEntity.
183func (entity MessageEntity) ParseURL() (*url.URL, error) {
184 if entity.URL == "" {
185 return nil, errors.New(ErrBadURL)
186 }
187
188 return url.Parse(entity.URL)
189}
190
191// PhotoSize contains information about photos.
192type PhotoSize struct {
193 FileID string `json:"file_id"`
194 Width int `json:"width"`
195 Height int `json:"height"`
196 FileSize int `json:"file_size"` // optional
197}
198
199// Audio contains information about audio.
200type Audio struct {
201 FileID string `json:"file_id"`
202 Duration int `json:"duration"`
203 Performer string `json:"performer"` // optional
204 Title string `json:"title"` // optional
205 MimeType string `json:"mime_type"` // optional
206 FileSize int `json:"file_size"` // optional
207}
208
209// Document contains information about a document.
210type Document struct {
211 FileID string `json:"file_id"`
212 Thumbnail *PhotoSize `json:"thumb"` // optional
213 FileName string `json:"file_name"` // optional
214 MimeType string `json:"mime_type"` // optional
215 FileSize int `json:"file_size"` // optional
216}
217
218// Sticker contains information about a sticker.
219type Sticker struct {
220 FileID string `json:"file_id"`
221 Width int `json:"width"`
222 Height int `json:"height"`
223 Thumbnail *PhotoSize `json:"thumb"` // optional
224 Emoji string `json:"emoji"` // optional
225 FileSize int `json:"file_size"` // optional
226}
227
228// Video contains information about a video.
229type Video struct {
230 FileID string `json:"file_id"`
231 Width int `json:"width"`
232 Height int `json:"height"`
233 Duration int `json:"duration"`
234 Thumbnail *PhotoSize `json:"thumb"` // optional
235 MimeType string `json:"mime_type"` // optional
236 FileSize int `json:"file_size"` // optional
237}
238
239// Voice contains information about a voice.
240type Voice struct {
241 FileID string `json:"file_id"`
242 Duration int `json:"duration"`
243 MimeType string `json:"mime_type"` // optional
244 FileSize int `json:"file_size"` // optional
245}
246
247// Contact contains information about a contact.
248//
249// Note that LastName and UserID may be empty.
250type Contact struct {
251 PhoneNumber string `json:"phone_number"`
252 FirstName string `json:"first_name"`
253 LastName string `json:"last_name"` // optional
254 UserID int `json:"user_id"` // optional
255}
256
257// Location contains information about a place.
258type Location struct {
259 Longitude float64 `json:"longitude"`
260 Latitude float64 `json:"latitude"`
261}
262
263// Venue contains information about a venue, including its Location.
264type Venue struct {
265 Location Location `json:"location"`
266 Title string `json:"title"`
267 Address string `json:"address"`
268 FoursquareID string `json:"foursquare_id"` // optional
269}
270
271// UserProfilePhotos contains a set of user profile photos.
272type UserProfilePhotos struct {
273 TotalCount int `json:"total_count"`
274 Photos [][]PhotoSize `json:"photos"`
275}
276
277// File contains information about a file to download from Telegram.
278type File struct {
279 FileID string `json:"file_id"`
280 FileSize int `json:"file_size"` // optional
281 FilePath string `json:"file_path"` // optional
282}
283
284// Link returns a full path to the download URL for a File.
285//
286// It requires the Bot Token to create the link.
287func (f *File) Link(token string) string {
288 return fmt.Sprintf(FileEndpoint, token, f.FilePath)
289}
290
291// ReplyKeyboardMarkup allows the Bot to set a custom keyboard.
292type ReplyKeyboardMarkup struct {
293 Keyboard [][]KeyboardButton `json:"keyboard"`
294 ResizeKeyboard bool `json:"resize_keyboard"` // optional
295 OneTimeKeyboard bool `json:"one_time_keyboard"` // optional
296 Selective bool `json:"selective"` // optional
297}
298
299// KeyboardButton is a button within a custom keyboard.
300type KeyboardButton struct {
301 Text string `json:"text"`
302 RequestContact bool `json:"request_contact"`
303 RequestLocation bool `json:"request_location"`
304}
305
306// ReplyKeyboardHide allows the Bot to hide a custom keyboard.
307type ReplyKeyboardHide struct {
308 HideKeyboard bool `json:"hide_keyboard"`
309 Selective bool `json:"selective"` // optional
310}
311
312// InlineKeyboardMarkup is a custom keyboard presented for an inline bot.
313type InlineKeyboardMarkup struct {
314 InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"`
315}
316
317// InlineKeyboardButton is a button within a custom keyboard for
318// inline query responses.
319//
320// Note that some values are references as even an empty string
321// will change behavior.
322type InlineKeyboardButton struct {
323 Text string `json:"text"`
324 URL *string `json:"url,omitempty"` // optional
325 CallbackData *string `json:"callback_data,omitempty"` // optional
326 SwitchInlineQuery *string `json:"switch_inline_query,omitempty"` // optional
327}
328
329// CallbackQuery is data sent when a keyboard button with callback data
330// is clicked.
331type CallbackQuery struct {
332 ID string `json:"id"`
333 From *User `json:"from"`
334 Message *Message `json:"message"` // optional
335 InlineMessageID string `json:"inline_message_id"` // optional
336 Data string `json:"data"` // optional
337}
338
339// ForceReply allows the Bot to have users directly reply to it without
340// additional interaction.
341type ForceReply struct {
342 ForceReply bool `json:"force_reply"`
343 Selective bool `json:"selective"` // optional
344}
345
346// InlineQuery is a Query from Telegram for an inline request.
347type InlineQuery struct {
348 ID string `json:"id"`
349 From *User `json:"from"`
350 Location *Location `json:"location"` // optional
351 Query string `json:"query"`
352 Offset string `json:"offset"`
353}
354
355// InlineQueryResultArticle is an inline query response article.
356type InlineQueryResultArticle struct {
357 Type string `json:"type"` // required
358 ID string `json:"id"` // required
359 Title string `json:"title"` // required
360 InputMessageContent interface{} `json:"input_message_content,omitempty"` // required
361 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
362 URL string `json:"url"`
363 HideURL bool `json:"hide_url"`
364 Description string `json:"description"`
365 ThumbURL string `json:"thumb_url"`
366 ThumbWidth int `json:"thumb_width"`
367 ThumbHeight int `json:"thumb_height"`
368}
369
370// InlineQueryResultPhoto is an inline query response photo.
371type InlineQueryResultPhoto struct {
372 Type string `json:"type"` // required
373 ID string `json:"id"` // required
374 URL string `json:"photo_url"` // required
375 MimeType string `json:"mime_type"`
376 Width int `json:"photo_width"`
377 Height int `json:"photo_height"`
378 ThumbURL string `json:"thumb_url"`
379 Title string `json:"title"`
380 Description string `json:"description"`
381 Caption string `json:"caption"`
382 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
383 InputMessageContent interface{} `json:"input_message_content,omitempty"`
384}
385
386// InlineQueryResultGIF is an inline query response GIF.
387type InlineQueryResultGIF struct {
388 Type string `json:"type"` // required
389 ID string `json:"id"` // required
390 URL string `json:"gif_url"` // required
391 Width int `json:"gif_width"`
392 Height int `json:"gif_height"`
393 ThumbURL string `json:"thumb_url"`
394 Title string `json:"title"`
395 Caption string `json:"caption"`
396 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
397 InputMessageContent interface{} `json:"input_message_content,omitempty"`
398}
399
400// InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF.
401type InlineQueryResultMPEG4GIF struct {
402 Type string `json:"type"` // required
403 ID string `json:"id"` // required
404 URL string `json:"mpeg4_url"` // required
405 Width int `json:"mpeg4_width"`
406 Height int `json:"mpeg4_height"`
407 ThumbURL string `json:"thumb_url"`
408 Title string `json:"title"`
409 Caption string `json:"caption"`
410 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
411 InputMessageContent interface{} `json:"input_message_content,omitempty"`
412}
413
414// InlineQueryResultVideo is an inline query response video.
415type InlineQueryResultVideo struct {
416 Type string `json:"type"` // required
417 ID string `json:"id"` // required
418 URL string `json:"video_url"` // required
419 MimeType string `json:"mime_type"` // required
420 ThumbURL string `json:"thumb_url"`
421 Title string `json:"title"`
422 Caption string `json:"caption"`
423 Width int `json:"video_width"`
424 Height int `json:"video_height"`
425 Duration int `json:"video_duration"`
426 Description string `json:"description"`
427 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
428 InputMessageContent interface{} `json:"input_message_content,omitempty"`
429}
430
431// InlineQueryResultAudio is an inline query response audio.
432type InlineQueryResultAudio struct {
433 Type string `json:"type"` // required
434 ID string `json:"id"` // required
435 URL string `json:"audio_url"` // required
436 Title string `json:"title"` // required
437 Performer string `json:"performer"`
438 Duration int `json:"audio_duration"`
439 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
440 InputMessageContent interface{} `json:"input_message_content,omitempty"`
441}
442
443// InlineQueryResultVoice is an inline query response voice.
444type InlineQueryResultVoice struct {
445 Type string `json:"type"` // required
446 ID string `json:"id"` // required
447 URL string `json:"voice_url"` // required
448 Title string `json:"title"` // required
449 Duration int `json:"voice_duration"`
450 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
451 InputMessageContent interface{} `json:"input_message_content,omitempty"`
452}
453
454// InlineQueryResultDocument is an inline query response document.
455type InlineQueryResultDocument struct {
456 Type string `json:"type"` // required
457 ID string `json:"id"` // required
458 Title string `json:"title"` // required
459 Caption string `json:"caption"`
460 URL string `json:"document_url"` // required
461 MimeType string `json:"mime_type"` // required
462 Description string `json:"description"`
463 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
464 InputMessageContent interface{} `json:"input_message_content,omitempty"`
465 ThumbURL string `json:"thumb_url"`
466 ThumbWidth int `json:"thumb_width"`
467 ThumbHeight int `json:"thumb_height"`
468}
469
470// InlineQueryResultLocation is an inline query response location.
471type InlineQueryResultLocation struct {
472 Type string `json:"type"` // required
473 ID string `json:"id"` // required
474 Latitude float64 `json:"latitude"` // required
475 Longitude float64 `json:"longitude"` // required
476 Title string `json:"title"` // required
477 ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
478 InputMessageContent interface{} `json:"input_message_content,omitempty"`
479 ThumbURL string `json:"thumb_url"`
480 ThumbWidth int `json:"thumb_width"`
481 ThumbHeight int `json:"thumb_height"`
482}
483
484// ChosenInlineResult is an inline query result chosen by a User
485type ChosenInlineResult struct {
486 ResultID string `json:"result_id"`
487 From *User `json:"from"`
488 Location *Location `json:"location"`
489 InlineMessageID string `json:"inline_message_id"`
490 Query string `json:"query"`
491}
492
493// InputTextMessageContent contains text for displaying
494// as an inline query result.
495type InputTextMessageContent struct {
496 Text string `json:"message_text"`
497 ParseMode string `json:"parse_mode"`
498 DisableWebPagePreview bool `json:"disable_web_page_preview"`
499}
500
501// InputLocationMessageContent contains a location for displaying
502// as an inline query result.
503type InputLocationMessageContent struct {
504 Latitude float64 `json:"latitude"`
505 Longitude float64 `json:"longitude"`
506}
507
508// InputVenueMessageContent contains a venue for displaying
509// as an inline query result.
510type InputVenueMessageContent struct {
511 Latitude float64 `json:"latitude"`
512 Longitude float64 `json:"longitude"`
513 Title string `json:"title"`
514 Address string `json:"address"`
515 FoursquareID string `json:"foursquare_id"`
516}
517
518// InputContactMessageContent contains a contact for displaying
519// as an inline query result.
520type InputContactMessageContent struct {
521 PhoneNumber string `json:"phone_number"`
522 FirstName string `json:"first_name"`
523 LastName string `json:"last_name"`
524}