Skip to content

Releases: tucnak/telebot

Telebot V3.3

10 Jun 20:03
Compare
Choose a tag to compare

Changelog

  • Bot API 6.6, 6.7, 6.8, 6.9, 7.0, 7.1
  • Implemented Boosts API support
  • Improved Stickers API support
  • Improved Album interaction
  • More of handy Context helpers
  • New telebot/react package with reaction bindings
  • Embedded FS support for telebot/layout
  • Lots of minor fixes and improvements

Bot API 6.6: Stickers

Unfortunately, due to breaking the Stickers API update on the Telegram side, we had to break the backward compatibility with previous versions of Telebot as well. However, this allowed us to rework the API and make it feel better and clearer to use.

// 1. UploadSticker now accepts the StickerSetFormat and File
b.UploadSticker(to, tele.StickerStatic, tele.FromDisk("telebot.png"))

// 2. CreateStickerSet now works with multiple stickers
b.CreateStickerSet(to, &tele.StickerInput{
  // ...
  Input: []tele.InputSticker{
    {File: tele.FromDisk("telebot1.png")},
    {File: tele.FromDisk("telebot2.png")},
  },
})

// 3. AddSticker is now called AddStickerToSet and accepts name and the InputSticker
b.AddStickerToSet(to, tele.InputSticker{
  File: tele.FromDisk("telebot.png"),
})

Bot API 7.0, 7.1

Boosts

// 1. Get a list of user boosts for a particular chat
boosts, err := b.UserBoosts(chat, user)
if err != nil {
  return err
}

// 2. Use boost fields
for _, boost := range boosts {
  boost.ID
  boost.AddDate()
  boost.ExpirationDate()
  ...
}

// 3. Handle boost-related events
b.Handle(tele.OnBoost, func(c tele.Context) error {
  boost := c.Boost()
  boost.Chat
  boost.Boost
  ...
})

Reactions

import (
  tele "gopkg.in/telebot.v3"
  "gopkg.in/telebot.v3/react"
)

// 1. Use a telebot/react package for the React shorthand
b.React(to, msg, react.React(react.ThumbUp, react.Fire))

// 2. Use ReactionOptions to add special options
b.React(to, msg, tele.ReactionOptions{
  Reactions: []tele.Reaction{react.Heart},
  Big:       true,
})

Multiple Message Actions

b.ForwardMany(to, msgs)
b.CopyMany(to, msgs)
b.DeleteMany(to, msgs)

Other Features

Check out the whole diff: #658

More shorthands

  • Use a new Trigger bot function to trigger the specific handler:
b.Handle("/start", func (c tele.Context) error {
  return c.Send("Hello, World!")
})

b.Handle("/help", func (c tele.Context) error {
  return b.Trigger("/start", c)
})
  • Finally, a SetCaption function to add a caption to the first media of the album:
var album tele.Album
// Populate album dynamically...
album.SetCaption("Hey, hey, hey!")

msgs, err := b.SendAlbum(user, album)
if err != nil {
  return err
}
  • Handy Context helpers to remove CallbackResponse from your code:
b.Handle(callback, func(c tele.Context) error {
  return c.RespondText("This is a pop-up!")
  // or ...
  return c.RespondAlert("This is an alert!")
})
  • Initialize a telebot/layout from the embedded FS:
import (
  "embed"

  tele "gopkg.in/telebot.v3"
  "gopkg.in/telebot.v3/layout"
)

//go:embed layout
var fs embed.FS

func main() {
  lt, err := layout.NewFromFS(fs, "bot.yml")
  if err != nil {
    panic(err)
  }

  b, err := tele.NewBot(lt.Settings())
  if err != nil {
    panic(err)
  }

 // Done!
}

