mirror of
https://github.com/idanoo/autobrr
synced 2025-07-23 16:59:12 +00:00
Feature: Get size by api for ptp btn and ggn (#66)
* chore: add package * feat: get size by api for ptp and btn * feat: download and parse torrent if not api * feat: bypass tls check and load meta from file * fix: no invite command needed for btn * feat: add ggn api * feat: imrpove logging * feat: build request url * feat: improve err logging
This commit is contained in:
parent
d2aa7c1e7e
commit
2ea2293745
32 changed files with 2181 additions and 99 deletions
121
internal/indexer/api.go
Normal file
121
internal/indexer/api.go
Normal file
|
@ -0,0 +1,121 @@
|
|||
package indexer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/autobrr/autobrr/internal/domain"
|
||||
"github.com/autobrr/autobrr/pkg/btn"
|
||||
"github.com/autobrr/autobrr/pkg/ggn"
|
||||
"github.com/autobrr/autobrr/pkg/ptp"
|
||||
)
|
||||
|
||||
type APIService interface {
|
||||
TestConnection(indexer string) (bool, error)
|
||||
GetTorrentByID(indexer string, torrentID string) (*domain.TorrentBasic, error)
|
||||
AddClient(indexer string, settings map[string]string) error
|
||||
RemoveClient(indexer string) error
|
||||
}
|
||||
|
||||
type apiClient interface {
|
||||
GetTorrentByID(torrentID string) (*domain.TorrentBasic, error)
|
||||
TestAPI() (bool, error)
|
||||
}
|
||||
|
||||
type apiService struct {
|
||||
apiClients map[string]apiClient
|
||||
}
|
||||
|
||||
func NewAPIService() APIService {
|
||||
return &apiService{
|
||||
apiClients: make(map[string]apiClient),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *apiService) GetTorrentByID(indexer string, torrentID string) (*domain.TorrentBasic, error) {
|
||||
v, ok := s.apiClients[indexer]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
log.Trace().Str("service", "api").Str("method", "GetTorrentByID").Msgf("'%v' trying to fetch torrent from api", indexer)
|
||||
|
||||
t, err := v.GetTorrentByID(torrentID)
|
||||
if err != nil {
|
||||
log.Error().Stack().Err(err).Msgf("could not get torrent: '%v' from: %v", torrentID, indexer)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Trace().Str("service", "api").Str("method", "GetTorrentByID").Msgf("'%v' successfully fetched torrent from api: %+v", indexer, t)
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (s *apiService) TestConnection(indexer string) (bool, error) {
|
||||
v, ok := s.apiClients[indexer]
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
t, err := v.TestAPI()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (s *apiService) AddClient(indexer string, settings map[string]string) error {
|
||||
// basic validation
|
||||
if indexer == "" {
|
||||
return fmt.Errorf("api_service.add_client: validation falied: indexer can't be empty")
|
||||
} else if len(settings) == 0 {
|
||||
return fmt.Errorf("api_service.add_client: validation falied: settings can't be empty")
|
||||
}
|
||||
|
||||
log.Trace().Msgf("api-service.add_client: init api client for '%v'", indexer)
|
||||
|
||||
// init client
|
||||
switch indexer {
|
||||
case "btn":
|
||||
key, ok := settings["api_key"]
|
||||
if !ok || key == "" {
|
||||
return fmt.Errorf("api_service: 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 fmt.Errorf("api_service: could not initialize ptp client: missing var 'api_user'")
|
||||
}
|
||||
|
||||
key, ok := settings["api_key"]
|
||||
if !ok || key == "" {
|
||||
return fmt.Errorf("api_service: 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 fmt.Errorf("api_service: could not initialize ggn client: missing var 'api_key'")
|
||||
}
|
||||
s.apiClients[indexer] = ggn.NewClient("", key)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("api_service: could not initialize client: unsupported indexer '%v'", indexer)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *apiService) RemoveClient(indexer string) error {
|
||||
_, ok := s.apiClients[indexer]
|
||||
if ok {
|
||||
delete(s.apiClients, indexer)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -11,6 +11,7 @@ protocol: torrent
|
|||
supports:
|
||||
- irc
|
||||
- rss
|
||||
- api
|
||||
source: gazelle
|
||||
settings:
|
||||
- name: authkey
|
||||
|
@ -21,6 +22,22 @@ settings:
|
|||
type: secret
|
||||
label: Torrent pass
|
||||
help: Right click DL on a torrent and get the torrent_pass.
|
||||
- name: api_key
|
||||
type: secret
|
||||
label: API Key
|
||||
help: Username -> Edit Profile -> API
|
||||
|
||||
api:
|
||||
url: https://api.broadcasthe.net
|
||||
type: jsonrpc
|
||||
limits:
|
||||
max: 150
|
||||
per: hour
|
||||
settings:
|
||||
- name: api_key
|
||||
type: secret
|
||||
label: API Key
|
||||
help: Username -> Edit Profile -> API
|
||||
|
||||
irc:
|
||||
network: BroadcasTheNet
|
||||
|
@ -42,12 +59,6 @@ irc:
|
|||
required: true
|
||||
label: NickServ Password
|
||||
help: NickServ password
|
||||
- name: invite_command
|
||||
type: secret
|
||||
default: "CableGuy IDENTIFY USERNAME IRCKey"
|
||||
required: true
|
||||
label: Invite command
|
||||
help: Invite auth with CableGuy.
|
||||
|
||||
parse:
|
||||
type: multi
|
||||
|
|
|
@ -11,6 +11,7 @@ protocol: torrent
|
|||
supports:
|
||||
- irc
|
||||
- rss
|
||||
- api
|
||||
source: gazelle
|
||||
settings:
|
||||
- name: authkey
|
||||
|
@ -21,6 +22,22 @@ settings:
|
|||
type: secret
|
||||
label: Torrent pass
|
||||
help: Right click DL on a torrent and get the torrent_pass.
|
||||
- name: api_key
|
||||
type: secret
|
||||
label: API Key
|
||||
help: Username -> Edit / Settings -> API Keys
|
||||
|
||||
api:
|
||||
url: https://gazellegames.net/api.php
|
||||
type: json
|
||||
limits:
|
||||
max: 5
|
||||
per: 10 seconds
|
||||
settings:
|
||||
- name: api_key
|
||||
type: secret
|
||||
label: API Key
|
||||
help: Username -> Edit / Settings -> API Keys
|
||||
|
||||
irc:
|
||||
network: GGn
|
||||
|
|
|
@ -11,6 +11,7 @@ protocol: torrent
|
|||
supports:
|
||||
- irc
|
||||
- rss
|
||||
- api
|
||||
source: gazelle
|
||||
settings:
|
||||
- name: authkey
|
||||
|
@ -21,6 +22,30 @@ settings:
|
|||
type: secret
|
||||
label: Torrent pass
|
||||
help: Right click DL on a torrent and get the torrent_pass.
|
||||
- name: api_user
|
||||
type: secret
|
||||
label: API User
|
||||
help: Edit profile -> Security -> Generate new api keys
|
||||
- name: api_key
|
||||
type: secret
|
||||
label: API Key
|
||||
help: Edit profile -> Security -> Generate new api keys
|
||||
|
||||
api:
|
||||
url: https://passthepopcorn.me/
|
||||
type: json
|
||||
limits:
|
||||
max: 60
|
||||
per: minute
|
||||
settings:
|
||||
- name: api_user
|
||||
type: secret
|
||||
label: API User
|
||||
help: Edit profile -> Security -> Generate new api keys
|
||||
- name: api_key
|
||||
type: secret
|
||||
label: API Key
|
||||
help: Edit profile -> Security -> Generate new api keys
|
||||
|
||||
irc:
|
||||
network: PassThePopcorn
|
||||
|
|
|
@ -26,7 +26,8 @@ type Service interface {
|
|||
}
|
||||
|
||||
type service struct {
|
||||
repo domain.IndexerRepo
|
||||
repo domain.IndexerRepo
|
||||
apiService APIService
|
||||
|
||||
// contains all raw indexer definitions
|
||||
indexerDefinitions map[string]domain.IndexerDefinition
|
||||
|
@ -37,9 +38,10 @@ type service struct {
|
|||
lookupIRCServerDefinition map[string]map[string]domain.IndexerDefinition
|
||||
}
|
||||
|
||||
func NewService(repo domain.IndexerRepo) Service {
|
||||
func NewService(repo domain.IndexerRepo, apiService APIService) Service {
|
||||
return &service{
|
||||
repo: repo,
|
||||
apiService: apiService,
|
||||
indexerDefinitions: make(map[string]domain.IndexerDefinition),
|
||||
mapIndexerIRCToName: make(map[string]string),
|
||||
lookupIRCServerDefinition: make(map[string]map[string]domain.IndexerDefinition),
|
||||
|
@ -150,6 +152,7 @@ func (s *service) mapIndexer(indexer domain.Indexer) (*domain.IndexerDefinition,
|
|||
Privacy: in.Privacy,
|
||||
Protocol: in.Protocol,
|
||||
URLS: in.URLS,
|
||||
Supports: in.Supports,
|
||||
Settings: nil,
|
||||
SettingsMap: make(map[string]string),
|
||||
IRC: in.IRC,
|
||||
|
@ -184,23 +187,34 @@ func (s *service) GetTemplates() ([]domain.IndexerDefinition, error) {
|
|||
}
|
||||
|
||||
func (s *service) Start() error {
|
||||
// load all indexer definitions
|
||||
err := s.LoadIndexerDefinitions()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// load the indexers' setup by the user
|
||||
indexerDefinitions, err := s.GetAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, indexerDefinition := range indexerDefinitions {
|
||||
s.mapIRCIndexerLookup(indexerDefinition.Identifier, *indexerDefinition)
|
||||
for _, indexer := range indexerDefinitions {
|
||||
s.mapIRCIndexerLookup(indexer.Identifier, *indexer)
|
||||
|
||||
// add to irc server lookup table
|
||||
s.mapIRCServerDefinitionLookup(indexerDefinition.IRC.Server, *indexerDefinition)
|
||||
s.mapIRCServerDefinitionLookup(indexer.IRC.Server, *indexer)
|
||||
|
||||
// check if it has api and add to api service
|
||||
if indexer.Enabled && indexer.HasApi() {
|
||||
if err := s.apiService.AddClient(indexer.Identifier, indexer.SettingsMap); err != nil {
|
||||
log.Error().Stack().Err(err).Msgf("indexer.start: could not init api client for: '%v'", indexer.Identifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Info().Msgf("Loaded %d indexers", len(indexerDefinitions))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -305,7 +319,7 @@ func (s *service) LoadIndexerDefinitions() error {
|
|||
}
|
||||
}
|
||||
|
||||
log.Info().Msgf("Loaded %d indexer definitions", len(s.indexerDefinitions))
|
||||
log.Debug().Msgf("Loaded %d indexer definitions", len(s.indexerDefinitions))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue