Merge pull request #1 from tucnak/master

Merge with upstream
pull/79/head
Vlad Lukyanov 8 years ago committed by GitHub
commit ae8106fc82

@ -1,118 +1,131 @@
# Telebot
>Telebot is a convenient wrapper to Telegram Bots API, written in Golang.
>Telebot is a Telegram bot framework in Go.
[![GoDoc](https://godoc.org/github.com/tucnak/telebot?status.svg)](https://godoc.org/github.com/tucnak/telebot)
[![Travis](https://travis-ci.org/tucnak/telebot.svg?branch=master)](https://travis-ci.org/tucnak/telebot)
Bots are special Telegram accounts designed to handle messages automatically. Users can interact with bots by sending them command messages in private or group chats. These accounts serve as an interface for code running somewhere on your server.
Bots are special Telegram accounts designed to handle messages automatically. Users can interact with bots
by sending them command messages in private or group chats. These accounts serve as an interface for
code running somewhere on your server.
Telebot offers a convenient wrapper to Bots API, so you shouldn't even care about networking at all. Here is an example "helloworld" bot, written with telebot:
Telebot offers a convenient wrapper to Bots API, so you shouldn't even
bother about networking at all. You may install it with
go get github.com/tucnak/telebot
(after setting up your `GOPATH` properly).
We highly recommend you to keep your bot access token outside the code base,
preferably as an environmental variable:
export BOT_TOKEN=<your token here>
Take a look at a minimal functional bot setup:
```go
package main
import (
"time"
"github.com/tucnak/telebot"
"log"
"os"
"time"
"github.com/tucnak/telebot"
)
func main() {
bot, err := telebot.NewBot("SECRET TOKEN")
if err != nil {
log.Fatalln(err)
}
messages := make(chan telebot.Message)
bot.Listen(messages, 1*time.Second)
for message := range messages {
if message.Text == "/hi" {
bot.SendMessage(message.Chat,
"Hello, "+message.Sender.FirstName+"!", nil)
}
}
bot, err := telebot.NewBot(os.Getenv("BOT_TOKEN"))
if err != nil {
log.Fatalln(err)
}
messages := make(chan telebot.Message, 100)
bot.Listen(messages, 1*time.Second)
for message := range messages {
if message.Text == "/hi" {
bot.SendMessage(message.Chat,
"Hello, "+message.Sender.FirstName+"!", nil)
}
}
}
```
## Inline mode
As of January 4, 2016, Telegram added inline mode support for bots.
Telebot support inline mode in a fancy manner.
Here's a nice way to handle both incoming messages and inline queries:
As of January 4, 2016, Telegram added inline mode support for bots. Here's
a nice way to handle both incoming messages and inline queries in the meantime:
```go
package main
import (
"log"
"time"
"github.com/tucnak/telebot"
"log"
"time"
"os"
"github.com/tucnak/telebot"
)
var bot *telebot.Bot
func main() {
var err error
bot, err = telebot.NewBot("SECRET TOKEN")
if err != nil {
log.Fatalln(err)
}
bot, err := telebot.NewBot(os.Getenv("BOT_TOKEN"))
if err != nil {
log.Fatalln(err)
}
bot.Messages = make(chan telebot.Message, 1000)
bot.Queries = make(chan telebot.Query, 1000)
bot.Messages = make(chan telebot.Message, 100)
bot.Queries = make(chan telebot.Query, 1000)
go messages()
go queries()
go messages(bot)
go queries(bot)
bot.Start(1 * time.Second)
bot.Start(1 * time.Second)
}
func messages() {
for message := range bot.Messages {
log.Printf("Received a message from %s with the text: %s\n", message.Sender.Username, message.Text)
}
func messages(bot *telebot.Bot) {
for message := range bot.Messages {
log.Printf("Received a message from %s with the text: %s\n",
message.Sender.Username, message.Text)
}
}
func queries() {
for query := range bot.Queries {
log.Println("--- new query ---")
log.Println("from:", query.From.Username)
log.Println("text:", query.Text)
// Create an article (a link) object to show in our results.
article := &telebot.InlineQueryResultArticle{
Title: "Telegram bot framework written in Go",
URL: "https://github.com/tucnak/telebot",
InputMessageContent: &telebot.InputTextMessageContent{
Text: "Telebot is a convenient wrapper to Telegram Bots API, written in Golang.",
DisablePreview: false,
},
}
// Build the list of results. In this instance, just our 1 article from above.
results := []telebot.InlineQueryResult{article}
// Build a response object to answer the query.
response := telebot.QueryResponse{
Results: results,
IsPersonal: true,
}
// And finally send the response.
if err := bot.AnswerInlineQuery(&query, &response); err != nil {
log.Println("Failed to respond to query:", err)
}
}
func queries(bot *telebot.Bot) {
for query := range bot.Queries {
log.Println("--- new query ---")
log.Println("from:", query.From.Username)
log.Println("text:", query.Text)
// Create an article (a link) object to show in results.
article := &telebot.InlineQueryResultArticle{
Title: "Telebot",
URL: "https://github.com/tucnak/telebot",
InputMessageContent: &telebot.InputTextMessageContent{
Text: "Telebot is a Telegram bot framework.",
DisablePreview: false,
},
}
// Build the list of results (make sure to pass pointers!).
results := []telebot.InlineQueryResult{article}
// Build a response object to answer the query.
response := telebot.QueryResponse{
Results: results,
IsPersonal: true,
}
// Send it.
if err := bot.AnswerInlineQuery(&query, &response); err != nil {
log.Println("Failed to respond to query:", err)
}
}
}
```
## Files
Telebot lets you upload files from the file system:
```go
boom, err := telebot.NewFile("boom.ogg")
if err != nil {
return err
return err
}
audio := telebot.Audio{File: boom}
@ -123,22 +136,22 @@ err = bot.SendAudio(recipient, &audio, nil)
```
## Reply markup
Sometimes you wanna send a little complicated messages with some optional parameters. The third argument of all `Send*` methods accepts `telebot.SendOptions`, capable of defining an advanced reply markup:
```go
// Send a selective force reply message.
bot.SendMessage(user, "pong", &telebot.SendOptions{
ReplyMarkup: telebot.ReplyMarkup{
ForceReply: true,
Selective: true,
ReplyMarkup: telebot.ReplyMarkup{
ForceReply: true,
Selective: true,
CustomKeyboard: [][]string{
[]string{"1", "2", "3"},
[]string{"4", "5", "6"},
[]string{"7", "8", "9"},
[]string{"*", "0", "#"},
},
},
},
},
},
)
```

@ -145,10 +145,10 @@ func getMe(token string) (User, error) {
return User{}, fmt.Errorf("telebot: %s", botInfo.Description)
}
func getUpdates(token string, offset, timeout int) (upd []Update, err error) {
func getUpdates(token string, offset, timeout int64) (upd []Update, err error) {
params := map[string]string{
"offset": strconv.Itoa(offset),
"timeout": strconv.Itoa(timeout),
"offset": strconv.FormatInt(offset, 10),
"timeout": strconv.FormatInt(timeout, 10),
}
updatesJSON, err := sendCommand("getUpdates", token, params)
if err != nil {

267
bot.go

@ -49,12 +49,12 @@ func (b *Bot) poll(
callbacks chan Callback,
timeout time.Duration,
) {
latestUpdate := 0
var latestUpdate int64
for {
updates, err := getUpdates(b.Token,
latestUpdate+1,
int(timeout/time.Second),
int64(timeout/time.Second),
)
if err != nil {
@ -462,8 +462,8 @@ func (b *Bot) SendVenue(recipient Recipient, venue *Venue, options *SendOptions)
"longitude": fmt.Sprintf("%f", venue.Location.Longitude),
"title": venue.Title,
"address": venue.Address}
if venue.Foursquare_id != "" {
params["foursquare_id"] = venue.Foursquare_id
if venue.FoursquareID != "" {
params["foursquare_id"] = venue.FoursquareID
}
if options != nil {
@ -502,10 +502,10 @@ func (b *Bot) SendVenue(recipient Recipient, venue *Venue, options *SendOptions)
//
// Currently, Telegram supports only a narrow range of possible
// actions, these are aligned as constants of this package.
func (b *Bot) SendChatAction(recipient Recipient, action string) error {
func (b *Bot) SendChatAction(recipient Recipient, action ChatAction) error {
params := map[string]string{
"chat_id": recipient.Destination(),
"action": action,
"action": string(action),
}
responseJSON, err := sendCommand("sendChatAction", b.Token, params)
@ -592,3 +592,258 @@ func (b *Bot) AnswerInlineQuery(query *Query, response *QueryResponse) error {
return nil
}
// AnswerCallbackQuery sends a response for a given callback query. A callback can
// only be responded to once, subsequent attempts to respond to the same callback
// will result in an error.
func (b *Bot) AnswerCallbackQuery(callback *Callback, response *CallbackResponse) error {
response.CallbackID = callback.ID
responseJSON, err := sendCommand("answerCallbackQuery", b.Token, response)
if err != nil {
return err
}
var responseRecieved struct {
Ok bool
Description string
}
err = json.Unmarshal(responseJSON, &responseRecieved)
if err != nil {
return err
}
if !responseRecieved.Ok {
return fmt.Errorf("telebot: %s", responseRecieved.Description)
}
return nil
}
// GetFile returns full file object including File.FilePath, which allow you to load file from Telegram
//
// Usually File objects does not contain any FilePath so you need to perform additional request
func (b *Bot) GetFile(fileID string) (File, error) {
params := map[string]string{
"file_id": fileID,
}
responseJSON, err := sendCommand("getFile", b.Token, params)
if err != nil {
return File{}, err
}
var responseRecieved struct {
Ok bool
Description string
Result File
}
err = json.Unmarshal(responseJSON, &responseRecieved)
if err != nil {
return File{}, err
}
if !responseRecieved.Ok {
return File{}, fmt.Errorf("telebot: %s", responseRecieved.Description)
}
return responseRecieved.Result, nil
}
// LeaveChat makes bot leave a group, supergroup or channel.
func (b *Bot) LeaveChat(recipient Recipient) error {
params := map[string]string{
"chat_id": recipient.Destination(),
}
responseJSON, err := sendCommand("leaveChat", b.Token, params)
if err != nil {
return err
}
var responseRecieved struct {
Ok bool
Description string
Result bool
}
err = json.Unmarshal(responseJSON, &responseRecieved)
if err != nil {
return err
}
if !responseRecieved.Ok {
return fmt.Errorf("telebot: leaveChat failure %s",
responseRecieved.Description)
}
return nil
}
// GetChat get up to date information about the chat.
//
// Including current name of the user for one-on-one conversations,
// current username of a user, group or channel, etc.
//
// Returns a Chat object on success.
func (b *Bot) GetChat(recipient Recipient) (Chat, error) {
params := map[string]string{
"chat_id": recipient.Destination(),
}
responseJSON, err := sendCommand("getChat", b.Token, params)
if err != nil {
return Chat{}, err
}
var responseRecieved struct {
Ok bool
Description string
Result Chat
}
err = json.Unmarshal(responseJSON, &responseRecieved)
if err != nil {
return Chat{}, err
}
if !responseRecieved.Ok {
return Chat{}, fmt.Errorf("telebot: getChat failure %s",
responseRecieved.Description)
}
return responseRecieved.Result, nil
}
// GetChatAdministrators return list of administrators in a chat.
//
// On success, returns an Array of ChatMember objects that
// contains information about all chat administrators except other bots.
//
// If the chat is a group or a supergroup and
// no administrators were appointed, only the creator will be returned.
func (b *Bot) GetChatAdministrators(recipient Recipient) ([]ChatMember, error) {
params := map[string]string{
"chat_id": recipient.Destination(),
}
responseJSON, err := sendCommand("getChatAdministrators", b.Token, params)
if err != nil {
return []ChatMember{}, err
}
var responseRecieved struct {
Ok bool
Result []ChatMember
Description string `json:"description"`
}
err = json.Unmarshal(responseJSON, &responseRecieved)
if err != nil {
return []ChatMember{}, err
}
if !responseRecieved.Ok {
return []ChatMember{}, fmt.Errorf("telebot: getChatAdministrators failure %s", responseRecieved.Description)
}
return responseRecieved.Result, nil
}
// GetChatMembersCount return the number of members in a chat.
//
// Returns Int on success.
func (b *Bot) GetChatMembersCount(recipient Recipient) (int, error) {
params := map[string]string{
"chat_id": recipient.Destination(),
}
responseJSON, err := sendCommand("getChatMembersCount", b.Token, params)
if err != nil {
return 0, err
}
var responseRecieved struct {
Ok bool
Result int
Description string `json:"description"`
}
err = json.Unmarshal(responseJSON, &responseRecieved)
if err != nil {
return 0, err
}
if !responseRecieved.Ok {
return 0, fmt.Errorf("telebot: getChatMembersCount failure %s", responseRecieved.Description)
}
return responseRecieved.Result, nil
}
// GetUserProfilePhotos return list of profile pictures for a user.
//
// Returns a UserProfilePhotos object.
func (b *Bot) GetUserProfilePhotos(recipient Recipient) (UserProfilePhotos, error) {
params := map[string]string{
"user_id": recipient.Destination(),
}
responseJSON, err := sendCommand("getUserProfilePhotos", b.Token, params)
if err != nil {
return UserProfilePhotos{}, err
}
var responseRecieved struct {
Ok bool
Result UserProfilePhotos
Description string `json:"description"`
}
err = json.Unmarshal(responseJSON, &responseRecieved)
if err != nil {
return UserProfilePhotos{}, err
}
if !responseRecieved.Ok {
return UserProfilePhotos{}, fmt.Errorf("telebot: getUserProfilePhotos failure %s", responseRecieved.Description)
}
return responseRecieved.Result, nil
}
// GetChatMember return information about a member of a chat.
//
// Returns a ChatMember object on success.
func (b *Bot) GetChatMember(recipient Recipient, user User) (ChatMember, error) {
params := map[string]string{
"chat_id": recipient.Destination(),
"user_id": user.Destination(),
}
responseJSON, err := sendCommand("getChatMember", b.Token, params)
if err != nil {
return ChatMember{}, err
}
var responseRecieved struct {
Ok bool
Result ChatMember
Description string `json:"description"`
}
err = json.Unmarshal(responseJSON, &responseRecieved)
if err != nil {
return ChatMember{}, err
}
if !responseRecieved.Ok {
return ChatMember{}, fmt.Errorf("telebot: getChatMember failure %s", responseRecieved.Description)
}
return responseRecieved.Result, nil
}
// GetFileDirectURL returns direct url for files using FileId which you can get from File object
func (b *Bot) GetFileDirectURL(fileID string) (string, error) {
f, err := b.GetFile(fileID)
if err != nil {
return "", err
}
return "https://api.telegram.org/file/bot" + b.Token + "/" + f.FilePath, nil
}

@ -9,6 +9,7 @@ import (
type File struct {
FileID string `json:"file_id"`
FileSize int `json:"file_size"`
FilePath string `json:"file_path"`
// Local absolute path to file on local file system.
filename string

@ -1,9 +1,10 @@
package telebot
import (
"github.com/mitchellh/hashstructure"
"hash/fnv"
"strconv"
"github.com/mitchellh/hashstructure"
)
// inlineQueryHashOptions sets the HashOptions to be used when hashing
@ -83,7 +84,7 @@ func hashInlineQueryResult(result InlineQueryResult) (string, error) {
return strconv.FormatUint(hash, 16), nil
}
// Deprecated interface type, superseded by InlineQueryResult.
// Result is a deprecated type, superseded by InlineQueryResult.
type Result interface {
MarshalJSON() ([]byte, error)
}

@ -44,31 +44,31 @@ type InlineQueryResultArticle struct {
ThumbHeight int `json:"thumb_height,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultArticle InlineQueryResultArticle
func (r *InlineQueryResultArticle) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultArticle
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultArticle
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultArticle: wrappedInlineQueryResultArticle(*r),
ID: id,
Type: "article",
wrapper: wrapper(*r),
ID: id,
Type: "article",
})
}
func (r *InlineQueryResultArticle) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultAudio represents a link to an mp3 audio file.
@ -97,32 +97,32 @@ type InlineQueryResultAudio struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultAudio InlineQueryResultAudio
func (r *InlineQueryResultAudio) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultAudio
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultAudio
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultAudio: wrappedInlineQueryResultAudio(*r),
ID: id,
Type: "audio",
wrapper: wrapper(*r),
ID: id,
Type: "audio",
})
}
func (r *InlineQueryResultAudio) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultContact represents a contact with a phone number.
@ -158,32 +158,32 @@ type InlineQueryResultContact struct {
ThumbHeight int `json:"thumb_height,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultContact InlineQueryResultContact
func (r *InlineQueryResultContact) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultContact
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultContact
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultContact: wrappedInlineQueryResultContact(*r),
ID: id,
Type: "contact",
wrapper: wrapper(*r),
ID: id,
Type: "contact",
})
}
func (r *InlineQueryResultContact) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultDocument represents a link to a file.
@ -226,32 +226,32 @@ type InlineQueryResultDocument struct {
ThumbHeight int `json:"thumb_height,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultDocument InlineQueryResultDocument
func (r *InlineQueryResultDocument) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultDocument
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultDocument
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultDocument: wrappedInlineQueryResultDocument(*r),
ID: id,
Type: "document",
wrapper: wrapper(*r),
ID: id,
Type: "document",
})
}
func (r *InlineQueryResultDocument) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultGif represents a link to an animated GIF file.
@ -287,31 +287,32 @@ type InlineQueryResultGif struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultGif InlineQueryResultGif
func (r *InlineQueryResultGif) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultGif
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultGif
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultGif: wrappedInlineQueryResultGif(*r),
ID: id,
Type: "gif",
wrapper: wrapper(*r),
ID: id,
Type: "gif",
})
}
func (r *InlineQueryResultGif) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultLocation represents a location on a map.
@ -348,31 +349,32 @@ type InlineQueryResultLocation struct {
ThumbHeight int `json:"thumb_height,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultLocation InlineQueryResultLocation
func (r *InlineQueryResultLocation) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultLocation
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultLocation
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultLocation: wrappedInlineQueryResultLocation(*r),
ID: id,
Type: "location",
wrapper: wrapper(*r),
ID: id,
Type: "location",
})
}
func (r *InlineQueryResultLocation) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultMpeg4Gif represents a link to a video animation
@ -409,31 +411,32 @@ type InlineQueryResultMpeg4Gif struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultMpeg4Gif InlineQueryResultMpeg4Gif
func (r *InlineQueryResultMpeg4Gif) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultMpeg4Gif
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultMpeg4Gif
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultMpeg4Gif: wrappedInlineQueryResultMpeg4Gif(*r),
ID: id,
Type: "mpeg4_gif",
wrapper: wrapper(*r),
ID: id,
Type: "mpeg4_gif",
})
}
func (r *InlineQueryResultMpeg4Gif) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultPhoto represents a link to a photo.
@ -473,31 +476,32 @@ type InlineQueryResultPhoto struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultPhoto InlineQueryResultPhoto
func (r *InlineQueryResultPhoto) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultPhoto
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultPhoto
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultPhoto: wrappedInlineQueryResultPhoto(*r),
ID: id,
Type: "photo",
wrapper: wrapper(*r),
ID: id,
Type: "photo",
})
}
func (r *InlineQueryResultPhoto) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultVenue represents a venue.
@ -539,31 +543,32 @@ type InlineQueryResultVenue struct {
ThumbHeight int `json:"thumb_height,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultVenue InlineQueryResultVenue
func (r *InlineQueryResultVenue) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultVenue
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultVenue
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultVenue: wrappedInlineQueryResultVenue(*r),
ID: id,
Type: "venue",
wrapper: wrapper(*r),
ID: id,
Type: "venue",
})
}
func (r *InlineQueryResultVenue) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultVideo represents a link to a page containing an embedded
@ -609,31 +614,32 @@ type InlineQueryResultVideo struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultVideo InlineQueryResultVideo
func (r *InlineQueryResultVideo) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultVideo
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultVideo
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultVideo: wrappedInlineQueryResultVideo(*r),
ID: id,
Type: "video",
wrapper: wrapper(*r),
ID: id,
Type: "video",
})
}
func (r *InlineQueryResultVideo) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}
// InlineQueryResultVoice represents a link to a voice recording in a
@ -662,29 +668,30 @@ type InlineQueryResultVoice struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
}
// Used to avoid endless recursion in MarshalJSON.
type wrappedInlineQueryResultVoice InlineQueryResultVoice
func (r *InlineQueryResultVoice) MarshalJSON() ([]byte, error) {
// avoiding endless self-recursion
type wrapper InlineQueryResultVoice
id, err := r.id()
if err != nil {
return nil, err
}
return json.Marshal(struct {
wrappedInlineQueryResultVoice
wrapper
Type string `json:"type"`
ID string `json:"id",hash:"ignore"`
}{
wrappedInlineQueryResultVoice: wrappedInlineQueryResultVoice(*r),
ID: id,
Type: "voice",
wrapper: wrapper(*r),
ID: id,
Type: "voice",
})
}
func (r *InlineQueryResultVoice) id() (string, error) {
if r.ID == "" {
return hashInlineQueryResult(r)
} else {
return r.ID, nil
}
return r.ID, nil
}

@ -19,7 +19,7 @@ type InputTextMessageContent struct {
ParseMode string `json:"parse_mode,omitempty"`
// Optional. Disables link previews for links in the sent message.
DisablePreview bool `json:"disable_web_page_preview`
DisablePreview bool `json:"disable_web_page_preview"`
}
func (input *InputTextMessageContent) IsInputMessageContent() bool {

@ -128,6 +128,10 @@ type Message struct {
//
// Sender would lead to creator of the migration.
MigrateFrom int64 `json:"migrate_from_chat_id"`
Entities []MessageEntity `json:"entities,omitempty"`
Caption string `json:"caption,omitempty"`
}
// Origin returns an origin of message: group chat / personal.

@ -1,15 +1,5 @@
package telebot
// ParseMode determines the way client applications treat the text of the message
type ParseMode string
// Supported ParseMode
const (
ModeDefault ParseMode = ""
ModeMarkdown ParseMode = "Markdown"
ModeHTML ParseMode = "HTML"
)
// SendOptions represents a set of custom options that could
// be appled to messages sent.
type SendOptions struct {

@ -27,14 +27,52 @@
//
package telebot
// A bunch of available chat actions.
// ChatAction is a client-side status indicating bot activity.
type ChatAction string
const (
Typing ChatAction = "typing"
UploadingPhoto ChatAction = "upload_photo"
UploadingVideo ChatAction = "upload_video"
UploadingAudio ChatAction = "upload_audio"
UploadingDocument ChatAction = "upload_document"
RecordingVideo ChatAction = "record_video"
RecordingAudio ChatAction = "record_audio"
FindingLocation ChatAction = "find_location"
)
// ParseMode determines the way client applications treat the text of the message
type ParseMode string
const (
ModeDefault ParseMode = ""
ModeMarkdown ParseMode = "Markdown"
ModeHTML ParseMode = "HTML"
)
// EntityType is a MessageEntity type.
type EntityType string
const (
EntityMention EntityType = "mention"
EntityTMention EntityType = "text_mention"
EntityHashtag EntityType = "hashtag"
EntityCommand EntityType = "bot_command"
EntityURL EntityType = "url"
EntityEmail EntityType = "email"
EntityBold EntityType = "bold"
EntityItalic EntityType = "italic"
EntityCode EntityType = "code"
EntityCodeBlock EntityType = "pre"
EntityTextLink EntityType = "text_link"
)
// ChatType represents one of the possible chat types.
type ChatType string
const (
Typing = "typing"
UploadingPhoto = "upload_photo"
UploadingVideo = "upload_video"
UploadingAudio = "upload_audio"
UploadingDocument = "upload_document"
RecordingVideo = "record_video"
RecordingAudio = "record_audio"
FindingLocation = "find_location"
ChatPrivate ChatType = "private"
ChatGroup ChatType = "group"
ChatSuperGroup ChatType = "supergroup"
ChatChannel ChatType = "channel"
)

@ -26,13 +26,17 @@ func (u User) Destination() string {
}
// Chat object represents a Telegram user, bot or group chat.
// Title for channels and group chats
//
// Type of chat, can be either “private”, “group”, "supergroup" or “channel”
type Chat struct {
ID int64 `json:"id"`
Type string `json:"type"`
ID int64 `json:"id"`
// See telebot.ChatType and consts.
Type ChatType `json:"type"`
// Won't be there for ChatPrivate.
Title string `json:"title"`
Title string `json:"title"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Username string `json:"username"`
@ -54,7 +58,7 @@ func (c Chat) IsGroupChat() bool {
// Update object represents an incoming update.
type Update struct {
ID int `json:"update_id"`
ID int64 `json:"update_id"`
Payload *Message `json:"message"`
// optional
@ -86,7 +90,16 @@ type Audio struct {
// Duration of the recording in seconds as defined by sender.
Duration int `json:"duration"`
// MIME type of the file as defined by sender.
// FileSize (optional) of the audio file.
FileSize int `json:"file_size"`
// Title (optional) as defined by sender or by audio tags.
Title string `json:"title"`
// Performer (optional) is defined by sender or by audio tags.
Performer string `json:"performer"`
// MIME type (optional) of the file as defined by sender.
Mime string `json:"mime_type"`
}
@ -138,10 +151,11 @@ type KeyboardButton struct {
InlineQuery string `json:"switch_inline_query,omitempty"`
}
// InlineKeyboardMarkup represents an inline keyboard that appears right next
// to the message it belongs to.
// InlineKeyboardMarkup represents an inline keyboard that appears
// right next to the message it belongs to.
type InlineKeyboardMarkup struct {
// Array of button rows, each represented by an Array of KeyboardButton objects.
// Array of button rows, each represented by
// an Array of KeyboardButton objects.
InlineKeyboard [][]KeyboardButton `json:"inline_keyboard,omitempty"`
}
@ -155,8 +169,8 @@ type Contact struct {
// Location object represents geographic position.
type Location struct {
Longitude float32 `json:"longitude"`
Latitude float32 `json:"latitude"`
Longitude float32 `json:"longitude"`
}
// Callback object represents a query from a callback button in an
@ -174,13 +188,76 @@ type Callback struct {
// MessageID will be set if the button was attached to a message
// sent via the bot in inline mode.
MessageID string `json:"inline_message_id"`
Data string `json:"data"`
// Data associated with the callback button. Be aware that
// a bad client can send arbitrary data in this field.
Data string `json:"data"`
}
// CallbackResponse builds a response to a Callback query.
//
// See also: https://core.telegram.org/bots/api#answerCallbackQuery
type CallbackResponse struct {
// The ID of the callback to which this is a response.
// It is not necessary to specify this field manually.
CallbackID string `json:"callback_query_id"`
// Text of the notification. If not specified, nothing will be shown to the user.
Text string `json:"text,omitempty"`
// (Optional) If true, an alert will be shown by the client instead
// of a notification at the top of the chat screen. Defaults to false.
ShowAlert bool `json:"show_alert,omitempty"`
// (Optional) URL that will be opened by the user's client.
// If you have created a Game and accepted the conditions via @Botfather
// specify the URL that opens your game
// note that this will only work if the query comes from a callback_game button.
// Otherwise, you may use links like telegram.me/your_bot?start=XXXX that open your bot with a parameter.
URL string `json:"url,omitempty"`
}
// Venue object represents a venue location with name, address and optional foursquare id.
// Venue object represents a venue location with name, address and
// optional foursquare ID.
type Venue struct {
Location Location `json:"location"`
Title string `json:"title"`
Address string `json:"address"`
Foursquare_id string `json:"foursquare_id",omitempty`
Location Location `json:"location"`
Title string `json:"title"`
Address string `json:"address"`
FoursquareID string `json:"foursquare_id,omitempty"`
}
// MessageEntity object represents "special" parts of text messages,
// including hashtags, usernames, URLs, etc.
type MessageEntity struct {
// Specifies entity type.
Type EntityType `json:"type"`
// Offset in UTF-16 code units to the start of the entity.
Offset int `json:"offset"`
// Length of the entity in UTF-16 code units.
Length int `json:"length"`
// (Optional) For EntityTextLink entity type only.
//
// URL will be opened after user taps on the text.
URL string `json:"url,omitempty"`
// (Optional) For EntityTMention entity type only.
User User `json:"user,omitempty"`
}
// ChatMember object represents information about a single chat member.
type ChatMember struct {
User User `json:"user"`
Status string `json:"status"`
}
// UserProfilePhotos object represent a user's profile pictures.
type UserProfilePhotos struct {
// Total number of profile pictures the target user has.
Count int `json:"total_count"`
// Requested profile pictures (in up to 4 sizes each).
Photos [][]Photo `json:"photos"`
}

Loading…
Cancel
Save