package main import ( "context" "time" "CatsOfMastodonBotGo/internal/auth" "CatsOfMastodonBotGo/internal/config" "CatsOfMastodonBotGo/internal/database" "CatsOfMastodonBotGo/internal/server" "CatsOfMastodonBotGo/internal/services" "CatsOfMastodonBotGo/internal/web/handlers" "go.uber.org/fx" "go.uber.org/zap" ) func main() { fx.New( fx.Provide( // Logger NewLogger, // Configuration config.Load, // Database database.Connect, // Services services.NewPostService, services.NewImgKitHelper, // Auth auth.NewJwtTokenGenerator, auth.NewGiteaOauth2Token, // Handlers handlers.NewAdminDashboardHandler, handlers.NewApiEndpointHandler, handlers.NewEmbedCardHandler, handlers.NewOauthLoginHandler, ), fx.Invoke( // Start background tasks startBackgroundTasks, // Setup and start server server.SetupRouter, ), fx.Logger(NewFXLogger()), // Optional custom logger ).Run() } // Background tasks as a separate function func startBackgroundTasks( lc fx.Lifecycle, postService *services.PostService, cfg *config.Config, logger *zap.Logger, ) { lc.Append(fx.Hook{ OnStart: func(context.Context) error { ticker := time.NewTicker(10 * time.Minute) runFetchPosts := func() { ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() posts, err := postService.GetPostsFromApi(ctx, cfg.Tag, cfg.Instance) if err != nil { logger.Error("Failed to fetch posts", zap.Error(err)) return } existingPostIds := postService.GetExistingPostIds() existingAccountIds := postService.GetExistingAccountIds() newPosts := postService.GetNewPosts(existingPostIds, posts) newAccounts := postService.GetNewAccounts(existingAccountIds, newPosts) logger.Info("Fetched posts", zap.Int("total", len(posts)), zap.Int("existing", len(existingPostIds)), zap.Int("new", len(newPosts)), zap.Int("new_accounts", len(newAccounts))) if len(newAccounts) > 0 { count := postService.InsertNewAccounts(newAccounts) logger.Info("Inserted accounts", zap.Int("count", count)) } if len(newPosts) > 0 { count := postService.InsertNewPosts(newPosts) logger.Info("Inserted posts", zap.Int("count", count)) } } // Run initial fetch go runFetchPosts() // Start ticker go func() { for range ticker.C { runFetchPosts() } }() return nil }, OnStop: func(context.Context) error { // Cleanup if needed return nil }, }) } // Logger provider func NewLogger() (*zap.Logger, error) { return zap.NewDevelopment() } // Simple logger for fx type FXLogger struct { logger *zap.Logger } func NewFXLogger() *FXLogger { logger, _ := zap.NewDevelopment() return &FXLogger{logger: logger} } func (l *FXLogger) Printf(str string, args ...any) { l.logger.Sugar().Infof(str, args...) }