Move bot config to separate struct.

This commit is contained in:
Ilja Lapkovskis 2024-01-28 00:16:53 +02:00
parent aa0cdf3719
commit 1b1af39b61
No known key found for this signature in database
GPG key ID: 53D2AA4F0D1079C4
8 changed files with 353 additions and 286 deletions

110
bot.go
View file

@ -14,66 +14,56 @@ import (
"time" "time"
) )
// HTTPClient is the type needed for the bot to perform HTTP requests. const DefaultBufferSize = 100
type HTTPClient interface {
// HTTPClientI is the type needed for the bot to perform HTTP requests.
type HTTPClientI interface {
Do(req *http.Request) (*http.Response, error) Do(req *http.Request) (*http.Response, error)
} }
// BotAPI allows you to interact with the Telegram Bot API. // BotAPI allows you to interact with the Telegram Bot API.
type BotAPI struct { type BotAPI struct {
Token string `json:"token"` config BotConfigI
Debug bool `json:"debug"` client HTTPClientI
Buffer int `json:"buffer"` readonly bool
Self User `json:"-"` buffer int
Client HTTPClient `json:"-"`
shutdownChannel chan interface{} shutdownChannel chan interface{}
apiEndpoint string
} }
// NewBotAPI creates a new BotAPI instance. // NewBot creates a new BotAPI instance.
// //
// It requires a token, provided by @BotFather on Telegram. // It requires a token, provided by @BotFather on Telegram.
func NewBotAPI(token string) (*BotAPI, error) { func NewBot(config BotConfigI) *BotAPI {
return NewBotAPIWithClient(token, APIEndpoint, &http.Client{}) return NewBotWithClient(config, &http.Client{})
} }
// NewBotAPIWithAPIEndpoint creates a new BotAPI instance // NewBotWithClient creates a new BotAPI instance
// and allows you to pass API endpoint.
//
// It requires a token, provided by @BotFather on Telegram and API endpoint.
func NewBotAPIWithAPIEndpoint(token, apiEndpoint string) (*BotAPI, error) {
return NewBotAPIWithClient(token, apiEndpoint, &http.Client{})
}
// NewBotAPIWithClient creates a new BotAPI instance
// and allows you to pass a http.Client. // and allows you to pass a http.Client.
// //
// It requires a token, provided by @BotFather on Telegram and API endpoint. // It requires a token, provided by @BotFather on Telegram and API endpoint.
func NewBotAPIWithClient(token, apiEndpoint string, client HTTPClient) (*BotAPI, error) { func NewBotWithClient(config BotConfigI, client HTTPClientI) *BotAPI {
bot := &BotAPI{ bot := &BotAPI{
Token: token, config: config.(*BotConfig),
Client: client, client: client,
Buffer: 100, buffer: DefaultBufferSize,
shutdownChannel: make(chan interface{}), shutdownChannel: make(chan interface{}),
apiEndpoint: apiEndpoint,
} }
self, err := bot.GetMe() return bot
if err != nil {
return nil, err
}
bot.Self = self
return bot, nil
} }
// SetAPIEndpoint changes the Telegram Bot API endpoint used by the instance. func (b *BotAPI) GetConfig() BotConfigI {
func (bot *BotAPI) SetAPIEndpoint(apiEndpoint string) { return b.config
bot.apiEndpoint = apiEndpoint }
func (b *BotAPI) Validate() error {
_, err := b.GetMe()
return err
}
func (bot *BotAPI) SetReadonly(readonly bool) {
bot.readonly = readonly
} }
func buildParams(in Params) url.Values { func buildParams(in Params) url.Values {
@ -92,11 +82,11 @@ func buildParams(in Params) url.Values {
// MakeRequest makes a request to a specific endpoint with our token. // MakeRequest makes a request to a specific endpoint with our token.
func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, error) { func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, error) {
if bot.Debug { if bot.config.GetDebug() {
log.Printf("Endpoint: %s, params: %v\n", endpoint, params) log.Printf("Endpoint: %s, params: %v\n", endpoint, params)
} }
method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint) method := fmt.Sprintf(bot.config.GetApiEndpoint(), bot.config.GetToken(), endpoint)
values := buildParams(params) values := buildParams(params)
@ -106,7 +96,7 @@ func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, er
} }
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := bot.Client.Do(req) resp, err := bot.client.Do(req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -118,7 +108,7 @@ func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, er
return &apiResp, err return &apiResp, err
} }
if bot.Debug { if bot.config.GetDebug() {
log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes)) log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes))
} }
@ -143,7 +133,7 @@ func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, er
// If debug disabled, just decode http.Response.Body stream to APIResponse struct // If debug disabled, just decode http.Response.Body stream to APIResponse struct
// for efficient memory usage // for efficient memory usage
func (bot *BotAPI) decodeAPIResponse(responseBody io.Reader, resp *APIResponse) ([]byte, error) { func (bot *BotAPI) decodeAPIResponse(responseBody io.Reader, resp *APIResponse) ([]byte, error) {
if !bot.Debug { if !bot.config.GetDebug() {
dec := json.NewDecoder(responseBody) dec := json.NewDecoder(responseBody)
err := dec.Decode(resp) err := dec.Decode(resp)
return nil, err return nil, err
@ -217,11 +207,11 @@ func (bot *BotAPI) UploadFiles(endpoint string, params Params, files []RequestFi
} }
}() }()
if bot.Debug { if bot.config.GetDebug() {
log.Printf("Endpoint: %s, params: %v, with %d files\n", endpoint, params, len(files)) log.Printf("Endpoint: %s, params: %v, with %d files\n", endpoint, params, len(files))
} }
method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint) method := fmt.Sprintf(bot.config.GetApiEndpoint(), bot.config.GetToken(), endpoint)
req, err := http.NewRequest("POST", method, r) req, err := http.NewRequest("POST", method, r)
if err != nil { if err != nil {
@ -230,7 +220,7 @@ func (bot *BotAPI) UploadFiles(endpoint string, params Params, files []RequestFi
req.Header.Set("Content-Type", m.FormDataContentType()) req.Header.Set("Content-Type", m.FormDataContentType())
resp, err := bot.Client.Do(req) resp, err := bot.client.Do(req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -242,7 +232,7 @@ func (bot *BotAPI) UploadFiles(endpoint string, params Params, files []RequestFi
return &apiResp, err return &apiResp, err
} }
if bot.Debug { if bot.config.GetDebug() {
log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes)) log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes))
} }
@ -272,7 +262,7 @@ func (bot *BotAPI) GetFileDirectURL(fileID string) (string, error) {
return "", err return "", err
} }
return file.Link(bot.Token), nil return file.Link(bot.config.GetToken()), nil
} }
// GetMe fetches the currently authenticated bot. // GetMe fetches the currently authenticated bot.
@ -292,12 +282,12 @@ func (bot *BotAPI) GetMe() (User, error) {
return user, err return user, err
} }
// IsMessageToMe returns true if message directed to this bot. //// IsMessageToMe returns true if message directed to this bot.
// ////
// It requires the Message. //// It requires the Message.
func (bot *BotAPI) IsMessageToMe(message Message) bool { //func (bot *BotAPI) IsMessageToMe(message Message) bool {
return strings.Contains(message.Text, "@"+bot.Self.UserName) // return strings.Contains(message.Text, "@"+bot.Self.UserName)
} //}
func hasFilesNeedingUpload(files []RequestFile) bool { func hasFilesNeedingUpload(files []RequestFile) bool {
for _, file := range files { for _, file := range files {
@ -428,7 +418,7 @@ func (bot *BotAPI) GetWebhookInfo() (WebhookInfo, error) {
// GetUpdatesChan starts and returns a channel for getting updates. // GetUpdatesChan starts and returns a channel for getting updates.
func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) UpdatesChannel { func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) UpdatesChannel {
ch := make(chan Update, bot.Buffer) ch := make(chan Update, bot.buffer)
go func() { go func() {
for { for {
@ -462,15 +452,16 @@ func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) UpdatesChannel {
// StopReceivingUpdates stops the go routine which receives updates // StopReceivingUpdates stops the go routine which receives updates
func (bot *BotAPI) StopReceivingUpdates() { func (bot *BotAPI) StopReceivingUpdates() {
if bot.Debug { if bot.config.GetDebug() {
log.Println("Stopping the update receiver routine...") log.Println("Stopping the update receiver routine...")
} }
close(bot.shutdownChannel) close(bot.shutdownChannel)
} }
// TODO: get rid of bot dependancy
// ListenForWebhook registers a http handler for a webhook. // ListenForWebhook registers a http handler for a webhook.
func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel { func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel {
ch := make(chan Update, bot.Buffer) ch := make(chan Update, bot.buffer)
http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
update, err := bot.HandleUpdate(r) update, err := bot.HandleUpdate(r)
@ -488,9 +479,10 @@ func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel {
return ch return ch
} }
// TODO: Remove dependancy on bot
// ListenForWebhookRespReqFormat registers a http handler for a single incoming webhook. // ListenForWebhookRespReqFormat registers a http handler for a single incoming webhook.
func (bot *BotAPI) ListenForWebhookRespReqFormat(w http.ResponseWriter, r *http.Request) UpdatesChannel { func (bot *BotAPI) ListenForWebhookRespReqFormat(w http.ResponseWriter, r *http.Request) UpdatesChannel {
ch := make(chan Update, bot.Buffer) ch := make(chan Update, bot.buffer)
func(w http.ResponseWriter, r *http.Request) { func(w http.ResponseWriter, r *http.Request) {
defer close(ch) defer close(ch)
@ -510,6 +502,8 @@ func (bot *BotAPI) ListenForWebhookRespReqFormat(w http.ResponseWriter, r *http.
return ch return ch
} }
// TODO: move it outside of bot struct, it's not related to bot
// HandleUpdate parses and returns update received via webhook // HandleUpdate parses and returns update received via webhook
func (bot *BotAPI) HandleUpdate(r *http.Request) (*Update, error) { func (bot *BotAPI) HandleUpdate(r *http.Request) (*Update, error) {
if r.Method != http.MethodPost { if r.Method != http.MethodPost {

42
bot_config.go Normal file
View file

@ -0,0 +1,42 @@
package tgbotapi
type BotConfigI interface {
GetApiEndpoint() string
GetToken() string
GetDebug() bool
}
type BotConfig struct {
token string
debug bool
apiEndpoint string
}
func NewBotConfig(token, apiEndpoint string, debug bool) *BotConfig {
return &BotConfig{
token: token,
debug: debug,
apiEndpoint: apiEndpoint,
}
}
func NewDefaultBotConfig(token string) *BotConfig {
return &BotConfig{
token: token,
debug: false,
apiEndpoint: APIEndpoint,
}
}
func (c *BotConfig) GetApiEndpoint() string {
return c.apiEndpoint
}
func (c *BotConfig) GetToken() string {
return c.token
}
func (c *BotConfig) GetDebug() bool {
return c.debug
}

View file

@ -16,7 +16,7 @@ import (
gomock "go.uber.org/mock/gomock" gomock "go.uber.org/mock/gomock"
) )
// MockHTTPClient is a mock of HTTPClient interface. // MockHTTPClient is a mock of HTTPClientI interface.
type MockHTTPClient struct { type MockHTTPClient struct {
ctrl *gomock.Controller ctrl *gomock.Controller
recorder *MockHTTPClientMockRecorder recorder *MockHTTPClientMockRecorder

View file

@ -36,7 +36,8 @@ func expectGetMe(t *testing.T, c *MockHTTPClient) {
} }
func TestNewBotInstance_WithEmptyToken(t *testing.T) { func TestNewBotInstance_WithEmptyToken(t *testing.T) {
_, err := NewBotAPI("") bot := NewBot(NewDefaultBotConfig(""))
err := bot.Validate()
require.Error(t, err) require.Error(t, err)
} }
@ -94,7 +95,8 @@ func TestGetUpdates(t *testing.T) {
return newOKResponse(updateResp), nil return newOKResponse(updateResp), nil
}) })
bot, err := NewBotAPIWithClient(TestToken, APIEndpoint, client) bot := NewBotWithClient(NewBotConfig(TestToken, APIEndpoint, false), client)
err := bot.Validate()
require.NoError(t, err) require.NoError(t, err)
u := NewUpdate(0) u := NewUpdate(0)
@ -107,25 +109,25 @@ func TestSendWithMessage(t *testing.T) {
defer client.ctrl.Finish() defer client.ctrl.Finish()
responseBody := `{ responseBody := `{
"ok": true, "ok": true,
"result": { "result": {
"message_id": 123, "message_id": 123,
"from": { "from": {
"id": 123456789, "id": 123456789,
"is_bot": true, "is_bot": true,
"first_name": "MyBot", "first_name": "MyBot",
"username": "my_bot" "username": "my_bot"
}, },
"chat": { "chat": {
"id": 987654321, "id": 987654321,
"first_name": "John", "first_name": "John",
"username": "john_doe", "username": "john_doe",
"type": "private" "type": "private"
}, },
"date": 1640001112, "date": 1640001112,
"text": "Hello, John!" "text": "Hello, John!"
} }
}` }`
expectGetMe(t, client) expectGetMe(t, client)
@ -137,7 +139,8 @@ func TestSendWithMessage(t *testing.T) {
return newOKResponse(responseBody), nil return newOKResponse(responseBody), nil
}) })
bot, err := NewBotAPIWithClient(TestToken, APIEndpoint, client) bot := NewBotWithClient(NewBotConfig(TestToken, APIEndpoint, false), client)
err := bot.Validate()
require.NoError(t, err) require.NoError(t, err)
msg := NewMessage(ChatID, "A test message from the test library in telegram-bot-api") msg := NewMessage(ChatID, "A test message from the test library in telegram-bot-api")
@ -151,25 +154,25 @@ func TestSendWithMessageReply(t *testing.T) {
defer client.ctrl.Finish() defer client.ctrl.Finish()
responseBody := `{ responseBody := `{
"ok": true, "ok": true,
"result": { "result": {
"message_id": 123, "message_id": 123,
"from": { "from": {
"id": 123456789, "id": 123456789,
"is_bot": true, "is_bot": true,
"first_name": "MyBot", "first_name": "MyBot",
"username": "my_bot" "username": "my_bot"
}, },
"chat": { "chat": {
"id": 987654321, "id": 987654321,
"first_name": "John", "first_name": "John",
"username": "john_doe", "username": "john_doe",
"type": "private" "type": "private"
}, },
"date": 1640001112, "date": 1640001112,
"text": "Hello, John!" "text": "Hello, John!"
} }
}` }`
expectGetMe(t, client) expectGetMe(t, client)
@ -181,7 +184,8 @@ func TestSendWithMessageReply(t *testing.T) {
return newOKResponse(responseBody), nil return newOKResponse(responseBody), nil
}) })
bot, err := NewBotAPIWithClient(TestToken, APIEndpoint, client) bot := NewBotWithClient(NewBotConfig(TestToken, APIEndpoint, false), client)
err := bot.Validate()
require.NoError(t, err) require.NoError(t, err)
msg := NewMessage(ChatID, "A test message from the test library in telegram-bot-api") msg := NewMessage(ChatID, "A test message from the test library in telegram-bot-api")
@ -196,25 +200,25 @@ func TestCopyMessage(t *testing.T) {
expectGetMe(t, client) expectGetMe(t, client)
responseBody := `{ responseBody := `{
"ok": true, "ok": true,
"result": { "result": {
"message_id": 123, "message_id": 123,
"from": { "from": {
"id": 123456789, "id": 123456789,
"is_bot": true, "is_bot": true,
"first_name": "MyBot", "first_name": "MyBot",
"username": "my_bot" "username": "my_bot"
}, },
"chat": { "chat": {
"id": 987654321, "id": 987654321,
"first_name": "John", "first_name": "John",
"username": "john_doe", "username": "john_doe",
"type": "private" "type": "private"
}, },
"date": 1640001112, "date": 1640001112,
"text": "Hello, John!" "text": "Hello, John!"
} }
}` }`
client.EXPECT(). client.EXPECT().
Do(gomock.Any()). Do(gomock.Any()).
@ -232,7 +236,8 @@ func TestCopyMessage(t *testing.T) {
return newOKResponse(responseBody), nil return newOKResponse(responseBody), nil
}) })
bot, err := NewBotAPIWithClient(TestToken, APIEndpoint, client) bot := NewBotWithClient(NewBotConfig(TestToken, APIEndpoint, false), client)
err := bot.Validate()
require.NoError(t, err) require.NoError(t, err)
msg := NewMessage(ChatID, "A test message from the test library in telegram-bot-api") msg := NewMessage(ChatID, "A test message from the test library in telegram-bot-api")
@ -245,7 +250,6 @@ func TestCopyMessage(t *testing.T) {
require.Equal(t, messageID.MessageID, message.MessageID) require.Equal(t, messageID.MessageID, message.MessageID)
} }
func TestPrepareInputMediaForParams(t *testing.T) { func TestPrepareInputMediaForParams(t *testing.T) {
media := []any{ media := []any{
NewInputMediaPhoto(FilePath("./image.jpg")), NewInputMediaPhoto(FilePath("./image.jpg")),

View file

@ -14,6 +14,8 @@ const (
// APIEndpoint is the endpoint for all API methods, // APIEndpoint is the endpoint for all API methods,
// with formatting for Sprintf. // with formatting for Sprintf.
APIEndpoint = "https://api.telegram.org/bot%s/%s" APIEndpoint = "https://api.telegram.org/bot%s/%s"
// APITestEndpoint is the endpoint for Telegram test server,
APITestEndpoint = "https://api.telegram.org/bot%s/test/%s"
// FileEndpoint is the endpoint for downloading a file from Telegram. // FileEndpoint is the endpoint for downloading a file from Telegram.
FileEndpoint = "https://api.telegram.org/file/bot%s/%s" FileEndpoint = "https://api.telegram.org/file/bot%s/%s"
) )

181
example/example_bot.go Normal file
View file

@ -0,0 +1,181 @@
package example
import (
"fmt"
"net/http"
"time"
"github.com/eli-l/telegram-bot-api/v7"
)
func ExampleNewBotAPI() {
cfg := tgbotapi.NewBotConfig("MyAwesomeBotToken", tgbotapi.APIEndpoint, true)
bot := tgbotapi.NewBot(cfg)
if err := bot.Validate(); err != nil {
panic(err)
}
usr, err := bot.GetMe()
if err != nil {
panic(err)
}
fmt.Printf("Authorized on account %s", usr.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates := bot.GetUpdatesChan(u)
// Optional: wait for updates and clear them if you don't want to handle
// a large backlog of old messages
time.Sleep(time.Millisecond * 500)
updates.Clear()
for update := range updates {
if update.Message == nil {
continue
}
fmt.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
msg.ReplyParameters.MessageID = update.Message.MessageID
_, err := bot.Send(msg)
if err != nil {
panic(err)
}
}
}
func ExampleNewWebhook() {
cfg := tgbotapi.NewBotConfig("MyAwesomeBotToken", tgbotapi.APIEndpoint, true)
bot := tgbotapi.NewBot(cfg)
if err := bot.Validate(); err != nil {
panic(err)
}
usr, err := bot.GetMe()
if err != nil {
panic(err)
}
fmt.Printf("Authorized on account %s", usr.UserName)
wh, err := tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+cfg.GetToken(), tgbotapi.FilePath("cert.pem"))
if err != nil {
panic(err)
}
_, err = bot.Request(wh)
if err != nil {
panic(err)
}
info, err := bot.GetWebhookInfo()
if err != nil {
panic(err)
}
if info.LastErrorDate != 0 {
fmt.Printf("failed to set webhook: %s", info.LastErrorMessage)
}
updates := bot.ListenForWebhook("/" + cfg.GetToken())
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
for update := range updates {
fmt.Printf("%+v\n", update)
}
}
func ExampleWebhookHandler() {
cfg := tgbotapi.NewBotConfig("MyAwesomeBotToken", tgbotapi.APIEndpoint, true)
bot := tgbotapi.NewBot(cfg)
if err := bot.Validate(); err != nil {
panic(err)
}
usr, err := bot.GetMe()
if err != nil {
panic(err)
}
fmt.Printf("Authorized on account %s", usr.UserName)
wh, err := tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+cfg.GetToken(), tgbotapi.FilePath("cert.pem"))
if err != nil {
panic(err)
}
_, err = bot.Request(wh)
if err != nil {
panic(err)
}
info, err := bot.GetWebhookInfo()
if err != nil {
panic(err)
}
if info.LastErrorDate != 0 {
fmt.Printf("[Telegram callback failed]%s", info.LastErrorMessage)
}
http.HandleFunc("/"+cfg.GetToken(), func(w http.ResponseWriter, r *http.Request) {
update, err := bot.HandleUpdate(r)
if err != nil {
fmt.Printf("%+v\n", err.Error())
} else {
fmt.Printf("%+v\n", *update)
}
})
go http.ListenAndServeTLS("0.0.0.0:8443", "./tests/cert.pem", "./tests/key.pem", nil)
}
func ExampleInlineConfig() {
cfg := tgbotapi.NewBotConfig("MyAwesomeBotToken", tgbotapi.APIEndpoint, true)
bot := tgbotapi.NewBot(cfg)
if err := bot.Validate(); err != nil {
panic(err)
}
usr, err := bot.GetMe()
if err != nil {
panic(err)
}
fmt.Printf("Authorized on account %s", usr.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates := bot.GetUpdatesChan(u)
for update := range updates {
if update.InlineQuery == nil { // if no inline query, ignore it
continue
}
article := tgbotapi.NewInlineQueryResultArticle(update.InlineQuery.ID, "Echo", update.InlineQuery.Query)
article.Description = update.InlineQuery.Query
inlineConf := tgbotapi.InlineConfig{
InlineQueryID: update.InlineQuery.ID,
IsPersonal: true,
CacheTime: 0,
Results: []interface{}{article},
}
if _, err := bot.Request(inlineConf); err != nil {
fmt.Println(err)
}
}
}

View file

@ -1,123 +0,0 @@
package tgbotapi
import (
"fmt"
"net/http"
"time"
)
func ExampleNewBotAPI() {
bot, err := NewBotAPI("MyAwesomeBotToken")
if err != nil {
panic(err)
}
bot.Debug = true
fmt.Printf("Authorized on account %s", bot.Self.UserName)
u := NewUpdate(0)
u.Timeout = 60
updates := bot.GetUpdatesChan(u)
// Optional: wait for updates and clear them if you don't want to handle
// a large backlog of old messages
time.Sleep(time.Millisecond * 500)
updates.Clear()
for update := range updates {
if update.Message == nil {
continue
}
fmt.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
msg := NewMessage(update.Message.Chat.ID, update.Message.Text)
msg.ReplyParameters.MessageID = update.Message.MessageID
_, err := bot.Send(msg)
if err != nil {
panic(err)
}
}
}
func ExampleNewWebhook() {
bot, err := NewBotAPI("MyAwesomeBotToken")
if err != nil {
panic(err)
}
bot.Debug = true
fmt.Printf("Authorized on account %s", bot.Self.UserName)
wh, err := NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, FilePath("cert.pem"))
if err != nil {
panic(err)
}
_, err = bot.Request(wh)
if err != nil {
panic(err)
}
info, err := bot.GetWebhookInfo()
if err != nil {
panic(err)
}
if info.LastErrorDate != 0 {
fmt.Printf("failed to set webhook: %s", info.LastErrorMessage)
}
updates := bot.ListenForWebhook("/" + bot.Token)
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
for update := range updates {
fmt.Printf("%+v\n", update)
}
}
func ExampleWebhookHandler() {
bot, err := NewBotAPI("MyAwesomeBotToken")
if err != nil {
panic(err)
}
bot.Debug = true
fmt.Printf("Authorized on account %s", bot.Self.UserName)
wh, err := NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, FilePath("cert.pem"))
if err != nil {
panic(err)
}
_, err = bot.Request(wh)
if err != nil {
panic(err)
}
info, err := bot.GetWebhookInfo()
if err != nil {
panic(err)
}
if info.LastErrorDate != 0 {
fmt.Printf("[Telegram callback failed]%s", info.LastErrorMessage)
}
http.HandleFunc("/"+bot.Token, func(w http.ResponseWriter, r *http.Request) {
update, err := bot.HandleUpdate(r)
if err != nil {
fmt.Printf("%+v\n", err.Error())
} else {
fmt.Printf("%+v\n", *update)
}
})
go http.ListenAndServeTLS("0.0.0.0:8443", "./tests/cert.pem", "./tests/key.pem", nil)
}

View file

@ -1,7 +1,6 @@
package tests package tests
import ( import (
"fmt"
"os" "os"
"strconv" "strconv"
"testing" "testing"
@ -52,9 +51,9 @@ func (t testLogger) Printf(format string, v ...interface{}) {
} }
func getBot(t *testing.T) (*tgbotapi.BotAPI, error) { func getBot(t *testing.T) (*tgbotapi.BotAPI, error) {
bot, err := tgbotapi.NewBotAPI(TestToken) bot := tgbotapi.NewBot(tgbotapi.NewBotConfig(TestToken, tgbotapi.APIEndpoint, Debug))
err := bot.Validate()
require.NoError(t, err) require.NoError(t, err)
bot.Debug = Debug
logger := testLogger{t} logger := testLogger{t}
err = tgbotapi.SetLogger(logger) err = tgbotapi.SetLogger(logger)
@ -64,9 +63,10 @@ func getBot(t *testing.T) (*tgbotapi.BotAPI, error) {
} }
func TestNewBotAPI_notoken(t *testing.T) { func TestNewBotAPI_notoken(t *testing.T) {
bot, err := tgbotapi.NewBotAPI("") bot := tgbotapi.NewBot(tgbotapi.NewBotConfig("", tgbotapi.APIEndpoint, Debug))
require.NotNil(t, bot)
err := bot.Validate()
require.Error(t, err) require.Error(t, err)
require.Nil(t, bot)
} }
func TestGetUpdates(t *testing.T) { func TestGetUpdates(t *testing.T) {
@ -545,13 +545,14 @@ func TestGetUserProfilePhotos(t *testing.T) {
} }
func TestSetWebhookWithCert(t *testing.T) { func TestSetWebhookWithCert(t *testing.T) {
bot, _ := getBot(t) bot, _ := getBot(t)
time.Sleep(time.Second * 2) time.Sleep(time.Second * 2)
bot.Request(tgbotapi.DeleteWebhookConfig{}) bot.Request(tgbotapi.DeleteWebhookConfig{})
wh, err := tgbotapi.NewWebhookWithCert("https://example.com/tgbotapi-test/"+bot.Token, tgbotapi.FilePath("./cert.pem")) wh, err := tgbotapi.NewWebhookWithCert("https://example.com/tgbotapi-test/"+bot.GetConfig().GetToken(), tgbotapi.FilePath("./cert.pem"))
require.NoError(t, err) require.NoError(t, err)
_, err = bot.Request(wh) _, err = bot.Request(wh)
require.NoError(t, err) require.NoError(t, err)
@ -571,7 +572,7 @@ func TestSetWebhookWithoutCert(t *testing.T) {
bot.Request(tgbotapi.DeleteWebhookConfig{}) bot.Request(tgbotapi.DeleteWebhookConfig{})
wh, err := tgbotapi.NewWebhook("https://example.com/tgbotapi-test/" + bot.Token) wh, err := tgbotapi.NewWebhook("https://example.com/tgbotapi-test/" + bot.GetConfig().GetToken())
require.NoError(t, err) require.NoError(t, err)
_, err = bot.Request(wh) _, err = bot.Request(wh)
@ -631,40 +632,6 @@ func TestSendWithMediaGroupAudio(t *testing.T) {
require.Equal(t, len(cfg.Media), len(messages)) require.Equal(t, len(cfg.Media), len(messages))
} }
func ExampleInlineConfig() {
bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken") // create new bot
if err != nil {
panic(err)
}
fmt.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates := bot.GetUpdatesChan(u)
for update := range updates {
if update.InlineQuery == nil { // if no inline query, ignore it
continue
}
article := tgbotapi.NewInlineQueryResultArticle(update.InlineQuery.ID, "Echo", update.InlineQuery.Query)
article.Description = update.InlineQuery.Query
inlineConf := tgbotapi.InlineConfig{
InlineQueryID: update.InlineQuery.ID,
IsPersonal: true,
CacheTime: 0,
Results: []interface{}{article},
}
if _, err := bot.Request(inlineConf); err != nil {
fmt.Println(err)
}
}
}
func TestDeleteMessage(t *testing.T) { func TestDeleteMessage(t *testing.T) {
bot, _ := getBot(t) bot, _ := getBot(t)