autobrr/internal/indexer/api.go
ze0s 604c7896bd
chore: add LICENSE GPLv2-or-later (#897)
* chore: add LICENSE

* chore: add LICENSE to README
2023-05-01 16:21:59 +02:00

185 lines
5.4 KiB
Go

// Copyright (c) 2021 - 2023, Ludvig Lundgren and the autobrr contributors.
// SPDX-License-Identifier: GPL-2.0-or-later
package indexer
import (
"context"
"github.com/rs/zerolog"
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/internal/logger"
"github.com/autobrr/autobrr/internal/mock"
"github.com/autobrr/autobrr/pkg/btn"
"github.com/autobrr/autobrr/pkg/errors"
"github.com/autobrr/autobrr/pkg/ggn"
"github.com/autobrr/autobrr/pkg/ptp"
"github.com/autobrr/autobrr/pkg/red"
)
type APIService interface {
TestConnection(ctx context.Context, req domain.IndexerTestApiRequest) (bool, error)
GetTorrentByID(ctx context.Context, indexer string, torrentID string) (*domain.TorrentBasic, error)
AddClient(indexer string, settings map[string]string) error
RemoveClient(indexer string) error
}
type apiClient interface {
GetTorrentByID(ctx context.Context, torrentID string) (*domain.TorrentBasic, error)
TestAPI(ctx context.Context) (bool, error)
}
type apiService struct {
log zerolog.Logger
apiClients map[string]apiClient
}
func NewAPIService(log logger.Logger) APIService {
return &apiService{
log: log.With().Str("module", "indexer-api").Logger(),
apiClients: make(map[string]apiClient),
}
}
func (s *apiService) GetTorrentByID(ctx context.Context, indexer string, torrentID string) (*domain.TorrentBasic, error) {
client, err := s.getApiClient(indexer)
if err != nil {
s.log.Error().Stack().Err(err).Msgf("could not get api client for: %s", indexer)
return nil, errors.Wrap(err, "could not get torrent via api for indexer: %s", indexer)
}
s.log.Trace().Str("method", "GetTorrentByID").Msgf("%s fetching torrent from api...", indexer)
torrent, err := client.GetTorrentByID(ctx, torrentID)
if err != nil {
s.log.Error().Stack().Err(err).Msgf("could not get torrent: %s from: %s", torrentID, indexer)
return nil, err
}
s.log.Trace().Str("method", "GetTorrentByID").Msgf("%s api successfully fetched torrent: %+v", indexer, torrent)
return torrent, nil
}
func (s *apiService) TestConnection(ctx context.Context, req domain.IndexerTestApiRequest) (bool, error) {
client, err := s.getClientForTest(req)
if err != nil {
return false, errors.New("could not init api client: %s", req.Identifier)
}
success, err := client.TestAPI(ctx)
if err != nil {
s.log.Error().Err(err).Msgf("error testing connection for api: %s", req.Identifier)
return false, err
}
return success, nil
}
func (s *apiService) AddClient(indexer string, settings map[string]string) error {
s.log.Trace().Msgf("api.Service.AddClient: init api client for: %s", indexer)
// init client
switch indexer {
case "btn":
key, ok := settings["api_key"]
if !ok || key == "" {
return errors.New("api.Service.AddClient: could not initialize btn client: missing var 'api_key'")
}
s.apiClients[indexer] = btn.NewClient("", key)
case "ptp":
user, ok := settings["api_user"]
if !ok || user == "" {
return errors.New("api.Service.AddClient: could not initialize ptp client: missing var 'api_user'")
}
key, ok := settings["api_key"]
if !ok || key == "" {
return errors.New("api.Service.AddClient: could not initialize ptp client: missing var 'api_key'")
}
s.apiClients[indexer] = ptp.NewClient(user, key)
case "ggn":
key, ok := settings["api_key"]
if !ok || key == "" {
return errors.New("api.Service.AddClient: could not initialize ggn client: missing var 'api_key'")
}
s.apiClients[indexer] = ggn.NewClient(key)
case "redacted":
key, ok := settings["api_key"]
if !ok || key == "" {
return errors.New("api.Service.AddClient: could not initialize red client: missing var 'api_key'")
}
s.apiClients[indexer] = red.NewClient(key)
case "mock":
s.apiClients[indexer] = mock.NewMockClient("", "mock")
default:
return errors.New("api.Service.AddClient: could not initialize client: unsupported indexer: %s", indexer)
}
return nil
}
func (s *apiService) getApiClient(indexer string) (apiClient, error) {
client, ok := s.apiClients[indexer]
if !ok {
return nil, errors.New("could not find api client for: %s", indexer)
}
return client, nil
}
func (s *apiService) getClientForTest(req domain.IndexerTestApiRequest) (apiClient, error) {
// init client
switch req.Identifier {
case "btn":
if req.ApiKey == "" {
return nil, errors.New("api.Service.AddClient: could not initialize btn client: missing var 'api_key'")
}
return btn.NewClient("", req.ApiKey), nil
case "ptp":
if req.ApiUser == "" {
return nil, errors.New("api.Service.AddClient: could not initialize ptp client: missing var 'api_user'")
}
if req.ApiKey == "" {
return nil, errors.New("api.Service.AddClient: could not initialize ptp client: missing var 'api_key'")
}
return ptp.NewClient(req.ApiUser, req.ApiKey), nil
case "ggn":
if req.ApiKey == "" {
return nil, errors.New("api.Service.AddClient: could not initialize ggn client: missing var 'api_key'")
}
return ggn.NewClient(req.ApiKey), nil
case "redacted":
if req.ApiKey == "" {
return nil, errors.New("api.Service.AddClient: could not initialize red client: missing var 'api_key'")
}
return red.NewClient(req.ApiKey), nil
case "mock":
return mock.NewMockClient("", "mock"), nil
default:
return nil, errors.New("api.Service.AddClient: could not initialize client: unsupported indexer: %s", req.Identifier)
}
}
func (s *apiService) RemoveClient(indexer string) error {
_, ok := s.apiClients[indexer]
if ok {
delete(s.apiClients, indexer)
}
return nil
}