package run import ( "context" "fmt" "os" "os/signal" "syscall" "gitea.dwysokinski.me/twhelp/dcbot/cmd/dcbot/internal" "gitea.dwysokinski.me/twhelp/dcbot/internal/adapter" "gitea.dwysokinski.me/twhelp/dcbot/internal/discord" "gitea.dwysokinski.me/twhelp/dcbot/internal/service" "github.com/kelseyhightower/envconfig" "github.com/urfave/cli/v2" "go.uber.org/zap" ) const ( healthyFilePath = "/tmp/healthy" healthyFilePerm = 0644 ) func New() *cli.Command { return &cli.Command{ Name: "run", Usage: "Runs the dc bot", Action: func(c *cli.Context) error { logger := zap.L() cfg, err := newBotConfig() if err != nil { return fmt.Errorf("newBotConfig: %w", err) } db, err := internal.NewBunDB() if err != nil { return fmt.Errorf("internal.NewBunDB: %w", err) } defer func() { _ = db.Close() }() redisClient, err := internal.NewRedisClient() if err != nil { return err } twhelpService, err := internal.NewTWHelpService(c.App.Version) if err != nil { return fmt.Errorf("internal.NewTWHelpService: %w", err) } groupRepo := adapter.NewGroupBun(db) villageRepo := adapter.NewVillageRedis(redisClient) choiceSvc := service.NewChoice(twhelpService) groupSvc := service.NewGroup(groupRepo, twhelpService, logger, cfg.MaxGroupsPerServer, cfg.MaxMonitorsPerGroup) villageSvc := service.NewVillage(villageRepo, twhelpService) bot, err := discord.NewBot(cfg.Token, groupSvc, choiceSvc, villageSvc, logger) if err != nil { return fmt.Errorf("discord.NewBot: %w", err) } defer func() { _ = bot.Close() }() go func() { if runErr := bot.Run(); runErr != nil { logger.Fatal("something went wrong while starting the bot", zap.Error(runErr)) } }() if err = os.WriteFile(healthyFilePath, []byte("healthy"), healthyFilePerm); err != nil { return fmt.Errorf("couldn't create file (path=%s): %w", healthyFilePath, err) } waitForSignal(c.Context) return nil }, } } type botConfig struct { Token string `envconfig:"TOKEN" required:"true"` MaxGroupsPerServer int `envconfig:"MAX_GROUPS_PER_SERVER" default:"5"` MaxMonitorsPerGroup int `envconfig:"MAX_MONITORS_PER_GROUP" default:"10"` } func newBotConfig() (botConfig, error) { var cfg botConfig if err := envconfig.Process("BOT", &cfg); err != nil { return botConfig{}, fmt.Errorf("envconfig.Process: %w", err) } return cfg, nil } func waitForSignal(ctx context.Context) { ctx, stop := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM) defer stop() <-ctx.Done() }