Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/NicoNex/echotron
An elegant and concurrent library for the Telegram bot API in Go.
https://github.com/NicoNex/echotron
awesome-go bot go golang golang-library library telegram telegram-api telegram-bot telegram-bot-api
Last synced: 11 days ago
JSON representation
An elegant and concurrent library for the Telegram bot API in Go.
- Host: GitHub
- URL: https://github.com/NicoNex/echotron
- Owner: NicoNex
- License: lgpl-3.0
- Created: 2019-07-22T17:31:49.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2024-10-16T18:51:27.000Z (20 days ago)
- Last Synced: 2024-10-18T09:58:02.239Z (18 days ago)
- Topics: awesome-go, bot, go, golang, golang-library, library, telegram, telegram-api, telegram-bot, telegram-bot-api
- Language: Go
- Homepage: https://t.me/s/echotronnews
- Size: 34.1 MB
- Stars: 368
- Watchers: 8
- Forks: 26
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: COPYING.LESSER
Awesome Lists containing this project
- awesome-go - echotron - An elegant and concurrent library for Telegram Bots in Go. (Bot Building)
- fucking-awesome-go - echotron - An elegant and concurrent library for Telegram Bots in Go. (Bot Building)
- awesome-go - echotron - An elegant and concurrent library for Telegram Bots in Go. (Bot Building)
- awesome-go - echotron - An elegant and concurrent library for Telegram Bots in Go. (Bot Building)
- awesome-go-extra - echotron - 07-22T17:31:49Z|2022-08-24T16:03:48Z| (Bot Building / Free e-books)
- awesome-go-with-stars - echotron - An elegant and concurrent library for Telegram Bots in Go. (Bot Building)
- awesome-go-plus - echotron - An elegant and concurrent library for Telegram Bots in Go. (Bot Building)
- awesome-go-plus - echotron - An elegant and concurrent library for Telegram Bots in Go. (Bot Building)
README
|
[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/) [![PkgGoDev](https://pkg.go.dev/badge/github.com/NicoNex/echotron/v3)](https://pkg.go.dev/github.com/NicoNex/echotron/v3) [![Go Report Card](https://goreportcard.com/badge/github.com/NicoNex/echotron/v3)](https://goreportcard.com/report/github.com/NicoNex/echotron/v3) [![codecov](https://codecov.io/gh/NicoNex/echotron/graph/badge.svg?token=LVJGOEYL5M)](https://codecov.io/gh/NicoNex/echotron) [![License](http://img.shields.io/badge/license-LGPL3.0-orange.svg?style=flat)](https://github.com/NicoNex/echotron/blob/master/LICENSE) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go) [![Telegram](https://img.shields.io/badge/Echotron%20News-blue?logo=telegram&style=flat)](https://t.me/echotronnews) |
| :------: |**Echotron** is an elegant and concurrent library for the Telegram bot API in Go.
Fetch with
```bash
go get github.com/NicoNex/echotron/v3
```## Example
### Simplest implementations
#### Long polling
```golang
package mainimport "github.com/NicoNex/echotron/v3"
const token = "MY TELEGRAM TOKEN"
func main() {
api := echotron.NewAPI(token)for u := range echotron.PollingUpdates(token) {
if u.Message.Text == "/start" {
api.SendMessage("Hello world", u.ChatID(), nil)
}
}
}
```
#### Webhook
```golang
package mainimport "github.com/NicoNex/echotron/v3"
const token = "MY TELEGRAM TOKEN"
func main() {
api := echotron.NewAPI(token)for u := range echotron.WebhookUpdates("https://example.com:443/my_token", token) {
if u.Message.Text == "/start" {
api.SendMessage("Hello world", u.ChatID(), nil)
}
}
}
```
For more scalable and recommended implementations see the other examples.### Long Polling
```golang
package mainimport (
"log"
"time""github.com/NicoNex/echotron/v3"
)// Struct useful for managing internal states in your bot, but it could be of
// any type such as `type bot int64` if you only need to store the chatID.
type bot struct {
chatID int64
echotron.API
}const token = "MY TELEGRAM TOKEN"
// This function needs to be of type 'echotron.NewBotFn' and is called by
// the echotron dispatcher upon any new message from a chatID that has never
// interacted with the bot before.
// This means that echotron keeps one instance of the echotron.Bot implementation
// for each chat where the bot is used.
func newBot(chatID int64) echotron.Bot {
return &bot{
chatID,
echotron.NewAPI(token),
}
}// This method is needed to implement the echotron.Bot interface.
func (b *bot) Update(update *echotron.Update) {
if update.Message.Text == "/start" {
b.SendMessage("Hello world", b.chatID, nil)
}
}func main() {
// This is the entry point of echotron library.
dsp := echotron.NewDispatcher(token, newBot)
for {
log.Println(dsp.Poll())
// In case of connection issues wait 5 seconds before trying to reconnect.
time.Sleep(5 * time.Second)
}
}
```## Design
**Echotron** makes a new instance of the struct bot for each open chat with a Telegram user, channel or group.
This allows to:
- safely call the `Update(*echotron.Update)` method concurrently
- give to the user a convenient way to manage the bot internal states across all the chats
- make sure that, even if one instance of the bot is deadlocked, the other ones keep running just fine, making the bot work for other users without any issues and/or slowdowns.Please note that the the aforementioned behaviour is dictated by the `echotron.Dispatcher` object whose usage is not mandatory and for special needs can be ignored and implemented in different ways still keeping all the methods in the `echotron.API` object.
**Echotron** is designed to be as similar to the official [Telegram API](https://core.telegram.org/bots/api) as possible, but there are some things to take into account before starting to work with this library.
- The methods have the exact same name, but with a capital first letter, since in Go methods have to start with a capital letter to be exported.
_Example: `sendMessage` becomes `SendMessage`_
- The order of the parameters in some methods is different than in the official Telegram API, so refer to the [docs](https://pkg.go.dev/github.com/NicoNex/echotron/v3) for the correct one.
- The only `chat_id` (or, in this case, `chatID`) type supported is `int64`, instead of the "Integer or String" requirement of the official API. That's because numeric IDs can't change in any way, which isn't the case with text-based usernames.
- In some methods, you might find a `InputFile` type parameter. [`InputFile`](https://pkg.go.dev/github.com/NicoNex/echotron/v3#InputFile) is a struct with unexported fields, since only three combination of fields are valid, which can be obtained through the methods [`NewInputFileID`](https://pkg.go.dev/github.com/NicoNex/echotron/v3#NewInputFileID), [`NewInputFilePath`](https://pkg.go.dev/github.com/NicoNex/echotron/v3#NewInputFilePath) and [`NewInputFileBytes`](https://pkg.go.dev/github.com/NicoNex/echotron/v3#NewInputFileBytes).
- In some methods, you might find a `MessageIDOptions` type parameter. [`MessageIDOptions`](https://pkg.go.dev/github.com/NicoNex/echotron/v3#MessageIDOptions) is another struct with unexported fields, since only two combination of field are valid, which can be obtained through the methods [`NewMessageID`](https://pkg.go.dev/github.com/NicoNex/echotron/v3#NewMessageID) and [`NewInlineMessageID`](https://pkg.go.dev/github.com/NicoNex/echotron/v3#NewInlineMessageID).
- Optional parameters can be added by passing the correct struct to each method that might request optional parameters. If you don't want to pass any optional parameter, `nil` is more than enough. Refer to the [docs](https://pkg.go.dev/github.com/NicoNex/echotron/v3) to check for each method's optional parameters struct: it's the type of the `opts` parameter.
- Some parameters are hardcoded to avoid putting random stuff which isn't recognized by the Telegram API. Some notable examples are [`ParseMode`](https://github.com/NicoNex/echotron/blob/master/options.go#L21), [`ChatAction`](https://github.com/NicoNex/echotron/blob/master/options.go#L54) and [`InlineQueryType`](https://github.com/NicoNex/echotron/blob/master/inline.go#L27). For a full list of custom hardcoded parameters, refer to the [docs](https://pkg.go.dev/github.com/NicoNex/echotron/v3) for each custom type: by clicking on the type's name, you'll get the source which contains the possible values for that type.## Additional examples
### Functional approach to state management
```golang
package mainimport (
"log"
"strings""github.com/NicoNex/echotron/v3"
)// Recursive type definition of the bot state function.
type stateFn func(*echotron.Update) stateFntype bot struct {
chatID int64
state stateFn
name string
echotron.API
}const token = "MY TELEGRAM TOKEN"
func newBot(chatID int64) echotron.Bot {
bot := &bot{
chatID: chatID,
API: echotron.NewAPI(token),
}
// We set the default state to the bot.handleMessage method.
bot.state = bot.handleMessage
return bot
}func (b *bot) Update(update *echotron.Update) {
// Here we execute the current state and set the next one.
b.state = b.state(update)
}func (b *bot) handleMessage(update *echotron.Update) stateFn {
if strings.HasPrefix(update.Message.Text, "/set_name") {
b.SendMessage("Send me my new name!", b.chatID, nil)
// Here we return b.handleName since next time we receive a message it
// will be the new name.
return b.handleName
}
return b.handleMessage
}func (b *bot) handleName(update *echotron.Update) stateFn {
b.name = update.Message.Text
b.SendMessage(fmt.Sprintf("My new name is %q", b.name), b.chatID, nil)
// Here we return b.handleMessage since the next time we receive a message
// it will be handled in the default way.
return b.handleMessage
}func main() {
dsp := echotron.NewDispatcher(token, newBot)
log.Println(dsp.Poll())
}
```### Self destruction for lower memory footprint
```golang
package mainimport (
"log"
"time""github.com/NicoNex/echotron/v3"
)type bot struct {
chatID int64
echotron.API
}const token = "MY TELEGRAM TOKEN"
var dsp *echotron.Dispatcher
func newBot(chatID int64) echotron.Bot {
bot := &bot{
chatID,
echotron.NewAPI(token),
}
go bot.selfDestruct(time.After(time.Hour))
return bot
}func (b *bot) selfDestruct(timech <-chan time.Time) {
<-timech
b.SendMessage("goodbye", b.chatID, nil)
dsp.DelSession(b.chatID)
}func (b *bot) Update(update *echotron.Update) {
if update.Message.Text == "/start" {
b.SendMessage("Hello world", b.chatID, nil)
}
}func main() {
dsp = echotron.NewDispatcher(token, newBot)
log.Println(dsp.Poll())
}
```### Webhook
```golang
package mainimport "github.com/NicoNex/echotron/v3"
type bot struct {
chatID int64
echotron.API
}const token = "MY TELEGRAM TOKEN"
func newBot(chatID int64) echotron.Bot {
return &bot{
chatID,
echotron.NewAPI(token),
}
}func (b *bot) Update(update *echotron.Update) {
if update.Message.Text == "/start" {
b.SendMessage("Hello world", b.chatID, nil)
}
}func main() {
dsp := echotron.NewDispatcher(token, newBot)
dsp.ListenWebhook("https://example.com:443/my_bot_token")
}
```### Webhook with a custom http.Server
This is an example for a custom http.Server which handles your own specified routes
and also the webhook route which is specified by ListenWebhook.```golang
package mainimport (
"github.com/NicoNex/echotron/v3""context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
)type bot struct {
chatID int64
echotron.API
}const token = "MY TELEGRAM TOKEN"
func newBot(chatID int64) echotron.Bot {
return &bot{
chatID,
echotron.NewAPI(token),
}
}func (b *bot) Update(update *echotron.Update) {
if update.Message.Text == "/start" {
b.SendMessage("Hello world", b.chatID, nil)
}
}func main() {
termChan := make(chan os.Signal, 1) // Channel for terminating the app via os.Interrupt signal
signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM)mux := http.NewServeMux()
mux.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
// Handle user login
})
mux.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) {
// Handle user logout
})
mux.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
// Tell something about your awesome telegram bot
})// Set custom http.Server
server := &http.Server{Addr: ":8080", Handler: mux}go func() {
<-termChan
// Perform some cleanup..
if err := server.Shutdown(context.Background()); err != nil {
log.Print(err)
}
}()// Capture the interrupt signal for app termination handling
dsp := echotron.NewDispatcher(token, newBot)
dsp.SetHTTPServer(server)
// Start your custom http.Server with a registered /my_bot_token handler.
log.Println(dsp.ListenWebhook("https://example.com/my_bot_token"))
}
```