<|start_filename|>examples/awslambdaechobot/main.go<|end_filename|>
package main

import (
	"encoding/json"
	"os"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	tb "gopkg.in/tucnak/telebot.v2"
)

func main() {
	b, err := tb.NewBot(tb.Settings{
		Token:       os.Getenv("TELEBOT_SECRET"),
		Synchronous: true,
	})
	if err != nil {
		panic(err)
	}

	b.Handle(tb.OnText, func(m *tb.Message) { b.Send(m.Chat, m.Text) })

	lambda.Start(func(req events.APIGatewayProxyRequest) (err error) {
		var u tb.Update
		if err = json.Unmarshal([]byte(req.Body), &u); err == nil {
			b.ProcessUpdate(u)
		}
		return
	})
}


<|start_filename|>voice.go<|end_filename|>
package telebot

import "time"

// VoiceChatStarted represents a service message about a voice chat
// started in the chat.
type VoiceChatStarted struct{}

// VoiceChatEnded represents a service message about a voice chat
// ended in the chat.
type VoiceChatEnded struct {
	Duration int `json:"duration"`
}

// VoiceChatParticipantsInvited represents a service message about new
// members invited to a voice chat
type VoiceChatParticipantsInvited struct {
	Users []User `json:"users"`
}

// VoiceChatScheduled represents a service message about a voice chat scheduled in the chat.
type VoiceChatScheduled struct {
	Unixtime int64 `json:"start_date"`
}

// ExpireDate returns the point when the voice chat is supposed to be started by a chat administrator.
func (v *VoiceChatScheduled) ExpireDate() time.Time {
	return time.Unix(v.Unixtime, 0)
}


<|start_filename|>stickers.go<|end_filename|>
package telebot

import (
	"encoding/json"
	"strconv"
)

// Sticker object represents a WebP image, so-called sticker.
type Sticker struct {
	File
	Width        int           `json:"width"`
	Height       int           `json:"height"`
	Animated     bool          `json:"is_animated"`
	Thumbnail    *Photo        `json:"thumb"`
	Emoji        string        `json:"emoji"`
	SetName      string        `json:"set_name"`
	MaskPosition *MaskPosition `json:"mask_position"`
}

// StickerSet represents a sticker set.
type StickerSet struct {
	Name          string        `json:"name"`
	Title         string        `json:"title"`
	Animated      bool          `json:"is_animated"`
	Stickers      []Sticker     `json:"stickers"`
	Thumbnail     *Photo        `json:"thumb"`
	PNG           *File         `json:"png_sticker"`
	TGS           *File         `json:"tgs_sticker"`
	Emojis        string        `json:"emojis"`
	ContainsMasks bool          `json:"contains_masks"`
	MaskPosition  *MaskPosition `json:"mask_position"`
}

// MaskPosition describes the position on faces where
// a mask should be placed by default.
type MaskPosition struct {
	Feature MaskFeature `json:"point"`
	XShift  float32     `json:"x_shift"`
	YShift  float32     `json:"y_shift"`
	Scale   float32     `json:"scale"`
}

// UploadStickerFile uploads a .PNG file with a sticker for later use.
func (b *Bot) UploadStickerFile(to Recipient, png *File) (*File, error) {
	files := map[string]File{
		"png_sticker": *png,
	}
	params := map[string]string{
		"user_id": to.Recipient(),
	}

	data, err := b.sendFiles("uploadStickerFile", files, params)
	if err != nil {
		return nil, err
	}

	var resp struct {
		Result File
	}
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, wrapError(err)
	}
	return &resp.Result, nil
}

// GetStickerSet returns a StickerSet on success.
func (b *Bot) GetStickerSet(name string) (*StickerSet, error) {
	data, err := b.Raw("getStickerSet", map[string]string{"name": name})
	if err != nil {
		return nil, err
	}

	var resp struct {
		Result *StickerSet
	}
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, wrapError(err)
	}
	return resp.Result, nil
}

// CreateNewStickerSet creates a new sticker set.
func (b *Bot) CreateNewStickerSet(to Recipient, s StickerSet) error {
	files := make(map[string]File)
	if s.PNG != nil {
		files["png_sticker"] = *s.PNG
	}
	if s.TGS != nil {
		files["tgs_sticker"] = *s.TGS
	}

	params := map[string]string{
		"user_id":        to.Recipient(),
		"name":           s.Name,
		"title":          s.Title,
		"emojis":         s.Emojis,
		"contains_masks": strconv.FormatBool(s.ContainsMasks),
	}

	if s.MaskPosition != nil {
		data, err := json.Marshal(&s.MaskPosition)
		if err != nil {
			return err
		}
		params["mask_position"] = string(data)
	}

	_, err := b.sendFiles("createNewStickerSet", files, params)
	return err
}

