Files
nabarr/media/client.go
dev 719528a06b
Some checks failed
Build / build (push) Failing after 13m30s
feat: enrich RSS items without IDs via TMDB title search
Items from RSS feeds that have no media ID (tmdb/imdb/tvdb) are now
enriched automatically using TMDB's search API. The release name is
parsed to extract a clean title and year, then searched against TMDB
to retrieve the TMDB ID before validation.

- Add media/tmdb package with SearchMovies, SearchShows, and
  ExtractTitleAndYear (parses torrent release names)
- Add EnrichFeedItemWithTmdbId to media.Client, called in rss/process.go
  before the ID validation switch
- Add --run-now flag to nabarr run to trigger all feeds immediately
- Wire media.Client through rss.Client and rssJob
- Merge feature/add-tag-option (tag support for Sonarr/Radarr)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 16:53:54 +00:00

90 lines
1.9 KiB
Go

package media
import (
"fmt"
"strconv"
"strings"
"github.com/rs/zerolog"
"github.com/l3uddz/nabarr/logger"
"github.com/l3uddz/nabarr/media/omdb"
"github.com/l3uddz/nabarr/media/tmdb"
"github.com/l3uddz/nabarr/media/trakt"
"github.com/l3uddz/nabarr/media/tvdb"
"github.com/l3uddz/nabarr/util"
)
type Client struct {
trakt *trakt.Client
omdb *omdb.Client
tvdb *tvdb.Client
tmdb *tmdb.Client
log zerolog.Logger
}
func (c *Client) EnrichFeedItemWithTmdbId(item *FeedItem) {
if c.tmdb == nil {
return
}
// skip if a valid ID is already present
hasId := (item.TvdbId != "" && !util.StringSliceContains([]string{"0", "1"}, item.TvdbId)) ||
(item.ImdbId != "" && strings.HasPrefix(item.ImdbId, "tt")) ||
(item.TmdbId != "" && !util.StringSliceContains([]string{"0", "1"}, item.TmdbId))
if hasId {
return
}
title, year := tmdb.ExtractTitleAndYear(item.Title)
if title == "" {
return
}
var tmdbId int
switch {
case util.ContainsMovieCategory(item.Categories):
if id, err := c.tmdb.SearchMovies(title, year); err == nil && id > 0 {
tmdbId = id
}
case util.ContainsTvCategory(item.Categories):
if id, err := c.tmdb.SearchShows(title, year); err == nil && id > 0 {
tmdbId = id
}
default:
return
}
if tmdbId > 0 {
item.TmdbId = strconv.Itoa(tmdbId)
c.log.Info().
Str("release", item.Title).
Str("clean_title", title).
Int("year", year).
Int("tmdb_id", tmdbId).
Msg("Enriched item with TMDB ID via title search")
}
}
func New(cfg *Config) (*Client, error) {
// validate trakt configured (it is mandatory)
if cfg.Trakt.ClientId == "" {
return nil, fmt.Errorf("trakt: no client_id specified")
}
var tmdbClient *tmdb.Client
if cfg.Tmdb.ApiKey != "" {
tmdbClient = tmdb.New(&cfg.Tmdb)
}
return &Client{
trakt: trakt.New(&cfg.Trakt),
omdb: omdb.New(&cfg.Omdb),
tvdb: tvdb.New(&cfg.Tvdb),
tmdb: tmdbClient,
log: logger.Child(logger.WithLevel(cfg.Verbosity)),
}, nil
}