Fixes and Improvements

  • New ErrIs function to check if the given description matches the error (71ac299)
  • Fixed stop channel race (#641)
  • Improved Context.Args parsing (#651)
  • Added missed types and fields (#647, #648)
  • Added more errors (#659)
  • Some *Chat arguments changed to Recipient (#568)
  • middleware.RecoverFunc now accepts the Context (a26ba9f)
  • !! Renamings (0d0d5e7, 32b47a4, 435ad60)

Discussion

Discuss on Telegram

Telebot V3.2

20 Nov 13:53
Compare
Choose a tag to compare

Changelog

  • Bot API 6.3, 6.4, 6.5
  • Group's forum topics support
  • Other minor fixes and improvements

Bot API 6.3, 6.4: Topics

// 1. Create a forum topic with specified settings
topic, err := b.CreateTopic(chat, &tele.Topic{Name: "Discussions"})
if err != nil {
  return err
}

// 2. Use topic methods
b.CloseTopic(chat, topic)
b.ReopenTopic(chat, topic)
b.DeleteTopic(chat, topic)
b.HideGeneralTopic(chat)
b.UnhideGeneralTopic(chat)
...

// 3. Handle topics-related events
b.Handle(tele.OnTopicCreated, func(c tele.Context) error {
  topic := c.Topic()
  topic.Name
  topic.ThreadID
})

Bot API 6.5: ReplyRecipient

// 1. Use a ReplyRecipient constructor for both
// `request_user` and `request_chat` params
var (
  replyUser = &tele.ReplyRecipient{
    ID:      1, // unique
    Bot:     tele.Flag(false),
    Premium: tele.Flag(true),
  }
  replyChat = &tele.ReplyRecipient{
    ID:       1,     // unique
    Channel:  false, // required
    Username: tele.Flag(true),
  }
)

markup := &tele.ReplyMarkup{}
markup.Reply(
  markup.Row(markup.User(replyUser)),
  markup.Row(markup.Chat(replyChat)),
)

b.Send(to, "Share with me...", markup)

// 2. Handle the shared user or chat
b.Handle(tele.OnUserShared, func(c tele.Context) error {
  user := c.Message().UserShared
  log.Println("Shared user ID:", user.UserID)
})

Use a Flag helper that returns a pointer to the given bool:

// Flag returns a pointer to the given bool.
// Useful for passing the three-state flags to a Bot API.
// For example, see ReplyRecipient type.
func Flag(b bool) *bool {
  return &b
}

Fixes and Improvements

  • Bot.SetWebhook error is loggable by default (#559)
  • telebot/layout fixes (7065335, 4c17ca7)
  • Fixed the middleware applying for groups (#588)
  • More errors (#570, 699e5db)
  • Added missed is_member field to the ChatMember (#615)
  • Added missed custom_emoji_id field to the Sticker (#579)
  • Fixed Results.MarshalJSON addressing inside for-loop (#589)

Discussion

Discuss on Telegram

Telebot V3.1

06 Oct 20:54
Compare
Choose a tag to compare

Changelog

  • Bot API 6.0, 6.1, 6.2
  • telebot/layout improvements
  • Changed panic-recovering behavior
  • Source restructure and refactoring
  • Other minor fixes and improvements

Web apps support

Use the new OnWebApp event along with the WebApp buttons field to interact with the new stunning web app functionality.

webApp := &tele.WebApp{
  URL: "https://mywebapp.com",
}

b.Handle("/start", func(c tele.Context) error {
  markup := b.NewMarkup()
  markup.Inline(markup.WebApp("Open", webApp))
  return c.Send("Open this app!", markup)
})
b.Handle(tele.OnWebApp, func(c tele.Context) error {
  webapp := c.Message().WebAppData

  // Use the data fields:
  // webapp.Data
  // webapp.Text
}

New Recover middleware

Be careful with allowing panics inside your handlers after the v3.0.1 release, since panics' recovering by default was removed. Instead, make sure you've added the Recover middleware in case you really need it:

b.Use(middleware.Recover())
b.Use(middleware.Logger())
// ...

telebot/layout improvements

  • Use new tele.M alias in your layout calls instead of map[string]any declaration:
lt.Text(c, "start", tele.M{...})
  • The new CommandsLocale function for localized commands:
# bot.yml
commands:
  /help: '{{ text `cmd_help` }}'

# en.yml
cmd_help: Show the help message

# fr.yml
cmd_help: Afficher le message d'aide
for _, locale := range lt.Locales() {
  b.SetCommands(locale, lt.CommandsLocale(locale))
}
  • layout.Config is now using viper under the hood
config:
  tiers:
    default: standard
    all:
    - name: standard
      limit: 5
      delay: 10m
    - name: premium
      limit: 50
      delay: 1h
// Instead of an old sequential method,
defaultTier := lt.Get("tiers").String("default")
// you can use viper's dot notation:
defaultTier := lt.String("tiers.default")

// Some clumsy methods were removed,
// so instead of lt.Each and lt.Index use:
for _, tier := range lt.Slice("tiers.all") {
  dur := tier.Duration("delay")
}

// You can also unmarshal any key directly:
var tiers []struct {
  Name string
  Limit int
  Delay time.Duration
}

lt.UnmarshalKey("tiers.all", &tiers)

Backward incompatible changes

Unfortunately, some of them had a place in the v3.1.0 release and we can't guarantee compatibility through all the minor versions after this. The main reason for it is the fact that Telegram itself allows the breaking changes to appear in their API, however in some cases you can't help it, and breaking becomes inevitable. We break the contract beforehand so that you're previously ready for the future breaking Bot API update.

Some of the changes you should be aware of:

  • Bot.OnError field won't be exposed, use Settings.OnError instead once at initialization
  • Aforementioned panic-recovering behavior is optional
  • File.FileSize changed the int type to the int64
  • voice_chat_* fields renamed to video_chat_*
  • *ChatJoinRequest functions renamed to *JoinRequest

Fixes

  • One minute is the default HTTP client timeout now (#478)
  • Handled video response from sendDocument (#481)
  • Message.Media() includes missed Sticker type (#520)
  • Cancel Raw() execution on bot stop (#532)
  • DeleteCommands function is fixed (#533)
  • Fixed the order in which layout template's Funcs are applied (#546)

Discussion

Discuss on Telegram

Telebot V3.0.1

01 Oct 23:22
Compare
Choose a tag to compare

Changelog

  • Sticker is treated as a Media now
  • DeleteCommands is working properly now
  • is_premium field is added to the Chat
  • Stop() behavior improvements (#532)
  • New tele.M alias type for the map[string]any to be used with layout package
  • middleware.Recover() is added instead of the default panic-recovering behavior
  • Bot.OnError is read-only now, instead pass the error handler once through tele.Settings

Telebot V3

08 Feb 00:08
Compare
Choose a tag to compare

We're happy to finally announce V3 of Telebot framework — the best of its kind API for interacting with Telegram bots. There were many changes and innovations based on our and the community's negative experience, which had a place while using V2. We've tried to include all common and most convenient routing, handling, and middleware patterns. Although this branch was widely tested and is production-ready, many planned but unimplemented things are left, so we're going to introduce even more allure features in future major and minor versions.

Especial thanks to all our contributors who helped through these years in fixing bugs, improving, and maintaining API.

Changelog

  • gopkg.in/tucnak.v3 is the new import path
  • tele is the new recommended alias
  • Bot API 5.3, 5.4, 5.5, 5.6, 5.7
  • Completed list of API errors
  • Better and clarified naming (#301)
  • Added missed events (cb12b17)
  • Got rid of github.com/pkg/errors package (#462)
  • Tons of other minor fixes and improvements

Introducing Context

Let's define a simple handler which responds to the /start command using v2:

b.Handle("/start", func(m *tele.Message) {
    _, err := b.Send(m.Sender, "Hello!")
    if err != nil {
        log.Println(err)
        return
    }
})

There'll be lots of similar calls in any advanced stateful Telegram bot, not only with b bot instance but also with databases and other dependencies. The default handler function signature does not imply error handling, which is wrong. So, the first thing that suggests itself is a way to minimize errors check routine. We also need one strictly defined place where all errors come together with a corresponding event.

Secondly, while developing a complex bot, you often need to perform the same logic for different endpoint types. As an example, to send a help message whether replying to the user's command or responding to the button pressing. In v2 it will be two separate functions: one taking *Message and another with *Callback.

What if we combine all the possible handler types and encapsulate the different logic for different events? Here comes a Context — an interface type, which implementation wraps an incoming update and provides a number of useful short-hands and helper functions.

b.Handle("/start", func(c tele.Context) error {
    return c.Send("Hello!")
})

Isn't it handy? It's a one-line v3 versus 4-5 lines v2. Now, we force a user to return the error, so most likely it will be recorded. For this purpose, we can override a special OnError callback:

b.OnError = func(err error, c tele.Context) {
    if err != tele.ErrTrueResult {
        log.Println(c.Sender().ID, err)
    }
}

It also doesn't matter which type the event is — context can handle it and send the message in the current chat:

b.Handle("/start", sendHello)
b.Handle(&btnHello, sendHello)

We can go even further and let's say, edit the message if it is editable; otherwise, send it:

func sendHello(c tele.Context) error {
    return c.EditOrSend("Hello!")
}

The same applies to all the functions in the Context interface. Check them out here.

Introducing Middleware

You might notice that the context approach is somewhat similar to what we experience in most advanced HTTP server frameworks like echo or gin. What we're missing is an easier way to define and use middleware. The only method to do it was to wrap a poller with a custom MiddlewarePoller which performs necessary logic processing incoming updates. When we have piles and piles of extra middleware functionality it becomes clumsy.

So how do we do it now? To register your own or some pre-defined middlewares from the telebot/middleware package, there's a Use function.

import "gopkg.in/telebot.v3/middleware"
// Global-scoped middleware:
b.Use(middleware.Logger()) // logs every incoming handled event
b.Use(middleware.AutoRespond()) // automatically responds to every callback

// Group-scoped middleware:
adminOnly := b.Group()
adminOnly.Use(middleware.Whitelist(adminIDs...))
adminOnly.Handle("/ban", onBan)
adminOnly.Handle("/kick", onKick)

// Handler-scoped middleware:
b.Handle(tele.OnText, onText, middleware.IgnoreVia())

It comes clear how to implement your own middleware by looking at built-in straightforward examples.

New OnMedia endpoint

All media types are now associated with a Media interface and all InputMedia types — with an Inputtable interface. Here perfectly fits the OnMedia event, which matches any kind of media that wasn't handled by a specific handler.

b.Handle(tele.OnMedia, func(c tele.Context) error {
    media := c.Message().Media()

    // Now you can store media's kind and file ID:
    kind := media.MediaType()
    file := media.MediaFile()

    // ...
})

Several useful helpers

A handy and my favorite Split helper splits a list of buttons into the rows of them by a given maximum capacity for each row:

b.Handle("/things", func(c tele.Context) error {
    var btns []tele.Btn
    for _, thing := range things {
        btns = append(btns, /* prepare a button */)
    }

    markup := b.NewMarkup()
    markup.Inline(markup.Split(3, btns)...)

    return c.Send("Choose a thing:", markup)
})

An input_field_placeholder wrapper:

b.Handle("/name", func(c tele.Context) error {
    return c.Send(
        "Input your new name:",
        tele.Placeholder("John Doe"),
    )
})

Message's text/caption entities parser via EntityText:

b.Handle(tele.OnText, func(c tele.Context) error {
    m := c.Message()

    var mentions []string
    for _, ent := range m.Entities {
        if ent.Type == tele.EntityMention {
            mentions = append(mentions, m.EntityText(ent))
        }
    }

    return c.Send(fmt.Sprintf("Mentions: %s.", strings.Join(mentions, ", ")))
})

Postponed message deletion:

b.Handle("/start", func(c tele.Context) error {
    c.DeleteAfter(10 * time.Second)
    return c.Send(...)
})

Introducing telebot/layout

This part, I believe, deserves another comprehensive description. It provides a lot of use-cases and allows you to separate the code and the business logic from a bot's content. A godoc documentation is available here.

Check out some examples

People often complain about the lack of examples. We've prepared plenty of them: github.com/handybots. These are real and working bots opened for the good of the community.

Discussion

Discuss on Telegram

Telebot V2.5

08 Dec 18:17
Compare
Choose a tag to compare

Changelog

User identifiers can now be bigger than 2^31 - 1 and it is no longer possible to store them in a signed 32-bit integer type. User identifiers have up to 52 significant bits, so a 64-bit integer or double-precision float type is safe for storing them. Please make sure that your code can correctly handle such user identifiers.

Announcement

Telebot V2 is no longer maintained — this is the last major version. Currently, we're working on V3, which is much more advanced and has tons of helpful features and continuous support. As there're not that many breaking changes between two APIs, consider migrating to the latest v3 branch as soon as the beta will be released.

Discussion

Discuss on Telegram

Telebot V2.4

13 Aug 13:08
Compare
Choose a tag to compare

Changelog

  • Bot API 5.0, 5.1, 5.2
  • SendAlbum improvements (#398)

Telebot V2.3

13 Jun 11:05
Compare
Choose a tag to compare

Changelog

  • Bot API 4.9

  • Special ErrTrueResult error for updating methods

  • Extended b.Edit() function:

    b.Edit(m, m.Text, newMarkup)
    b.Edit(m, "new <b>text</b>", tb.ModeHTML)
    b.Edit(m, &tb.ReplyMarkup{...})
    b.Edit(m, &tb.Photo{File: ...})
    b.Edit(m, tb.Location{42.1337, 69.4242})
  • Default parse mode:

    pref := tb.Settings{
        Token:     "",
        ParseMode: tb.ModeMarkdown,
    }
    
    b, _ := tb.NewBot(pref)
    b.Send(to, "*text*")                   // default markdown mode
    b.Send(to, "<b>text</b>", tb.ModeHTML) // forced html mode
  • Verbose mode for outcoming requests:

    pref := tb.Settings{
        Token:   "",
        Verbose: true,
    }
    
    b, _ := tb.NewBot(pref)
    b.Notify(to, tb.Typing)
    [verbose] telebot: sent request
    Method: sendChatAction
    Params: {
        "action": "typing",
        "chat_id": "..."
    }
    Response: {
        "ok": true,
        "result": true
    }
    

Fixes

  • Updating methods unmarshalling fix (#298)
  • SuccessfulPayment currency type fix (#299)
  • Stickers API minor fixes

Telebot V2.2

13 Jun 11:05
Compare
Choose a tag to compare

For this release, aside from Bot API implementation, we've prepared many new useful features.

Changelog

  • Completed Webhook, Games, Stickers and Payments APIs
  • Synchronous mode and serverless support (#219)
  • Keyboard constructors (#290)
  • Special ChatID recipient type (#263)

Serverless

Now it's possible to use telebot together with serverless providers like AWS, Azure, etc... Thanks to one of the package's contributors, you can check out the exhaustive example in examples/awslambdaechobot.

pref := tb.Settings{
    Token:       "",
    Synchronous: true,
}
b, err := tb.NewBot(pref)
// ...

Keyboard constructors

Use special helper functions and types to decrease boilerplate across the code. The new keyboards builder make their definition easier. Look into updated README Keyboards section for details.

menu := &ReplyMarkup{ResizeReplyKeyboard: true}

var (
    // Reply buttons.
    btnHelp     = menu.Text("ℹ Help")
    btnSettings = menu.Text("⚙ Settings")
)

menu.Reply(
    menu.Row(btnHelp),
    menu.Row(btnSettings),
)

b.Handle(&btnHelp, func(m *tb.Message) {...})
b.Handle(&btnSettings, func(m *tb.Message) {...})

ChatID type

It was a bit confusing to work with specific chat IDs. You had to wrap integer into &tb.Chat{} every time you wanted to send a message. Imagine you have a config file with a bunch of defined group or channel IDs. Now you can use your int64 values directly with functions which accept Recipient interface.

type Config struct {
    AdminGroup tb.ChatID `yaml:"admin_group_id"`
    AdsChannel tb.ChatID `yaml:"ads_channel_id"`
}

b.Send(conf.AdminGroup, "message")
b.Send(conf.AdsChannel, "message")

Fixes

  • Added OnAnimation endpoint
  • Fixed regular expression for errors handling
  • Action fields were removed from Buttons
  • b.Forward() changed to take Editable instead of *Message

Telebot V2.1

13 Jun 11:04
59629fe
Compare
Choose a tag to compare

Finally, a new Telebot v2.1 release with a lot of minor fixes, additions and new methods implementations.

Changelog

  • Practically full implemented Bot API 4.8
  • Started code coverage process (now it's about 30%)
  • A convenient way to handle Telegram errors
  • A lot of bug fixes

Errors

From this release, you will be able to easily check for specific Telegram errors. We have a bunch of pre-defined Bot API errors and their descriptions in errors.go file. The work is still in progress, so feel free to contribute and to add missed entries. All errors are prefixed with telebot: if it's telebot-related or with telegram: if it's an API response.

msg, err := b.Send(user, "Hello World!")
if err != nil {
    if err == tb.ErrBlockedByUser {
        // remove user from database
    }
    // ...
}

Fixes

  • Use b.Edit() to invoke editMessageLiveLocation method (#239)
  • OnPinned also fires on channel posts (#244)
  • Exposed Webhook API (#214, #265)
  • LongPoller is now stoppable (#266)
  • Fixed a typo in DeleteGroupPhoto method
  • A little more nil checks to prevent unexpected panics