// AddStickerToSet adds new sticker to existing sticker set.
func (b *Bot) AddStickerToSet(to Recipient, s StickerSet) error {
	files := make(map[string]File)
	if s.PNG != nil {
		files["png_sticker"] = *s.PNG
	} else if s.TGS != nil {
		files["tgs_sticker"] = *s.TGS
	}

	params := map[string]string{
		"user_id": to.Recipient(),
		"name":    s.Name,
		"emojis":  s.Emojis,
	}

	if s.MaskPosition != nil {
		data, err := json.Marshal(&s.MaskPosition)
		if err != nil {
			return err
		}
		params["mask_position"] = string(data)
	}

	_, err := b.sendFiles("addStickerToSet", files, params)
	return err
}

// SetStickerPositionInSet moves a sticker in set to a specific position.
func (b *Bot) SetStickerPositionInSet(sticker string, position int) error {
	params := map[string]string{
		"sticker":  sticker,
		"position": strconv.Itoa(position),
	}

	_, err := b.Raw("setStickerPositionInSet", params)
	return err
}

// DeleteStickerFromSet deletes sticker from set created by the bot.
func (b *Bot) DeleteStickerFromSet(sticker string) error {
	_, err := b.Raw("deleteStickerFromSet", map[string]string{"sticker": sticker})
	return err

}

// SetStickerSetThumb sets the thumbnail of a sticker set.
// Animated thumbnails can be set for animated sticker sets only.
//
// Thumbnail must be a PNG image, up to 128 kilobytes in size
// and have width and height exactly 100px, or a TGS animation
// up to 32 kilobytes in size.
//
// Animated sticker set thumbnail can't be uploaded via HTTP URL.
//
func (b *Bot) SetStickerSetThumb(to Recipient, s StickerSet) error {
	files := map[string]File{}
	if s.PNG != nil {
		files["thumb"] = *s.PNG
	} else if s.TGS != nil {
		files["thumb"] = *s.TGS
	}

	params := map[string]string{
		"name":    s.Name,
		"user_id": to.Recipient(),
	}

	_, err := b.sendFiles("setStickerSetThumb", files, params)
	return err
}


<|start_filename|>api_test.go<|end_filename|>
package telebot

import (
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
)

// testPayload implements json.Marshaler
// to test json encoding error behaviour.
type testPayload struct{}

func (testPayload) MarshalJSON() ([]byte, error) {
	return nil, errors.New("test error")
}

func testRawServer(w http.ResponseWriter, r *http.Request) {
	switch {
	// causes EOF error on ioutil.ReadAll
	case strings.HasSuffix(r.URL.Path, "/testReadError"):
		// tells the body is 1 byte length but actually it's 0
		w.Header().Set("Content-Length", "1")

	// returns unknown telegram error
	case strings.HasSuffix(r.URL.Path, "/testUnknownError"):
		data, _ := json.Marshal(struct {
			Ok          bool   `json:"ok"`
			Code        int    `json:"error_code"`
			Description string `json:"description"`
		}{
			Ok:          false,
			Code:        400,
			Description: "unknown error",
		})

		w.WriteHeader(400)
		w.Write(data)
	}
}

func TestRaw(t *testing.T) {
	if token == "" {
		t.Skip("TELEBOT_SECRET is required")
	}

	b, err := newTestBot()
	if err != nil {
		t.Fatal(err)
	}

	_, err = b.Raw("BAD METHOD", nil)
	assert.EqualError(t, err, ErrNotFound.Error())

	_, err = b.Raw("", &testPayload{})
	assert.Error(t, err)

	srv := httptest.NewServer(http.HandlerFunc(testRawServer))
	defer srv.Close()

	b.URL = srv.URL
	b.client = srv.Client()

	_, err = b.Raw("testReadError", nil)
	assert.EqualError(t, err, "telebot: "+io.ErrUnexpectedEOF.Error())

	_, err = b.Raw("testUnknownError", nil)
	assert.EqualError(t, err, "telegram unknown: unknown error (400)")
}
