Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade telegram api #17049

Merged
merged 4 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ func configureMessengers(conf globalconfig.Messaging, vehicles push.Vehicles, va
}

for _, service := range conf.Services {
impl, err := push.NewFromConfig(service.Type, service.Other)
impl, err := push.NewFromConfig(context.TODO(), service.Type, service.Other)
if err != nil {
return messageChan, fmt.Errorf("failed configuring push service %s: %w", service.Type, err)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ require (
github.com/glebarez/sqlite v1.11.0
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
github.com/go-playground/validator/v10 v10.22.1
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
github.com/go-telegram/bot v1.10.0
github.com/go-viper/mapstructure/v2 v2.2.1
github.com/godbus/dbus/v5 v5.1.0
github.com/gokrazy/updater v0.0.0-20240113102150-4ac511a17e33
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=
github.com/go-telegram/bot v1.10.0 h1:/Y9ZupcZhYQiAOFE1ETCF8P4836XE42nDkLcWHYTg3g=
github.com/go-telegram/bot v1.10.0/go.mod h1:i2TRs7fXWIeaceF3z7KzsMt/he0TwkVC680mvdTFYeM=
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
Expand Down
39 changes: 13 additions & 26 deletions push/config.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,31 @@
package push

import (
"context"
"fmt"
"strings"

reg "github.com/evcc-io/evcc/util/registry"
)

// Messenger implements message sending
type Messenger interface {
Send(title, msg string)
}

type senderRegistry map[string]func(map[string]interface{}) (Messenger, error)

func (r senderRegistry) Add(name string, factory func(map[string]interface{}) (Messenger, error)) {
if _, exists := r[name]; exists {
panic(fmt.Sprintf("cannot register duplicate messenger type: %s", name))
}
r[name] = factory
}

func (r senderRegistry) Get(name string) (func(map[string]interface{}) (Messenger, error), error) {
factory, exists := r[name]
if !exists {
return nil, fmt.Errorf("messenger type not registered: %s", name)
}
return factory, nil
}

var registry senderRegistry = make(map[string]func(map[string]interface{}) (Messenger, error))
var registry = reg.New[Messenger]("messenger")

// NewFromConfig creates messenger from configuration
func NewFromConfig(typ string, other map[string]interface{}) (v Messenger, err error) {
func NewFromConfig(ctx context.Context, typ string, other map[string]interface{}) (Messenger, error) {
factory, err := registry.Get(strings.ToLower(typ))
if err == nil {
if v, err = factory(other); err != nil {
err = fmt.Errorf("cannot create messenger '%s': %w", typ, err)
}
} else {
err = fmt.Errorf("invalid messenger type: %s", typ)
if err != nil {
return nil, err
}

v, err := factory(ctx, other)
if err != nil {
err = fmt.Errorf("cannot create messenger type '%s': %w", typ, err)
}

return
return v, err
}
69 changes: 36 additions & 33 deletions push/telegram.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
package push

import (
"context"
"errors"
"strconv"
"sync"

"github.com/evcc-io/evcc/util"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
)

func init() {
registry.Add("telegram", NewTelegramFromConfig)
registry.AddCtx("telegram", NewTelegramFromConfig)
}

// Telegram implements the Telegram messenger
type Telegram struct {
log *util.Logger
sync.Mutex
bot *tgbotapi.BotAPI
bot *bot.Bot
chats map[int64]struct{}
}

// NewTelegramFromConfig creates new pushover messenger
func NewTelegramFromConfig(other map[string]interface{}) (Messenger, error) {
func NewTelegramFromConfig(ctx context.Context, other map[string]interface{}) (Messenger, error) {
var cc struct {
Token string
Chats []int64
Expand All @@ -32,60 +34,61 @@ func NewTelegramFromConfig(other map[string]interface{}) (Messenger, error) {
return nil, err
}

bot, err := tgbotapi.NewBotAPI(cc.Token)
if err != nil {
return nil, errors.New("telegram: invalid bot token")
}

log := util.NewLogger("telegram").Redact(cc.Token)
_ = tgbotapi.SetLogger(log.ERROR)

for _, i := range cc.Chats {
log.Redact(strconv.FormatInt(i, 10))
}

m := &Telegram{
log: log,
bot: bot,
chats: make(map[int64]struct{}),
}

bot, err := bot.New(cc.Token, bot.WithDefaultHandler(m.handler), bot.WithErrorsHandler(func(err error) {
log.ERROR.Println(err)
}), bot.WithDebugHandler(func(format string, args ...interface{}) {
log.TRACE.Printf(format, args...)
}))
if err != nil {
return nil, errors.New("invalid bot token")
}

m.bot = bot

go bot.Start(ctx)

for _, chat := range cc.Chats {
log.Redact(strconv.FormatInt(chat, 10))
m.chats[chat] = struct{}{}
}

go m.trackChats()

return m, nil
}

// trackChats captures ids of all chats that bot participates in
func (m *Telegram) trackChats() {
conf := tgbotapi.NewUpdate(0)
conf.Timeout = 1000
// handler captures ids of all chats that bot participates in
func (m *Telegram) handler(ctx context.Context, b *bot.Bot, update *models.Update) {
if update.Message == nil {
return
}

for update := range m.bot.GetUpdatesChan(conf) {
if update.Message == nil || update.Message.Chat == nil {
continue
}
m.Lock()
if _, ok := m.chats[update.Message.Chat.ID]; !ok {
m.log.INFO.Printf("new chat id: %d", update.Message.Chat.ID)
}
m.Unlock()
m.Lock()
defer m.Unlock()

if _, ok := m.chats[update.Message.Chat.ID]; !ok {
m.log.INFO.Printf("new chat id: %d", update.Message.Chat.ID)
}
}

// Send sends to all receivers
func (m *Telegram) Send(title, msg string) {
m.Lock()
defer m.Unlock()

for chat := range m.chats {
m.log.DEBUG.Printf("sending to %d", chat)

msg := tgbotapi.NewMessage(chat, msg)
if _, err := m.bot.Send(msg); err != nil {
if _, err := m.bot.SendMessage(context.Background(), &bot.SendMessageParams{
ChatID: chat,
Text: msg,
}); err != nil {
m.log.ERROR.Println("send:", err)
}
}
m.Unlock()
}