package app import ( "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/config" "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/db" "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/handler" "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/handler/iface" "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/locale" "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/logger" "github.com/mymmrac/telego" "go.uber.org/zap" "gorm.io/gorm" "net/url" ) type App struct { Logger *zap.SugaredLogger Telegram *telego.Bot BotProfile *telego.User Config *config.Config Repositories *db.Repositories Handlers map[handler.Type]handler.Handler db *gorm.DB } func (a *App) Start() error { if err := a.loadConfig(); err != nil { return err } if err := a.initLogger(); err != nil { return err } if a.Config.Debug { a.Logger.Debugf("loaded configuration: %+v", a.Config) } if err := a.migrateDB(); err != nil { return err } if err := a.initDB(); err != nil { return err } if err := a.initTelegram(); err != nil { return err } a.initHandlers() a.Logger.Info("Vega Poker Bot is running") if a.Config.Listen == "" || !a.isValidURL(a.Config.WebhookURL) { return a.longPoll() } return a.listenWebhook() } func (a *App) Log() *zap.SugaredLogger { return a.Logger } func (a *App) TG() *telego.Bot { return a.Telegram } func (a *App) TGProfile() *telego.User { return a.BotProfile } func (a *App) Conf() *config.Config { return a.Config } func (a *App) DB() iface.Repositories { return &DBWrapper{a.Repositories} } func (a *App) Localizer(lang string) locale.Localizer { return locale.For(lang) } func (a *App) loadConfig() error { config, err := config.LoadConfig() if err != nil { return err } a.Config = config return nil } func (a *App) initLogger() error { var err error a.Logger, err = logger.NewLogger(a.Config.Debug) return err } func (a *App) migrateDB() error { return db.Migrate(a.Config.PostgresDSN) } func (a *App) initDB() error { conn, err := db.Connect(a.Config.PostgresDSN) if err != nil { return err } a.Repositories = db.InitRepositories(conn) return nil } func (a *App) initTelegram() error { var err error a.Telegram, err = telego.NewBot(a.Config.TelegramToken, logger.WrapForTelego(a.Logger, a.Config.Debug)) if err != nil { return err } a.BotProfile, err = a.Telegram.GetMe() return err } func (a *App) initHandlers() { a.Handlers = map[handler.Type]handler.Handler{ handler.Noop: handler.NewNoopHandler(a.Logger, a.Config.Debug), handler.Message: handler.NewMessageHandler(a), handler.ChatMemberUpdated: handler.NewChatMemberUpdatedHandler(a), handler.CallbackQuery: handler.NewCallbackQueryHandler(a), } } func (a *App) handler(update telego.Update) handler.Handler { if update.Message != nil { return a.Handlers[handler.Message] } if update.MyChatMember != nil { return a.Handlers[handler.ChatMemberUpdated] } if update.CallbackQuery != nil { return a.Handlers[handler.CallbackQuery] } return a.Handlers[handler.Noop] } func (a *App) processUpdate(update telego.Update) { defer func() { if r := recover(); r != nil { a.Logger.Errorf("recovered from panic inside the handler: %v", r) } }() if err := a.handler(update).Handle(update); err != nil { a.Logger.Errorf("error while handling the update: %s", err) } } func (a *App) longPoll() error { _ = a.Telegram.DeleteWebhook(&telego.DeleteWebhookParams{}) updates, err := a.Telegram.UpdatesViaLongPolling(nil) if err != nil { return err } defer a.Telegram.StopLongPolling() for update := range updates { go a.processUpdate(update) } return nil } func (a *App) listenWebhook() error { uri, _ := url.Parse(a.Config.WebhookURL) err := a.Telegram.SetWebhook(&telego.SetWebhookParams{ URL: a.Config.WebhookURL, }) if err != nil { return err } a.Logger.Debugf("fetching updates from webhook: %s", uri.Path) updates, err := a.Telegram.UpdatesViaWebhook(uri.Path) if err != nil { return err } go func() { _ = a.Telegram.StartWebhook(a.Config.Listen) }() defer func() { _ = a.Telegram.StopWebhook() }() for update := range updates { go a.processUpdate(update) } return nil } func (a *App) isValidURL(uri string) bool { if uri == "" { return false } _, err := url.Parse(uri) return err == nil }