123 lines
2.8 KiB
Go
123 lines
2.8 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/fujin/music-agregator/internal/config"
|
|
"github.com/fujin/music-agregator/internal/indexer"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type IndexerService struct {
|
|
indexers []*indexer.TorznabIndexer
|
|
}
|
|
|
|
type IndexerInfo struct {
|
|
Name string `json:"name"`
|
|
URL string `json:"url"`
|
|
Healthy bool `json:"healthy"`
|
|
}
|
|
|
|
func NewIndexerService(configs []config.IndexerConfig) (*IndexerService, error) {
|
|
var indexers []*indexer.TorznabIndexer
|
|
|
|
for _, cfg := range configs {
|
|
url := buildTorznabURL(cfg)
|
|
idx, err := indexer.NewTorznabIndexer(cfg.Name, url, cfg.APIKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create indexer %s: %w", cfg.Name, err)
|
|
}
|
|
indexers = append(indexers, idx)
|
|
}
|
|
|
|
svc := &IndexerService{indexers: indexers}
|
|
svc.checkHealth(context.Background())
|
|
|
|
return svc, nil
|
|
}
|
|
|
|
func (s *IndexerService) checkHealth(ctx context.Context) {
|
|
for _, idx := range s.indexers {
|
|
if err := idx.TestConnection(ctx); err != nil {
|
|
log.Warn().
|
|
Str("indexer", idx.Name()).
|
|
Err(err).
|
|
Msg("[INDEXER] failed to connect to indexer")
|
|
} else {
|
|
log.Info().
|
|
Str("indexer", idx.Name()).
|
|
Msg("[INDEXER] connected successfully")
|
|
}
|
|
}
|
|
}
|
|
|
|
func buildTorznabURL(cfg config.IndexerConfig) string {
|
|
url := strings.TrimRight(cfg.URL, "/")
|
|
|
|
switch cfg.IndexerType {
|
|
case config.IndexerTypeJackett:
|
|
if !strings.Contains(url, "/api/") {
|
|
url = fmt.Sprintf("%s/api/v2.0/indexers/all/results/torznab", url)
|
|
}
|
|
case config.IndexerTypeProwlarr:
|
|
if !strings.Contains(url, "/api/") {
|
|
url = fmt.Sprintf("%s/api/v1/indexer/all/newznab", url)
|
|
}
|
|
}
|
|
|
|
return url
|
|
}
|
|
|
|
func (s *IndexerService) Search(ctx context.Context, criteria *indexer.MusicSearchCriteria, indexerName *string) ([]indexer.SearchResult, error) {
|
|
var results []indexer.SearchResult
|
|
|
|
log.Info().
|
|
Str("artist", criteria.Artist).
|
|
Interface("album", criteria.Album).
|
|
Interface("year", criteria.Year).
|
|
Msg("[INDEXER] searching indexers")
|
|
|
|
for _, idx := range s.indexers {
|
|
if indexerName != nil && idx.Name() != *indexerName {
|
|
continue
|
|
}
|
|
|
|
log.Debug().Str("indexer", idx.Name()).Msg("[INDEXER] querying indexer")
|
|
|
|
r, err := idx.Search(ctx, criteria)
|
|
if err != nil {
|
|
log.Warn().
|
|
Str("indexer", idx.Name()).
|
|
Err(err).
|
|
Msg("[INDEXER] search failed")
|
|
continue
|
|
}
|
|
|
|
log.Info().
|
|
Str("indexer", idx.Name()).
|
|
Int("results", len(r)).
|
|
Msg("[INDEXER] search completed")
|
|
|
|
results = append(results, r...)
|
|
}
|
|
|
|
log.Info().Int("total_results", len(results)).Msg("[INDEXER] search finished")
|
|
return results, nil
|
|
}
|
|
|
|
func (s *IndexerService) GetIndexers(ctx context.Context) []IndexerInfo {
|
|
var infos []IndexerInfo
|
|
|
|
for _, idx := range s.indexers {
|
|
healthy := idx.TestConnection(ctx) == nil
|
|
infos = append(infos, IndexerInfo{
|
|
Name: idx.Name(),
|
|
Healthy: healthy,
|
|
})
|
|
}
|
|
|
|
return infos
|
|
}
|