package main import ( "bufio" "context" "log/slog" "os" "strings" "galo/internal/config" "galo/internal/db" "galo/internal/settings" "galo/internal/storage" "galo/internal/store" ) func main() { loadDotEnv(".env") loadDotEnv("../.env") logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})) slog.SetDefault(logger) cfg, err := config.Load() if err != nil { slog.Error("config error", "error", err) os.Exit(1) } ctx := context.Background() pool, err := db.Connect(ctx, cfg.Postgres.DSN()) if err != nil { slog.Error("database connect failed", "error", err) os.Exit(1) } defer pool.Close() repos := store.NewPostgres(pool) secret, err := repos.Settings.Ensure(ctx, settings.JWTSecretKey, settings.GenerateSecret) if err != nil { slog.Error("secret init failed", "error", err) os.Exit(1) } blob, err := storage.Open(ctx, cfg, secret) if err != nil { slog.Error("storage init failed", "error", err) os.Exit(1) } updated, err := repos.Photos.BackfillEXIF(ctx, blob.Get) if err != nil { slog.Error("backfill failed", "error", err) os.Exit(1) } slog.Info("exif backfill complete", "updated", updated) } func loadDotEnv(path string) { f, err := os.Open(path) if err != nil { return } defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } key, value, ok := strings.Cut(line, "=") if !ok { continue } key = strings.TrimSpace(key) value = strings.TrimSpace(value) if _, exists := os.LookupEnv(key); !exists { _ = os.Setenv(key, value) } } }