Skip to content

Commit

Permalink
Custom http client as option.
Browse files Browse the repository at this point in the history
  • Loading branch information
onrik committed Feb 15, 2018
1 parent 2813663 commit d5b441b
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 257 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ language: go
go:
- 1.6
- 1.7
- 1.8
- 1.9
- tip

before_install:
Expand Down
110 changes: 68 additions & 42 deletions bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"

"github.com/onrik/micha/http"
)

const (
Expand All @@ -22,21 +21,32 @@ type Response struct {
Result json.RawMessage `json:"result"`
}

// Bot telegram bot
type Bot struct {
Options
Me User

token string
updates chan Update
stop bool
offset uint64
limit int
timeout int
logger Logger
}

// NewBot - create new bot instance
func NewBot(token string, opts ...Option) (*Bot, error) {
options := Options{
limit: 100,
timeout: 25,
logger: newLogger("micha"),
httpClient: http.DefaultClient,
}

for _, opt := range opts {
opt(&options)
}

bot := Bot{
Options: options,
token: token,
updates: make(chan Update),
}
Expand All @@ -46,20 +56,8 @@ func NewBot(token string, opts ...Option) (*Bot, error) {
return nil, err
}

options := &Options{
Limit: 100,
Timeout: 25,
Logger: newLogger(me.Username),
}

for _, opt := range opts {
opt(options)
}

bot.Me = *me
bot.limit = options.Limit
bot.timeout = options.Timeout
bot.logger = options.Logger

return &bot, nil
}

Expand All @@ -86,39 +84,67 @@ func (bot *Bot) decodeResponse(data []byte, target interface{}) error {

if err := json.Unmarshal(response.Result, target); err != nil {
return fmt.Errorf("Decode result error (%s)", err.Error())
} else {
return nil
}

return nil
}

// Make GET request to Telegram API
// Send GET request to Telegram API
func (bot *Bot) get(method string, params url.Values, target interface{}) error {
response, err := http.Get(bot.buildURL(method) + "?" + params.Encode())
request, err := newGetRequest(bot.buildURL(method), params)
if err != nil {
return err
}

response, err := bot.httpClient.Do(request)
if err != nil {
return err
} else {
return bot.decodeResponse(response, target)
}

body, err := handleResponse(response)
if err != nil {
return err
}

return bot.decodeResponse(body, target)
}

// Make POST request to Telegram API
// Send POST request to Telegram API
func (bot *Bot) post(method string, data, target interface{}) error {
response, err := http.Post(bot.buildURL(method), data)
request, err := newPostRequest(bot.buildURL(method), data)
if err != nil {
return err
}
response, err := bot.httpClient.Do(request)
if err != nil {
return err
}

body, err := handleResponse(response)
if err != nil {
return err
} else {
return bot.decodeResponse(response, target)
}

return bot.decodeResponse(body, target)
}

// Make POST request to Telegram API
func (bot *Bot) postMultipart(method string, file *http.File, params url.Values, target interface{}) error {
response, err := http.PostMultipart(bot.buildURL(method), file, params)
// Send POST multipart request to Telegram API
func (bot *Bot) postMultipart(method string, file *fileField, params url.Values, target interface{}) error {
request, err := newMultipartRequest(bot.buildURL(method), file, params)
if err != nil {
return err
} else {
return bot.decodeResponse(response, target)
}
response, err := bot.httpClient.Do(request)
if err != nil {
return err
}

body, err := handleResponse(response)
if err != nil {
return err
}

return bot.decodeResponse(body, target)
}

// Use this method to receive incoming updates using long polling.
Expand Down Expand Up @@ -177,7 +203,7 @@ func (bot *Bot) GetWebhookInfo() (*WebhookInfo, error) {
}

func (bot *Bot) SetWebhook(webhookURL string, options *SetWebhookOptions) error {
var file *http.File
var file *fileField
params := url.Values{
"url": {webhookURL},
}
Expand All @@ -189,7 +215,7 @@ func (bot *Bot) SetWebhook(webhookURL string, options *SetWebhookOptions) error
params["allowed_updates"] = options.AllowedUpdates
}
if len(options.Certificate) > 0 {
file = &http.File{
file = &fileField{
Source: bytes.NewBuffer(options.Certificate),
Fieldname: "certificate",
Filename: "certificate",
Expand Down Expand Up @@ -247,7 +273,7 @@ func (bot *Bot) SendPhotoFile(chatID ChatID, file io.Reader, fileName string, op
return nil, err
}

f := &http.File{
f := &fileField{
Source: file,
Fieldname: "photo",
Filename: fileName,
Expand Down Expand Up @@ -277,7 +303,7 @@ func (bot *Bot) SendAudioFile(chatID ChatID, file io.Reader, fileName string, op
return nil, err
}

f := &http.File{
f := &fileField{
Source: file,
Fieldname: "audio",
Filename: fileName,
Expand Down Expand Up @@ -307,7 +333,7 @@ func (bot *Bot) SendDocumentFile(chatID ChatID, file io.Reader, fileName string,
return nil, err
}

f := &http.File{
f := &fileField{
Source: file,
Fieldname: "document",
Filename: fileName,
Expand Down Expand Up @@ -337,7 +363,7 @@ func (bot *Bot) SendStickerFile(chatID ChatID, file io.Reader, fileName string,
return nil, err
}

f := &http.File{
f := &fileField{
Source: file,
Fieldname: "sticker",
Filename: fileName,
Expand Down Expand Up @@ -367,7 +393,7 @@ func (bot *Bot) SendVideoFile(chatID ChatID, file io.Reader, fileName string, op
return nil, err
}

f := &http.File{
f := &fileField{
Source: file,
Fieldname: "video",
Filename: fileName,
Expand Down Expand Up @@ -399,7 +425,7 @@ func (bot *Bot) SendVoiceFile(chatID ChatID, file io.Reader, fileName string, op
return nil, err
}

f := &http.File{
f := &fileField{
Source: file,
Fieldname: "voice",
Filename: fileName,
Expand Down Expand Up @@ -429,7 +455,7 @@ func (bot *Bot) SendVideoNoteFile(chatID ChatID, file io.Reader, fileName string
return nil, err
}

f := &http.File{
f := &fileField{
Source: file,
Fieldname: "video_note",
Filename: fileName,
Expand Down
15 changes: 10 additions & 5 deletions bot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,13 @@ func (s *BotTestSuite) SetupSuite() {

s.bot = &Bot{
token: "111",
timeout: 25,
limit: 100,
logger: newLogger("micha"),
updates: make(chan Update),
Options: Options{
limit: 100,
timeout: 25,
logger: newLogger("micha"),
httpClient: http.DefaultClient,
},
}
}

Expand Down Expand Up @@ -128,16 +131,18 @@ func (s *BotTestSuite) TestNewBot() {
s.Require().NotNil(bot)
s.Require().Equal(25, bot.timeout)
s.Require().Equal(100, bot.limit)
s.Require().Equal(newLogger("michabot"), bot.logger)
s.Require().Equal(newLogger("micha"), bot.logger)

// With options
logger := log.New(os.Stderr, "", log.LstdFlags)
bot, err = NewBot("111", WithLimit(50), WithTimeout(10), WithLogger(logger))
httpClient := &http.Client{}
bot, err = NewBot("111", WithLimit(50), WithTimeout(10), WithLogger(logger), WithHttpClient(httpClient))
s.Require().Nil(err)
s.Require().NotNil(bot)
s.Require().Equal(10, bot.timeout)
s.Require().Equal(50, bot.limit)
s.Require().Equal(logger, bot.logger)
s.Require().Equal(httpClient, bot.httpClient)
}

func (s *BotTestSuite) TestErrorsHandle() {
Expand Down
47 changes: 20 additions & 27 deletions http/http.go → http.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package http
package micha

import (
"bytes"
Expand All @@ -11,7 +11,12 @@ import (
"net/url"
)

type File struct {
// HttpClient interface
type HttpClient interface {
Do(*http.Request) (*http.Response, error)
}

type fileField struct {
Source io.Reader
Fieldname string
Filename string
Expand All @@ -20,45 +25,38 @@ type File struct {
func handleResponse(response *http.Response) ([]byte, error) {
defer response.Body.Close()
if response.StatusCode > http.StatusBadRequest {
return nil, fmt.Errorf("Response status: %d", response.StatusCode)
} else {
return ioutil.ReadAll(response.Body)
return nil, fmt.Errorf("HTTP status: %d", response.StatusCode)
}

return ioutil.ReadAll(response.Body)
}

func Get(url string) ([]byte, error) {
response, err := http.Get(url)
if err != nil {
return nil, err
} else {
return handleResponse(response)
func newGetRequest(url string, params url.Values) (*http.Request, error) {
if params != nil {
url += fmt.Sprintf("?%s", params.Encode())
}
return http.NewRequest(http.MethodGet, url, nil)
}

func Post(url string, data interface{}) ([]byte, error) {
func newPostRequest(url string, data interface{}) (*http.Request, error) {
body := new(bytes.Buffer)
if data != nil {
if err := json.NewEncoder(body).Encode(data); err != nil {
return nil, fmt.Errorf("Encode data error (%s)", err.Error())
}
}

request, err := http.NewRequest("POST", url, body)
request, err := http.NewRequest(http.MethodPost, url, body)
if err != nil {
return nil, err
}

request.Header.Add("Content-Type", "application/json")

response, err := (&http.Client{}).Do(request)
if err != nil {
return nil, err
} else {
return handleResponse(response)
}
return request, nil
}

func PostMultipart(url string, file *File, params url.Values) ([]byte, error) {
func newMultipartRequest(url string, file *fileField, params url.Values) (*http.Request, error) {
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)

Expand All @@ -85,17 +83,12 @@ func PostMultipart(url string, file *File, params url.Values) ([]byte, error) {
return nil, err
}

request, err := http.NewRequest("POST", url, body)
request, err := http.NewRequest(http.MethodPost, url, body)
if err != nil {
return nil, err
}

request.Header.Add("Content-Type", writer.FormDataContentType())

response, err := (&http.Client{}).Do(request)
if err != nil {
return nil, err
} else {
return handleResponse(response)
}
return request, nil
}
Loading

0 comments on commit d5b441b

Please sign in to comment.