mirror of
https://github.com/FJurmanovic/sugarr.git
synced 2026-11-11 07:41:08 +00:00
init
This commit is contained in:
102
cmd/sugarr/main.go
Normal file
102
cmd/sugarr/main.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/fjurmanovic/sugarr/internal/model"
|
||||
"github.com/fjurmanovic/sugarr/internal/service"
|
||||
"github.com/fjurmanovic/sugarr/internal/utl/configs"
|
||||
"github.com/fjurmanovic/sugarr/internal/utl/server"
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
|
||||
cfg, err := configs.Load()
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to load config")
|
||||
}
|
||||
|
||||
printBanner(cfg)
|
||||
|
||||
rec := service.NewRecommender(cfg)
|
||||
|
||||
// Cron scheduler
|
||||
if cfg.CronEnabled {
|
||||
c := cron.New()
|
||||
if _, err := c.AddFunc(cfg.CronSchedule, func() {
|
||||
log.Info().Msg("Cron: running recommendation pipeline")
|
||||
recs, err := rec.Run()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Cron: pipeline failed")
|
||||
return
|
||||
}
|
||||
if cfg.RadarrEnabled {
|
||||
rec.AutoRequest(recs)
|
||||
}
|
||||
logRecommendations(recs)
|
||||
}); err != nil {
|
||||
log.Fatal().Err(err).Msg("Invalid cron schedule")
|
||||
}
|
||||
c.Start()
|
||||
defer c.Stop()
|
||||
log.Info().Msgf("Cron scheduled: %s", cfg.CronSchedule)
|
||||
}
|
||||
|
||||
// HTTP API — blocks until server exits
|
||||
if cfg.APIEnabled {
|
||||
if err := server.Start(cfg, rec); err != nil {
|
||||
log.Fatal().Err(err).Msg("HTTP server failed")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// One-shot mode: no API, no cron
|
||||
if !cfg.CronEnabled {
|
||||
recs, err := rec.Run()
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Recommendation pipeline failed")
|
||||
}
|
||||
printTable(recs)
|
||||
return
|
||||
}
|
||||
|
||||
// Cron-only mode: block forever
|
||||
select {}
|
||||
}
|
||||
|
||||
func printBanner(cfg *configs.Config) {
|
||||
log.Info().Msg("sugarr starting")
|
||||
log.Info().Msgf(" Jellyfin: %s (user: %s)", cfg.JellyfinURL, cfg.JellyfinUserID)
|
||||
log.Info().Msgf(" LLM: enabled=%v model=%s", cfg.LLMEnabled, cfg.LLMModel)
|
||||
log.Info().Msgf(" Radarr: enabled=%v", cfg.RadarrEnabled)
|
||||
log.Info().Msgf(" Cron: enabled=%v schedule=%s", cfg.CronEnabled, cfg.CronSchedule)
|
||||
log.Info().Msgf(" API: enabled=%v port=%d", cfg.APIEnabled, cfg.APIPort)
|
||||
log.Info().Msgf(" Count: %d recommendations", cfg.RecommendCount)
|
||||
}
|
||||
|
||||
func logRecommendations(recs []model.Recommendation) {
|
||||
log.Info().Msgf("Recommendations (%d):", len(recs))
|
||||
for i, r := range recs {
|
||||
log.Info().Msgf(" %d. %s (%d) [tmdb:%d] — %s", i+1, r.Title, r.Year, r.TMDbID, r.Reason)
|
||||
}
|
||||
}
|
||||
|
||||
func printTable(recs []model.Recommendation) {
|
||||
if len(recs) == 0 {
|
||||
fmt.Println("No recommendations found.")
|
||||
return
|
||||
}
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, "#\tTitle\tYear\tTMDb ID\tReason")
|
||||
fmt.Fprintln(w, "-\t-----\t----\t-------\t------")
|
||||
for i, r := range recs {
|
||||
fmt.Fprintf(w, "%d\t%s\t%d\t%d\t%s\n", i+1, r.Title, r.Year, r.TMDbID, r.Reason)
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
Reference in New Issue
Block a user