Files
mgdigital 6358b27bc6 Search query string rework (#96)
- `search_string` field is removed
- text search vector for `content` and `torrent_contents` is generated in code with improvements in normalisation and tokenisation
- the slow `LIKE` query is removed from text search
- a query DSL is implemented which translates the input search string to a Postgres tsquery
- a CLI command (`reindex`) is provided for updating the tsv for pre-existing records
- the unused `tsv` and `search_string` fields are removed from the `torrents` table

See https://github.com/bitmagnet-io/bitmagnet/issues/89
2024-01-07 11:51:40 +00:00

97 lines
2.9 KiB
Go

package video
import (
"context"
"errors"
"github.com/bitmagnet-io/bitmagnet/internal/classifier"
"github.com/bitmagnet-io/bitmagnet/internal/classifier/video/tmdb"
"github.com/bitmagnet-io/bitmagnet/internal/model"
)
type videoResolver struct {
config classifier.SubResolverConfig
tmdbClient tmdb.Client
}
func (r videoResolver) Config() classifier.SubResolverConfig {
return r.config
}
func (r videoResolver) PreEnrich(content model.TorrentContent) (model.TorrentContent, error) {
return PreEnrich(content)
}
func (r videoResolver) Resolve(ctx context.Context, content model.TorrentContent) (model.TorrentContent, error) {
if content.ContentType.Valid {
switch content.ContentType.ContentType {
case model.ContentTypeMovie:
return r.resolveMovie(ctx, content)
case model.ContentTypeTvShow:
return r.resolveTvShow(ctx, content)
}
}
return model.TorrentContent{}, classifier.ErrNoMatch
}
func (r videoResolver) resolveMovie(ctx context.Context, tc model.TorrentContent) (model.TorrentContent, error) {
externalIds := tc.ExternalIds.OrderedEntries()
if len(externalIds) > 0 {
for _, id := range externalIds {
if movie, err := r.tmdbClient.GetMovieByExternalId(ctx, id.Key, id.Value); err == nil {
if err := tc.SetContent(movie); err != nil {
return model.TorrentContent{}, err
}
return tc, nil
} else if !errors.Is(err, tmdb.ErrNotFound) {
return model.TorrentContent{}, err
}
}
} else if !tc.ReleaseYear.IsNil() {
if movie, err := r.tmdbClient.SearchMovie(ctx, tmdb.SearchMovieParams{
Title: tc.Title,
Year: tc.ReleaseYear,
IncludeAdult: true,
LevenshteinThreshold: 5,
}); err == nil {
if err := tc.SetContent(movie); err != nil {
return model.TorrentContent{}, err
}
return tc, nil
} else if !errors.Is(err, tmdb.ErrNotFound) {
return model.TorrentContent{}, err
}
}
return model.TorrentContent{}, classifier.ErrNoMatch
}
func (r videoResolver) resolveTvShow(ctx context.Context, tc model.TorrentContent) (model.TorrentContent, error) {
externalIds := tc.ExternalIds.OrderedEntries()
if len(externalIds) > 0 {
for _, id := range externalIds {
if tvShow, err := r.tmdbClient.GetTvShowByExternalId(ctx, id.Key, id.Value); err == nil {
if err := tc.SetContent(tvShow); err != nil {
return model.TorrentContent{}, err
}
return tc, nil
} else if !errors.Is(err, tmdb.ErrNotFound) {
return model.TorrentContent{}, err
}
}
} else {
if tvShow, err := r.tmdbClient.SearchTvShow(ctx, tmdb.SearchTvShowParams{
Name: tc.Title,
FirstAirDateYear: tc.ReleaseYear,
IncludeAdult: true,
LevenshteinThreshold: 5,
}); err == nil {
if err := tc.SetContent(tvShow); err != nil {
return model.TorrentContent{}, err
}
return tc, nil
} else if !errors.Is(err, tmdb.ErrNotFound) {
return model.TorrentContent{}, err
}
}
return model.TorrentContent{}, classifier.ErrNoMatch
}