112 lines
3.0 KiB
Go
112 lines
3.0 KiB
Go
package telegram
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"time"
|
|
|
|
"github.com/mymmrac/telego"
|
|
th "github.com/mymmrac/telego/telegohandler"
|
|
|
|
"git.entityseven.com/rilaxik/pllist/internal/service"
|
|
accesstelegram "git.entityseven.com/rilaxik/pllist/internal/telegram/access"
|
|
itemtelegram "git.entityseven.com/rilaxik/pllist/internal/telegram/item"
|
|
"git.entityseven.com/rilaxik/pllist/internal/telegram/list"
|
|
"git.entityseven.com/rilaxik/pllist/internal/telegram/menu"
|
|
sharetelegram "git.entityseven.com/rilaxik/pllist/internal/telegram/share"
|
|
"git.entityseven.com/rilaxik/pllist/internal/telegram/shared"
|
|
)
|
|
|
|
const (
|
|
shutdownTimeout = 10 * time.Second
|
|
updateTimeout = 30 * time.Second
|
|
)
|
|
|
|
type Bot struct {
|
|
api *telego.Bot
|
|
handler *th.BotHandler
|
|
logger *slog.Logger
|
|
users *service.UserService
|
|
botAccess *service.BotAccessService
|
|
shares *service.ShareService
|
|
pending *service.PendingStore
|
|
sender *shared.Sender
|
|
pendingRouter *shared.PendingRouter
|
|
menu *menu.Handler
|
|
access *accesstelegram.Handler
|
|
list *list.Handler
|
|
item *itemtelegram.Handler
|
|
share *sharetelegram.Handler
|
|
locker *keyedLocker
|
|
}
|
|
|
|
func New(
|
|
api *telego.Bot,
|
|
updates <-chan telego.Update,
|
|
users *service.UserService,
|
|
lists *service.ListService,
|
|
items *service.ItemService,
|
|
shares *service.ShareService,
|
|
access *service.AccessService,
|
|
botAccess *service.BotAccessService,
|
|
pending *service.PendingStore,
|
|
logger *slog.Logger,
|
|
) (*Bot, error) {
|
|
if logger == nil {
|
|
logger = slog.Default()
|
|
}
|
|
sender := shared.NewSender(api)
|
|
itemHandler := itemtelegram.New(sender, items, access, pending)
|
|
bot := &Bot{
|
|
api: api,
|
|
logger: logger,
|
|
users: users,
|
|
botAccess: botAccess,
|
|
shares: shares,
|
|
pending: pending,
|
|
sender: sender,
|
|
pendingRouter: shared.NewPendingRouter(),
|
|
menu: menu.New(sender, pending, botAccess),
|
|
access: accesstelegram.New(sender, botAccess),
|
|
list: list.New(sender, lists, access, pending, itemHandler),
|
|
item: itemHandler,
|
|
share: sharetelegram.New(sender, shares, pending),
|
|
locker: newKeyedLocker(),
|
|
}
|
|
|
|
handler, err := th.NewBotHandler(api, updates, th.WithErrorHandler(bot.handleError))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("create bot handler: %w", err)
|
|
}
|
|
bot.handler = handler
|
|
|
|
handler.Use(
|
|
th.PanicRecoveryHandler(func(recovered any) error {
|
|
return fmt.Errorf("panic: %v", recovered)
|
|
}),
|
|
th.Timeout(updateTimeout),
|
|
bot.answerCallback,
|
|
bot.serialize,
|
|
bot.privateOnly,
|
|
bot.requireAccess,
|
|
bot.withUser,
|
|
)
|
|
bot.register()
|
|
|
|
return bot, nil
|
|
}
|
|
|
|
func (b *Bot) Run() error {
|
|
if err := b.handler.Start(); err != nil {
|
|
return fmt.Errorf("start bot handler: %w", err)
|
|
}
|
|
|
|
stopCtx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
|
|
defer cancel()
|
|
if err := b.handler.StopWithContext(stopCtx); err != nil {
|
|
return fmt.Errorf("stop bot handler: %w", err)
|
|
}
|
|
return nil
|
|
}
|