From 0016228d899113c1af859505504f9a17b669f536 Mon Sep 17 00:00:00 2001 From: ze0s <43699394+zze0s@users.noreply.github.com> Date: Sat, 4 May 2024 12:37:01 +0200 Subject: [PATCH] feat(indexers): add External Identifier to map with ARR indexers (#1534) * feat(indexers): add External Identifier to map with ARR indexers * fix: web build * fix: tests * feat: set identifier for manual processing --- internal/action/exec_test.go | 7 +- internal/action/lidarr.go | 2 +- internal/action/radarr.go | 2 +- internal/action/readarr.go | 2 +- internal/action/sonarr.go | 2 +- internal/action/whisparr.go | 2 +- internal/announce/announce.go | 2 +- internal/database/feed.go | 9 +- internal/database/indexer.go | 45 +++--- internal/database/postgres_migrate.go | 25 ++-- internal/database/sqlite_migrate.go | 25 ++-- internal/domain/indexer.go | 59 ++++---- internal/domain/indexer_test.go | 12 +- internal/domain/macros.go | 146 ++++++++++---------- internal/domain/macros_test.go | 28 ++-- internal/feed/newznab.go | 2 +- internal/feed/rss.go | 2 +- internal/feed/rss_test.go | 36 ++--- internal/feed/torznab.go | 2 +- internal/indexer/indexer_test.go | 14 +- internal/indexer/service.go | 2 + internal/release/service.go | 2 +- web/src/forms/settings/IndexerForms.tsx | 17 +++ web/src/screens/dashboard/ActivityTable.tsx | 2 + web/src/screens/releases/ReleaseTable.tsx | 1 + web/src/types/Indexer.d.ts | 3 + 26 files changed, 254 insertions(+), 197 deletions(-) diff --git a/internal/action/exec_test.go b/internal/action/exec_test.go index 930f820..994c6cf 100644 --- a/internal/action/exec_test.go +++ b/internal/action/exec_test.go @@ -82,9 +82,10 @@ func Test_service_execCmd(t *testing.T) { TorrentName: "This is a test", TorrentTmpFile: "tmp-10000", Indexer: domain.IndexerMinimal{ - ID: 0, - Name: "Mock Indexer", - Identifier: "mock", + ID: 0, + Name: "Mock Indexer", + Identifier: "mock", + IdentifierExternal: "Mock Indexer", }, }, action: &domain.Action{ diff --git a/internal/action/lidarr.go b/internal/action/lidarr.go index c99a94b..cb2455d 100644 --- a/internal/action/lidarr.go +++ b/internal/action/lidarr.go @@ -59,7 +59,7 @@ func (s *service) lidarr(ctx context.Context, action *domain.Action, release dom DownloadUrl: release.DownloadURL, MagnetUrl: release.MagnetURI, Size: int64(release.Size), - Indexer: release.Indexer.Identifier, + Indexer: release.Indexer.IdentifierExternal, DownloadClientId: externalClientId, DownloadClient: externalClient, DownloadProtocol: string(release.Protocol), diff --git a/internal/action/radarr.go b/internal/action/radarr.go index 1a83f0d..9220fd2 100644 --- a/internal/action/radarr.go +++ b/internal/action/radarr.go @@ -58,7 +58,7 @@ func (s *service) radarr(ctx context.Context, action *domain.Action, release dom DownloadUrl: release.DownloadURL, MagnetUrl: release.MagnetURI, Size: int64(release.Size), - Indexer: release.Indexer.Identifier, + Indexer: release.Indexer.IdentifierExternal, DownloadClientId: externalClientId, DownloadClient: externalClient, DownloadProtocol: string(release.Protocol), diff --git a/internal/action/readarr.go b/internal/action/readarr.go index 04f978e..f0d1c4e 100644 --- a/internal/action/readarr.go +++ b/internal/action/readarr.go @@ -58,7 +58,7 @@ func (s *service) readarr(ctx context.Context, action *domain.Action, release do DownloadUrl: release.DownloadURL, MagnetUrl: release.MagnetURI, Size: int64(release.Size), - Indexer: release.Indexer.Identifier, + Indexer: release.Indexer.IdentifierExternal, DownloadClientId: externalClientId, DownloadClient: externalClient, DownloadProtocol: string(release.Protocol), diff --git a/internal/action/sonarr.go b/internal/action/sonarr.go index d644818..e6b7f1c 100644 --- a/internal/action/sonarr.go +++ b/internal/action/sonarr.go @@ -58,7 +58,7 @@ func (s *service) sonarr(ctx context.Context, action *domain.Action, release dom DownloadUrl: release.DownloadURL, MagnetUrl: release.MagnetURI, Size: int64(release.Size), - Indexer: release.Indexer.Identifier, + Indexer: release.Indexer.IdentifierExternal, DownloadClientId: externalClientId, DownloadClient: externalClient, DownloadProtocol: string(release.Protocol), diff --git a/internal/action/whisparr.go b/internal/action/whisparr.go index 51a7ed7..b98c392 100644 --- a/internal/action/whisparr.go +++ b/internal/action/whisparr.go @@ -58,7 +58,7 @@ func (s *service) whisparr(ctx context.Context, action *domain.Action, release d DownloadUrl: release.DownloadURL, MagnetUrl: release.MagnetURI, Size: int64(release.Size), - Indexer: release.Indexer.Identifier, + Indexer: release.Indexer.IdentifierExternal, DownloadClientId: externalClientId, DownloadClient: externalClient, DownloadProtocol: string(release.Protocol), diff --git a/internal/announce/announce.go b/internal/announce/announce.go index c6fc357..99bcdfa 100644 --- a/internal/announce/announce.go +++ b/internal/announce/announce.go @@ -103,7 +103,7 @@ func (a *announceProcessor) processQueue(queue chan string) { continue } - rls := domain.NewRelease(domain.IndexerMinimal{ID: a.indexer.ID, Name: a.indexer.Name, Identifier: a.indexer.Identifier}) + rls := domain.NewRelease(domain.IndexerMinimal{ID: a.indexer.ID, Name: a.indexer.Name, Identifier: a.indexer.Identifier, IdentifierExternal: a.indexer.IdentifierExternal}) rls.Protocol = domain.ReleaseProtocol(a.indexer.Protocol) // on lines matched diff --git a/internal/database/feed.go b/internal/database/feed.go index 2a80db7..3a938d7 100644 --- a/internal/database/feed.go +++ b/internal/database/feed.go @@ -34,6 +34,7 @@ func (r *FeedRepo) FindByID(ctx context.Context, id int) (*domain.Feed, error) { "f.id", "i.id", "i.identifier", + "i.identifier_external", "i.name", "f.name", "f.type", @@ -66,7 +67,7 @@ func (r *FeedRepo) FindByID(ctx context.Context, id int) (*domain.Feed, error) { var apiKey, cookie, settings sql.NullString - if err := row.Scan(&f.ID, &f.Indexer.ID, &f.Indexer.Identifier, &f.Indexer.Name, &f.Name, &f.Type, &f.Enabled, &f.URL, &f.Interval, &f.Timeout, &f.MaxAge, &apiKey, &cookie, &settings, &f.CreatedAt, &f.UpdatedAt); err != nil { + if err := row.Scan(&f.ID, &f.Indexer.ID, &f.Indexer.Identifier, &f.Indexer.IdentifierExternal, &f.Indexer.Name, &f.Name, &f.Type, &f.Enabled, &f.URL, &f.Interval, &f.Timeout, &f.MaxAge, &apiKey, &cookie, &settings, &f.CreatedAt, &f.UpdatedAt); err != nil { return nil, errors.Wrap(err, "error scanning row") } @@ -91,6 +92,7 @@ func (r *FeedRepo) FindByIndexerIdentifier(ctx context.Context, indexer string) "f.id", "i.id", "i.identifier", + "i.identifier_external", "i.name", "f.name", "f.type", @@ -123,7 +125,7 @@ func (r *FeedRepo) FindByIndexerIdentifier(ctx context.Context, indexer string) var apiKey, cookie, settings sql.NullString - if err := row.Scan(&f.ID, &f.Indexer.ID, &f.Indexer.Identifier, &f.Indexer.Name, &f.Name, &f.Type, &f.Enabled, &f.URL, &f.Interval, &f.Timeout, &f.MaxAge, &apiKey, &cookie, &settings, &f.CreatedAt, &f.UpdatedAt); err != nil { + if err := row.Scan(&f.ID, &f.Indexer.ID, &f.Indexer.Identifier, &f.Indexer.IdentifierExternal, &f.Indexer.Name, &f.Name, &f.Type, &f.Enabled, &f.URL, &f.Interval, &f.Timeout, &f.MaxAge, &apiKey, &cookie, &settings, &f.CreatedAt, &f.UpdatedAt); err != nil { return nil, errors.Wrap(err, "error scanning row") } @@ -146,6 +148,7 @@ func (r *FeedRepo) Find(ctx context.Context) ([]domain.Feed, error) { "f.id", "i.id", "i.identifier", + "i.identifier_external", "i.name", "f.name", "f.type", @@ -185,7 +188,7 @@ func (r *FeedRepo) Find(ctx context.Context) ([]domain.Feed, error) { var apiKey, cookie, lastRunData, settings sql.NullString var lastRun sql.NullTime - if err := rows.Scan(&f.ID, &f.Indexer.ID, &f.Indexer.Identifier, &f.Indexer.Name, &f.Name, &f.Type, &f.Enabled, &f.URL, &f.Interval, &f.Timeout, &f.MaxAge, &apiKey, &cookie, &lastRun, &lastRunData, &settings, &f.CreatedAt, &f.UpdatedAt); err != nil { + if err := rows.Scan(&f.ID, &f.Indexer.ID, &f.Indexer.Identifier, &f.Indexer.IdentifierExternal, &f.Indexer.Name, &f.Name, &f.Type, &f.Enabled, &f.URL, &f.Interval, &f.Timeout, &f.MaxAge, &apiKey, &cookie, &lastRun, &lastRunData, &settings, &f.CreatedAt, &f.UpdatedAt); err != nil { return nil, errors.Wrap(err, "error scanning row") } diff --git a/internal/database/indexer.go b/internal/database/indexer.go index c02e4bd..6cc34ed 100644 --- a/internal/database/indexer.go +++ b/internal/database/indexer.go @@ -36,19 +36,16 @@ func (r *IndexerRepo) Store(ctx context.Context, indexer domain.Indexer) (*domai } queryBuilder := r.db.squirrel. - Insert("indexer").Columns("enabled", "name", "identifier", "implementation", "base_url", "settings"). - Values(indexer.Enabled, indexer.Name, indexer.Identifier, indexer.Implementation, indexer.BaseURL, settings). + Insert("indexer").Columns("enabled", "name", "identifier", "identifier_external", "implementation", "base_url", "settings"). + Values(indexer.Enabled, indexer.Name, indexer.Identifier, indexer.IdentifierExternal, indexer.Implementation, indexer.BaseURL, settings). Suffix("RETURNING id").RunWith(r.db.handler) // return values - var retID int64 - - if err = queryBuilder.QueryRowContext(ctx).Scan(&retID); err != nil { + err = queryBuilder.QueryRowContext(ctx).Scan(&indexer.ID) + if err != nil { return nil, errors.Wrap(err, "error executing query") } - indexer.ID = retID - return &indexer, nil } @@ -62,6 +59,7 @@ func (r *IndexerRepo) Update(ctx context.Context, indexer domain.Indexer) (*doma Update("indexer"). Set("enabled", indexer.Enabled). Set("name", indexer.Name). + Set("identifier_external", indexer.IdentifierExternal). Set("base_url", indexer.BaseURL). Set("settings", settings). Set("updated_at", time.Now().Format(time.RFC3339)). @@ -81,7 +79,7 @@ func (r *IndexerRepo) Update(ctx context.Context, indexer domain.Indexer) (*doma func (r *IndexerRepo) List(ctx context.Context) ([]domain.Indexer, error) { queryBuilder := r.db.squirrel. - Select("id", "enabled", "name", "identifier", "implementation", "base_url", "settings"). + Select("id", "enabled", "name", "identifier", "identifier_external", "implementation", "base_url", "settings"). From("indexer"). OrderBy("name ASC") @@ -102,16 +100,17 @@ func (r *IndexerRepo) List(ctx context.Context) ([]domain.Indexer, error) { for rows.Next() { var f domain.Indexer - var implementation, baseURL sql.NullString + var identifierExternal, implementation, baseURL sql.Null[string] var settings string var settingsMap map[string]string - if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.Identifier, &implementation, &baseURL, &settings); err != nil { + if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.Identifier, &identifierExternal, &implementation, &baseURL, &settings); err != nil { return nil, errors.Wrap(err, "error scanning row") } - f.Implementation = implementation.String - f.BaseURL = baseURL.String + f.IdentifierExternal = identifierExternal.V + f.Implementation = implementation.V + f.BaseURL = baseURL.V if err = json.Unmarshal([]byte(settings), &settingsMap); err != nil { return nil, errors.Wrap(err, "error unmarshal settings") @@ -130,7 +129,7 @@ func (r *IndexerRepo) List(ctx context.Context) ([]domain.Indexer, error) { func (r *IndexerRepo) FindByID(ctx context.Context, id int) (*domain.Indexer, error) { queryBuilder := r.db.squirrel. - Select("id", "enabled", "name", "identifier", "implementation", "base_url", "settings"). + Select("id", "enabled", "name", "identifier", "identifier_external", "implementation", "base_url", "settings"). From("indexer"). Where(sq.Eq{"id": id}) @@ -146,17 +145,18 @@ func (r *IndexerRepo) FindByID(ctx context.Context, id int) (*domain.Indexer, er var i domain.Indexer - var implementation, baseURL, settings sql.NullString + var identifierExternal, implementation, baseURL, settings sql.Null[string] - if err := row.Scan(&i.ID, &i.Enabled, &i.Name, &i.Identifier, &implementation, &baseURL, &settings); err != nil { + if err := row.Scan(&i.ID, &i.Enabled, &i.Name, &i.Identifier, &identifierExternal, &implementation, &baseURL, &settings); err != nil { return nil, errors.Wrap(err, "error scanning row") } - i.Implementation = implementation.String - i.BaseURL = baseURL.String + i.IdentifierExternal = identifierExternal.V + i.Implementation = implementation.V + i.BaseURL = baseURL.V var settingsMap map[string]string - if err = json.Unmarshal([]byte(settings.String), &settingsMap); err != nil { + if err = json.Unmarshal([]byte(settings.V), &settingsMap); err != nil { return nil, errors.Wrap(err, "error unmarshal settings") } @@ -167,7 +167,7 @@ func (r *IndexerRepo) FindByID(ctx context.Context, id int) (*domain.Indexer, er func (r *IndexerRepo) FindByFilterID(ctx context.Context, id int) ([]domain.Indexer, error) { queryBuilder := r.db.squirrel. - Select("id", "enabled", "name", "identifier", "base_url", "settings"). + Select("id", "enabled", "name", "identifier", "identifier_external", "base_url", "settings"). From("indexer"). Join("filter_indexer ON indexer.id = filter_indexer.indexer_id"). Where(sq.Eq{"filter_indexer.filter_id": id}) @@ -190,9 +190,9 @@ func (r *IndexerRepo) FindByFilterID(ctx context.Context, id int) ([]domain.Inde var settings string var settingsMap map[string]string - var baseURL sql.NullString + var identifierExternal, baseURL sql.Null[string] - if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.Identifier, &baseURL, &settings); err != nil { + if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.Identifier, &identifierExternal, &baseURL, &settings); err != nil { return nil, errors.Wrap(err, "error scanning row") } @@ -200,7 +200,8 @@ func (r *IndexerRepo) FindByFilterID(ctx context.Context, id int) ([]domain.Inde return nil, errors.Wrap(err, "error unmarshal settings") } - f.BaseURL = baseURL.String + f.IdentifierExternal = identifierExternal.V + f.BaseURL = baseURL.V f.Settings = settingsMap indexers = append(indexers, f) diff --git a/internal/database/postgres_migrate.go b/internal/database/postgres_migrate.go index d6746c6..899e08b 100644 --- a/internal/database/postgres_migrate.go +++ b/internal/database/postgres_migrate.go @@ -16,15 +16,16 @@ CREATE TABLE users CREATE TABLE indexer ( - id SERIAL PRIMARY KEY, - identifier TEXT, - implementation TEXT, - base_url TEXT, - enabled BOOLEAN, - name TEXT NOT NULL, - settings TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + id SERIAL PRIMARY KEY, + identifier TEXT, + identifier_external TEXT, + implementation TEXT, + base_url TEXT, + enabled BOOLEAN, + name TEXT NOT NULL, + settings TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE (identifier) ); @@ -877,5 +878,11 @@ ALTER TABLE filter `, `ALTER TABLE action ADD COLUMN first_last_piece_prio BOOLEAN DEFAULT false; +`, + `ALTER TABLE indexer + ADD COLUMN identifier_external TEXT; + + UPDATE indexer + SET identifier_external = name; `, } diff --git a/internal/database/sqlite_migrate.go b/internal/database/sqlite_migrate.go index 79c0549..6cd8eb9 100644 --- a/internal/database/sqlite_migrate.go +++ b/internal/database/sqlite_migrate.go @@ -16,15 +16,16 @@ CREATE TABLE users CREATE TABLE indexer ( - id INTEGER PRIMARY KEY, - identifier TEXT, - implementation TEXT, - base_url TEXT, - enabled BOOLEAN, - name TEXT NOT NULL, - settings TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + id INTEGER PRIMARY KEY, + identifier TEXT, + identifier_external TEXT, + implementation TEXT, + base_url TEXT, + enabled BOOLEAN, + name TEXT NOT NULL, + settings TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE (identifier) ); @@ -1515,5 +1516,11 @@ ALTER TABLE filter `, `ALTER TABLE action ADD COLUMN first_last_piece_prio BOOLEAN DEFAULT false; +`, + `ALTER TABLE indexer + ADD COLUMN identifier_external TEXT; + + UPDATE indexer + SET identifier_external = name; `, } diff --git a/internal/domain/indexer.go b/internal/domain/indexer.go index 395ddd9..483e16b 100644 --- a/internal/domain/indexer.go +++ b/internal/domain/indexer.go @@ -26,40 +26,43 @@ type IndexerRepo interface { } type Indexer struct { - ID int64 `json:"id"` - Name string `json:"name"` - Identifier string `json:"identifier"` - Enabled bool `json:"enabled"` - Implementation string `json:"implementation"` - BaseURL string `json:"base_url,omitempty"` - Settings map[string]string `json:"settings,omitempty"` + ID int64 `json:"id"` + Name string `json:"name"` + Identifier string `json:"identifier"` + IdentifierExternal string `json:"identifier_external"` + Enabled bool `json:"enabled"` + Implementation string `json:"implementation"` + BaseURL string `json:"base_url,omitempty"` + Settings map[string]string `json:"settings,omitempty"` } type IndexerMinimal struct { - ID int `json:"id"` - Name string `json:"name"` - Identifier string `json:"identifier"` + ID int `json:"id"` + Name string `json:"name"` + Identifier string `json:"identifier"` + IdentifierExternal string `json:"identifier_external"` } type IndexerDefinition struct { - ID int `json:"id,omitempty"` - Name string `json:"name"` - Identifier string `json:"identifier"` - Implementation string `json:"implementation"` - BaseURL string `json:"base_url,omitempty"` - Enabled bool `json:"enabled"` - Description string `json:"description"` - Language string `json:"language"` - Privacy string `json:"privacy"` - Protocol string `json:"protocol"` - URLS []string `json:"urls"` - Supports []string `json:"supports"` - Settings []IndexerSetting `json:"settings,omitempty"` - SettingsMap map[string]string `json:"-"` - IRC *IndexerIRC `json:"irc,omitempty"` - Torznab *Torznab `json:"torznab,omitempty"` - Newznab *Newznab `json:"newznab,omitempty"` - RSS *FeedSettings `json:"rss,omitempty"` + ID int `json:"id,omitempty"` + Name string `json:"name"` + Identifier string `json:"identifier"` + IdentifierExternal string `json:"identifier_external"` + Implementation string `json:"implementation"` + BaseURL string `json:"base_url,omitempty"` + Enabled bool `json:"enabled"` + Description string `json:"description"` + Language string `json:"language"` + Privacy string `json:"privacy"` + Protocol string `json:"protocol"` + URLS []string `json:"urls"` + Supports []string `json:"supports"` + Settings []IndexerSetting `json:"settings,omitempty"` + SettingsMap map[string]string `json:"-"` + IRC *IndexerIRC `json:"irc,omitempty"` + Torznab *Torznab `json:"torznab,omitempty"` + Newznab *Newznab `json:"newznab,omitempty"` + RSS *FeedSettings `json:"rss,omitempty"` } type IndexerImplementation string diff --git a/internal/domain/indexer_test.go b/internal/domain/indexer_test.go index 4ad5883..3636f55 100644 --- a/internal/domain/indexer_test.go +++ b/internal/domain/indexer_test.go @@ -254,7 +254,7 @@ func TestIRCParserGazelleGames_Parse(t *testing.T) { { name: "", args: args{ - rls: NewRelease(IndexerMinimal{0, "GazelleGames", "ggn"}), + rls: NewRelease(IndexerMinimal{0, "GazelleGames", "ggn", "GazelleGames"}), vars: map[string]string{ "torrentName": "Trouble.in.Paradise-GROUP in Trouble in Paradise", }, @@ -267,7 +267,7 @@ func TestIRCParserGazelleGames_Parse(t *testing.T) { { name: "", args: args{ - rls: NewRelease(IndexerMinimal{0, "GazelleGames", "ggn"}), + rls: NewRelease(IndexerMinimal{0, "GazelleGames", "ggn", "GazelleGames"}), vars: map[string]string{ "torrentName": "F.I.L.F. Game Walkthrough v.0.18 in F.I.L.F.", }, @@ -280,7 +280,7 @@ func TestIRCParserGazelleGames_Parse(t *testing.T) { { name: "", args: args{ - rls: NewRelease(IndexerMinimal{0, "GazelleGames", "ggn"}), + rls: NewRelease(IndexerMinimal{0, "GazelleGames", "ggn", "GazelleGames"}), vars: map[string]string{ "torrentName": "Ni no Kuni: Dominion of the Dark Djinn in Ni no Kuni: Dominion of the Dark Djinn", }, @@ -293,7 +293,7 @@ func TestIRCParserGazelleGames_Parse(t *testing.T) { { name: "", args: args{ - rls: NewRelease(IndexerMinimal{0, "GazelleGames", "ggn"}), + rls: NewRelease(IndexerMinimal{0, "GazelleGames", "ggn", "GazelleGames"}), vars: map[string]string{ "torrentName": "Year 2 Remastered by Insaneintherainmusic", "category": "OST", @@ -332,7 +332,7 @@ func TestIRCParserOrpheus_Parse(t *testing.T) { { name: "", args: args{ - rls: NewRelease(IndexerMinimal{0, "Orpheus", "ops"}), + rls: NewRelease(IndexerMinimal{0, "Orpheus", "ops", "Orpheus"}), vars: map[string]string{ "torrentName": "Busta Rhymes – BEACH BALL (feat. BIA) – [2023] [Single] WEB/FLAC/24bit Lossless", "title": "Busta Rhymes – BEACH BALL (feat. BIA)", @@ -348,7 +348,7 @@ func TestIRCParserOrpheus_Parse(t *testing.T) { { name: "", args: args{ - rls: NewRelease(IndexerMinimal{0, "Orpheus", "ops"}), + rls: NewRelease(IndexerMinimal{0, "Orpheus", "ops", "Orpheus"}), vars: map[string]string{ "torrentName": "Busta Rhymes – BEACH BALL (feat. BIA) – [2023] [Single] CD/FLAC/Lossless", "title": "Busta Rhymes – BEACH BALL (feat. BIA)", diff --git a/internal/domain/macros.go b/internal/domain/macros.go index 2885912..de294c0 100644 --- a/internal/domain/macros.go +++ b/internal/domain/macros.go @@ -16,84 +16,86 @@ import ( ) type Macro struct { - TorrentName string - TorrentPathName string - TorrentHash string - TorrentID string - TorrentUrl string - TorrentDataRawBytes []byte - MagnetURI string - Group string - GroupID string - DownloadUrl string - InfoUrl string - Indexer string - IndexerName string - IndexerIdentifier string - Title string - Type string - Category string - Categories []string - Resolution string - Source string - HDR string - FilterID int - FilterName string - Size uint64 - SizeString string - Season int - Episode int - Year int - CurrentYear int - CurrentMonth int - CurrentDay int - CurrentHour int - CurrentMinute int - CurrentSecond int - Tags string - Artists string + TorrentName string + TorrentPathName string + TorrentHash string + TorrentID string + TorrentUrl string + TorrentDataRawBytes []byte + MagnetURI string + Group string + GroupID string + DownloadUrl string + InfoUrl string + Indexer string + IndexerName string + IndexerIdentifier string + IndexerIdentifierExternal string + Title string + Type string + Category string + Categories []string + Resolution string + Source string + HDR string + FilterID int + FilterName string + Size uint64 + SizeString string + Season int + Episode int + Year int + CurrentYear int + CurrentMonth int + CurrentDay int + CurrentHour int + CurrentMinute int + CurrentSecond int + Tags string + Artists string } func NewMacro(release Release) Macro { currentTime := time.Now() ma := Macro{ - TorrentName: release.TorrentName, - TorrentUrl: release.DownloadURL, - TorrentPathName: release.TorrentTmpFile, - TorrentDataRawBytes: release.TorrentDataRawBytes, - TorrentHash: release.TorrentHash, - TorrentID: release.TorrentID, - MagnetURI: release.MagnetURI, - Group: release.Group, - GroupID: release.GroupID, - InfoUrl: release.InfoURL, - DownloadUrl: release.DownloadURL, - Indexer: release.Indexer.Identifier, - IndexerName: release.Indexer.Name, - IndexerIdentifier: release.Indexer.Identifier, - Title: release.Title, - Type: release.Type, - Category: release.Category, - Categories: release.Categories, - Resolution: release.Resolution, - Source: release.Source, - HDR: strings.Join(release.HDR, ", "), - FilterID: release.FilterID, - FilterName: release.FilterName, - Size: release.Size, - SizeString: humanize.Bytes(release.Size), - Season: release.Season, - Episode: release.Episode, - Year: release.Year, - CurrentYear: currentTime.Year(), - CurrentMonth: int(currentTime.Month()), - CurrentDay: currentTime.Day(), - CurrentHour: currentTime.Hour(), - CurrentMinute: currentTime.Minute(), - CurrentSecond: currentTime.Second(), - Tags: strings.Join(release.Tags, ", "), - Artists: release.Artists, + TorrentName: release.TorrentName, + TorrentUrl: release.DownloadURL, + TorrentPathName: release.TorrentTmpFile, + TorrentDataRawBytes: release.TorrentDataRawBytes, + TorrentHash: release.TorrentHash, + TorrentID: release.TorrentID, + MagnetURI: release.MagnetURI, + Group: release.Group, + GroupID: release.GroupID, + InfoUrl: release.InfoURL, + DownloadUrl: release.DownloadURL, + Indexer: release.Indexer.Identifier, + IndexerName: release.Indexer.Name, + IndexerIdentifier: release.Indexer.Identifier, + IndexerIdentifierExternal: release.Indexer.IdentifierExternal, + Title: release.Title, + Type: release.Type, + Category: release.Category, + Categories: release.Categories, + Resolution: release.Resolution, + Source: release.Source, + HDR: strings.Join(release.HDR, ", "), + FilterID: release.FilterID, + FilterName: release.FilterName, + Size: release.Size, + SizeString: humanize.Bytes(release.Size), + Season: release.Season, + Episode: release.Episode, + Year: release.Year, + CurrentYear: currentTime.Year(), + CurrentMonth: int(currentTime.Month()), + CurrentDay: currentTime.Day(), + CurrentHour: currentTime.Hour(), + CurrentMinute: currentTime.Minute(), + CurrentSecond: currentTime.Second(), + Tags: strings.Join(release.Tags, ", "), + Artists: release.Artists, } return ma diff --git a/internal/domain/macros_test.go b/internal/domain/macros_test.go index 07fb5e3..4b6ffb6 100644 --- a/internal/domain/macros_test.go +++ b/internal/domain/macros_test.go @@ -36,7 +36,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", TorrentTmpFile: "/tmp/a-temporary-file.torrent", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "Print mee {{.TorrentPathName}}"}, want: "Print mee /tmp/a-temporary-file.torrent", @@ -47,7 +47,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", TorrentTmpFile: "/tmp/a-temporary-file.torrent", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "Print mee {{TorrentPathName}}"}, want: "", @@ -58,7 +58,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", TorrentTmpFile: "/tmp/a-temporary-file.torrent", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "add {{.TorrentPathName}} --category test"}, want: "add /tmp/a-temporary-file.torrent --category test", @@ -68,7 +68,7 @@ func TestMacros_Parse(t *testing.T) { name: "test_program_arg_bad", release: Release{ TorrentTmpFile: "/tmp/a-temporary-file.torrent", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "add {{.TorrenttPathName}} --category test"}, want: "", @@ -79,7 +79,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", TorrentTmpFile: "/tmp/a-temporary-file.torrent", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "add {{.TorrentPathName}} --category test --other {{.TorrentName}}"}, want: "add /tmp/a-temporary-file.torrent --category test --other This movie 2021", @@ -90,7 +90,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", DownloadURL: "https://some.site/download/fakeid", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "{{.TorrentName}} {{.TorrentUrl}} SOME_LONG_TOKEN"}, want: "This movie 2021 https://some.site/download/fakeid SOME_LONG_TOKEN", @@ -101,7 +101,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", DownloadURL: "https://some.site/download/fakeid", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "{{.Indexer}} {{.TorrentName}} {{.TorrentUrl}} SOME_LONG_TOKEN"}, want: "mock1 This movie 2021 https://some.site/download/fakeid SOME_LONG_TOKEN", @@ -112,7 +112,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", DownloadURL: "https://some.site/download/fakeid", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "{{.Indexer}}-race"}, want: "mock1-race", @@ -123,7 +123,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", DownloadURL: "https://some.site/download/fakeid", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "{{.Indexer}}-{{.CurrentYear}}-race"}, want: fmt.Sprintf("mock1-%v-race", currentTime.Year()), @@ -134,7 +134,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", DownloadURL: "https://some.site/download/fakeid", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, Resolution: "2160p", HDR: []string{"DV"}, }, @@ -147,7 +147,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", DownloadURL: "https://some.site/download/fakeid", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, Resolution: "2160p", HDR: []string{"HDR"}, }, @@ -160,7 +160,7 @@ func TestMacros_Parse(t *testing.T) { release: Release{ TorrentName: "This movie 2021", DownloadURL: "https://some.site/download/fakeid", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, Resolution: "2160p", HDR: []string{"HDR"}, Year: 2021, @@ -220,7 +220,7 @@ func TestMacros_Parse(t *testing.T) { TorrentName: "This movie 2021", DownloadURL: "https://some.site/download/fakeid", Group: "thisgrp", - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, Year: 2021, }, args: args{text: "movies-{{.Group}}"}, @@ -266,7 +266,7 @@ func TestMacros_Parse(t *testing.T) { { name: "test_args_indexer", release: Release{ - Indexer: IndexerMinimal{0, "Mock Indexer", "mock1"}, + Indexer: IndexerMinimal{0, "Mock Indexer", "mock1", "Mock Indexer"}, }, args: args{text: "indexer={{.IndexerName}}"}, want: fmt.Sprintf("indexer=Mock Indexer"), diff --git a/internal/feed/newznab.go b/internal/feed/newznab.go index 7e16137..67b390f 100644 --- a/internal/feed/newznab.go +++ b/internal/feed/newznab.go @@ -95,7 +95,7 @@ func (j *NewznabJob) process(ctx context.Context) error { } } - rls := domain.NewRelease(domain.IndexerMinimal{ID: j.Feed.Indexer.ID, Name: j.Feed.Indexer.Name, Identifier: j.Feed.Indexer.Identifier}) + rls := domain.NewRelease(domain.IndexerMinimal{ID: j.Feed.Indexer.ID, Name: j.Feed.Indexer.Name, Identifier: j.Feed.Indexer.Identifier, IdentifierExternal: j.Feed.Indexer.IdentifierExternal}) rls.Implementation = domain.ReleaseImplementationNewznab rls.Protocol = domain.ReleaseProtocolNzb diff --git a/internal/feed/rss.go b/internal/feed/rss.go index ce806a4..000f588 100644 --- a/internal/feed/rss.go +++ b/internal/feed/rss.go @@ -119,7 +119,7 @@ func (j *RSSJob) processItem(item *gofeed.Item) *domain.Release { } } - rls := domain.NewRelease(domain.IndexerMinimal{ID: j.Feed.Indexer.ID, Name: j.Feed.Indexer.Name, Identifier: j.Feed.Indexer.Identifier}) + rls := domain.NewRelease(domain.IndexerMinimal{ID: j.Feed.Indexer.ID, Name: j.Feed.Indexer.Name, Identifier: j.Feed.Indexer.Identifier, IdentifierExternal: j.Feed.Indexer.IdentifierExternal}) rls.Implementation = domain.ReleaseImplementationRSS rls.ParseString(item.Title) diff --git a/internal/feed/rss_test.go b/internal/feed/rss_test.go index 3f5ef30..208665f 100644 --- a/internal/feed/rss_test.go +++ b/internal/feed/rss_test.go @@ -46,9 +46,10 @@ func TestRSSJob_processItem(t *testing.T) { Feed: &domain.Feed{ MaxAge: 3600, Indexer: domain.IndexerMinimal{ - ID: 0, - Name: "Mock Feed", - Identifier: "mock-feed", + ID: 0, + Name: "Mock Feed", + Identifier: "mock-feed", + IdentifierExternal: "Mock Indexer", }, }, Name: "test feed", @@ -71,7 +72,7 @@ func TestRSSJob_processItem(t *testing.T) { Link: "/details.php?id=00000&hit=1", GUID: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", }}, - want: &domain.Release{ID: 0, FilterStatus: "PENDING", Rejections: []string{}, Indexer: domain.IndexerMinimal{0, "Mock Feed", "mock-feed"}, FilterName: "", Protocol: "torrent", Implementation: "RSS", Timestamp: now, GroupID: "", TorrentID: "", DownloadURL: "https://fake-feed.com/details.php?id=00000&hit=1", TorrentTmpFile: "", TorrentDataRawBytes: []uint8(nil), TorrentHash: "", TorrentName: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", Size: 1490000000, Title: "Some Release Title", Description: "Category: Example\n Size: 1.49 GB\n Status: 27 seeders and 1 leechers\n Speed: 772.16 kB/s\n Added: 2022-09-29 16:06:08\n", Category: "", Season: 0, Episode: 0, Year: 2022, Resolution: "720p", Source: "WEB", Codec: []string{"H.264"}, Container: "", HDR: []string(nil), Audio: []string(nil), AudioChannels: "", Group: "GROUP", Region: "", Language: nil, Proper: false, Repack: false, Website: "", Artists: "", Type: "episode", LogScore: 0, Origin: "", Tags: []string{}, ReleaseTags: "", Freeleech: false, FreeleechPercent: 0, Bonus: []string(nil), Uploader: "", PreTime: "", Other: []string(nil), RawCookie: "", AdditionalSizeCheckRequired: false, FilterID: 0, Filter: (*domain.Filter)(nil), ActionStatus: []domain.ReleaseActionStatus(nil)}, + want: &domain.Release{ID: 0, FilterStatus: "PENDING", Rejections: []string{}, Indexer: domain.IndexerMinimal{0, "Mock Feed", "mock-feed", "Mock Indexer"}, FilterName: "", Protocol: "torrent", Implementation: "RSS", Timestamp: now, GroupID: "", TorrentID: "", DownloadURL: "https://fake-feed.com/details.php?id=00000&hit=1", TorrentTmpFile: "", TorrentDataRawBytes: []uint8(nil), TorrentHash: "", TorrentName: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", Size: 1490000000, Title: "Some Release Title", Description: "Category: Example\n Size: 1.49 GB\n Status: 27 seeders and 1 leechers\n Speed: 772.16 kB/s\n Added: 2022-09-29 16:06:08\n", Category: "", Season: 0, Episode: 0, Year: 2022, Resolution: "720p", Source: "WEB", Codec: []string{"H.264"}, Container: "", HDR: []string(nil), Audio: []string(nil), AudioChannels: "", Group: "GROUP", Region: "", Language: nil, Proper: false, Repack: false, Website: "", Artists: "", Type: "episode", LogScore: 0, Origin: "", Tags: []string{}, ReleaseTags: "", Freeleech: false, FreeleechPercent: 0, Bonus: []string(nil), Uploader: "", PreTime: "", Other: []string(nil), RawCookie: "", AdditionalSizeCheckRequired: false, FilterID: 0, Filter: (*domain.Filter)(nil), ActionStatus: []domain.ReleaseActionStatus(nil)}, }, { name: "with_baseurl", @@ -79,9 +80,10 @@ func TestRSSJob_processItem(t *testing.T) { Feed: &domain.Feed{ MaxAge: 3600, Indexer: domain.IndexerMinimal{ - ID: 0, - Name: "Mock Feed", - Identifier: "mock-feed", + ID: 0, + Name: "Mock Feed", + Identifier: "mock-feed", + IdentifierExternal: "Mock Indexer", }, }, Name: "test feed", @@ -104,7 +106,7 @@ func TestRSSJob_processItem(t *testing.T) { Link: "https://fake-feed.com/details.php?id=00000&hit=1", GUID: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", }}, - want: &domain.Release{ID: 0, FilterStatus: "PENDING", Rejections: []string{}, Indexer: domain.IndexerMinimal{0, "Mock Feed", "mock-feed"}, FilterName: "", Protocol: "torrent", Implementation: "RSS", Timestamp: now, GroupID: "", TorrentID: "", DownloadURL: "https://fake-feed.com/details.php?id=00000&hit=1", TorrentTmpFile: "", TorrentDataRawBytes: []uint8(nil), TorrentHash: "", TorrentName: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", Size: 1490000000, Title: "Some Release Title", Description: "Category: Example\n Size: 1.49 GB\n Status: 27 seeders and 1 leechers\n Speed: 772.16 kB/s\n Added: 2022-09-29 16:06:08\n", Category: "", Season: 0, Episode: 0, Year: 2022, Resolution: "720p", Source: "WEB", Codec: []string{"H.264"}, Container: "", HDR: []string(nil), Audio: []string(nil), AudioChannels: "", Group: "GROUP", Region: "", Language: nil, Proper: false, Repack: false, Website: "", Artists: "", Type: "episode", LogScore: 0, Origin: "", Tags: []string{}, ReleaseTags: "", Freeleech: false, FreeleechPercent: 0, Bonus: []string(nil), Uploader: "", PreTime: "", Other: []string(nil), RawCookie: "", AdditionalSizeCheckRequired: false, FilterID: 0, Filter: (*domain.Filter)(nil), ActionStatus: []domain.ReleaseActionStatus(nil)}, + want: &domain.Release{ID: 0, FilterStatus: "PENDING", Rejections: []string{}, Indexer: domain.IndexerMinimal{0, "Mock Feed", "mock-feed", "Mock Indexer"}, FilterName: "", Protocol: "torrent", Implementation: "RSS", Timestamp: now, GroupID: "", TorrentID: "", DownloadURL: "https://fake-feed.com/details.php?id=00000&hit=1", TorrentTmpFile: "", TorrentDataRawBytes: []uint8(nil), TorrentHash: "", TorrentName: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", Size: 1490000000, Title: "Some Release Title", Description: "Category: Example\n Size: 1.49 GB\n Status: 27 seeders and 1 leechers\n Speed: 772.16 kB/s\n Added: 2022-09-29 16:06:08\n", Category: "", Season: 0, Episode: 0, Year: 2022, Resolution: "720p", Source: "WEB", Codec: []string{"H.264"}, Container: "", HDR: []string(nil), Audio: []string(nil), AudioChannels: "", Group: "GROUP", Region: "", Language: nil, Proper: false, Repack: false, Website: "", Artists: "", Type: "episode", LogScore: 0, Origin: "", Tags: []string{}, ReleaseTags: "", Freeleech: false, FreeleechPercent: 0, Bonus: []string(nil), Uploader: "", PreTime: "", Other: []string(nil), RawCookie: "", AdditionalSizeCheckRequired: false, FilterID: 0, Filter: (*domain.Filter)(nil), ActionStatus: []domain.ReleaseActionStatus(nil)}, }, { name: "time_parse", @@ -112,9 +114,10 @@ func TestRSSJob_processItem(t *testing.T) { Feed: &domain.Feed{ MaxAge: 360, Indexer: domain.IndexerMinimal{ - ID: 0, - Name: "Mock Feed", - Identifier: "mock-feed", + ID: 0, + Name: "Mock Feed", + Identifier: "mock-feed", + IdentifierExternal: "Mock Indexer", }, }, Name: "test feed", @@ -138,7 +141,7 @@ func TestRSSJob_processItem(t *testing.T) { GUID: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", //PublishedParsed: &nowMinusTime, }}, - want: &domain.Release{ID: 0, FilterStatus: "PENDING", Rejections: []string{}, Indexer: domain.IndexerMinimal{0, "Mock Feed", "mock-feed"}, FilterName: "", Protocol: "torrent", Implementation: "RSS", Timestamp: now, GroupID: "", TorrentID: "", DownloadURL: "https://fake-feed.com/details.php?id=00000&hit=1", TorrentTmpFile: "", TorrentDataRawBytes: []uint8(nil), TorrentHash: "", TorrentName: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", Size: 1490000000, Title: "Some Release Title", Description: "Category: Example\n Size: 1.49 GB\n Status: 27 seeders and 1 leechers\n Speed: 772.16 kB/s\n Added: 2022-09-29 16:06:08\n", Category: "", Season: 0, Episode: 0, Year: 2022, Resolution: "720p", Source: "WEB", Codec: []string{"H.264"}, Container: "", HDR: []string(nil), Audio: []string(nil), AudioChannels: "", Group: "GROUP", Region: "", Language: nil, Proper: false, Repack: false, Website: "", Artists: "", Type: "episode", LogScore: 0, Origin: "", Tags: []string{}, ReleaseTags: "", Freeleech: false, FreeleechPercent: 0, Bonus: []string(nil), Uploader: "", PreTime: "", Other: []string(nil), RawCookie: "", AdditionalSizeCheckRequired: false, FilterID: 0, Filter: (*domain.Filter)(nil), ActionStatus: []domain.ReleaseActionStatus(nil)}, + want: &domain.Release{ID: 0, FilterStatus: "PENDING", Rejections: []string{}, Indexer: domain.IndexerMinimal{0, "Mock Feed", "mock-feed", "Mock Indexer"}, FilterName: "", Protocol: "torrent", Implementation: "RSS", Timestamp: now, GroupID: "", TorrentID: "", DownloadURL: "https://fake-feed.com/details.php?id=00000&hit=1", TorrentTmpFile: "", TorrentDataRawBytes: []uint8(nil), TorrentHash: "", TorrentName: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", Size: 1490000000, Title: "Some Release Title", Description: "Category: Example\n Size: 1.49 GB\n Status: 27 seeders and 1 leechers\n Speed: 772.16 kB/s\n Added: 2022-09-29 16:06:08\n", Category: "", Season: 0, Episode: 0, Year: 2022, Resolution: "720p", Source: "WEB", Codec: []string{"H.264"}, Container: "", HDR: []string(nil), Audio: []string(nil), AudioChannels: "", Group: "GROUP", Region: "", Language: nil, Proper: false, Repack: false, Website: "", Artists: "", Type: "episode", LogScore: 0, Origin: "", Tags: []string{}, ReleaseTags: "", Freeleech: false, FreeleechPercent: 0, Bonus: []string(nil), Uploader: "", PreTime: "", Other: []string(nil), RawCookie: "", AdditionalSizeCheckRequired: false, FilterID: 0, Filter: (*domain.Filter)(nil), ActionStatus: []domain.ReleaseActionStatus(nil)}, }, { name: "time_parse", @@ -175,9 +178,10 @@ func TestRSSJob_processItem(t *testing.T) { Feed: &domain.Feed{ MaxAge: 3600, Indexer: domain.IndexerMinimal{ - ID: 0, - Name: "Mock Feed", - Identifier: "mock-feed", + ID: 0, + Name: "Mock Feed", + Identifier: "mock-feed", + IdentifierExternal: "Mock Indexer", }, Settings: &domain.FeedSettingsJSON{DownloadType: domain.FeedDownloadTypeMagnet}, }, @@ -203,7 +207,7 @@ func TestRSSJob_processItem(t *testing.T) { }, }, }}, - want: &domain.Release{ID: 0, FilterStatus: "PENDING", Rejections: []string{}, Indexer: domain.IndexerMinimal{0, "Mock Feed", "mock-feed"}, FilterName: "", Protocol: "torrent", Implementation: "RSS", Timestamp: now, MagnetURI: "magnet:?xt=this-not-a-valid-magnet", GroupID: "", TorrentID: "", DownloadURL: "https://fake-feed.com/details.php?id=00000&hit=1", TorrentTmpFile: "", TorrentDataRawBytes: []uint8(nil), TorrentHash: "", TorrentName: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", Size: 0, Title: "Some Release Title", Description: "Category: Example", Category: "", Season: 0, Episode: 0, Year: 2022, Resolution: "720p", Source: "WEB", Codec: []string{"H.264"}, Container: "", HDR: []string(nil), Audio: []string(nil), AudioChannels: "", Group: "GROUP", Region: "", Language: nil, Proper: false, Repack: false, Website: "", Artists: "", Type: "episode", LogScore: 0, Origin: "", Tags: []string{}, ReleaseTags: "", Freeleech: false, FreeleechPercent: 0, Bonus: []string(nil), Uploader: "", PreTime: "", Other: []string(nil), RawCookie: "", AdditionalSizeCheckRequired: false, FilterID: 0, Filter: (*domain.Filter)(nil), ActionStatus: []domain.ReleaseActionStatus(nil)}, + want: &domain.Release{ID: 0, FilterStatus: "PENDING", Rejections: []string{}, Indexer: domain.IndexerMinimal{0, "Mock Feed", "mock-feed", "Mock Indexer"}, FilterName: "", Protocol: "torrent", Implementation: "RSS", Timestamp: now, MagnetURI: "magnet:?xt=this-not-a-valid-magnet", GroupID: "", TorrentID: "", DownloadURL: "https://fake-feed.com/details.php?id=00000&hit=1", TorrentTmpFile: "", TorrentDataRawBytes: []uint8(nil), TorrentHash: "", TorrentName: "Some.Release.Title.2022.09.22.720p.WEB.h264-GROUP", Size: 0, Title: "Some Release Title", Description: "Category: Example", Category: "", Season: 0, Episode: 0, Year: 2022, Resolution: "720p", Source: "WEB", Codec: []string{"H.264"}, Container: "", HDR: []string(nil), Audio: []string(nil), AudioChannels: "", Group: "GROUP", Region: "", Language: nil, Proper: false, Repack: false, Website: "", Artists: "", Type: "episode", LogScore: 0, Origin: "", Tags: []string{}, ReleaseTags: "", Freeleech: false, FreeleechPercent: 0, Bonus: []string(nil), Uploader: "", PreTime: "", Other: []string(nil), RawCookie: "", AdditionalSizeCheckRequired: false, FilterID: 0, Filter: (*domain.Filter)(nil), ActionStatus: []domain.ReleaseActionStatus(nil)}, }, } for _, tt := range tests { diff --git a/internal/feed/torznab.go b/internal/feed/torznab.go index 0bbcd52..ce717e5 100644 --- a/internal/feed/torznab.go +++ b/internal/feed/torznab.go @@ -101,7 +101,7 @@ func (j *TorznabJob) process(ctx context.Context) error { } } - rls := domain.NewRelease(domain.IndexerMinimal{ID: j.Feed.Indexer.ID, Name: j.Feed.Indexer.Name, Identifier: j.Feed.Indexer.Identifier}) + rls := domain.NewRelease(domain.IndexerMinimal{ID: j.Feed.Indexer.ID, Name: j.Feed.Indexer.Name, Identifier: j.Feed.Indexer.Identifier, IdentifierExternal: j.Feed.Indexer.IdentifierExternal}) rls.Implementation = domain.ReleaseImplementationTorznab rls.TorrentName = item.Title diff --git a/internal/indexer/indexer_test.go b/internal/indexer/indexer_test.go index 83fe987..9dff652 100644 --- a/internal/indexer/indexer_test.go +++ b/internal/indexer/indexer_test.go @@ -15,8 +15,9 @@ import ( func TestIndexersParseAndFilter(t *testing.T) { type fields struct { - identifier string - settings map[string]string + identifier string + identifierExternal string + settings map[string]string } type filterTest struct { filter *domain.Filter @@ -41,7 +42,8 @@ func TestIndexersParseAndFilter(t *testing.T) { { name: "ops", fields: fields{ - identifier: "orpheus", + identifier: "orpheus", + identifierExternal: "Orpheus", settings: map[string]string{ "torrent_pass": "pass", "api_key": "key", @@ -115,7 +117,8 @@ func TestIndexersParseAndFilter(t *testing.T) { { name: "redacted", fields: fields{ - identifier: "red", + identifier: "red", + identifierExternal: "Redacted", settings: map[string]string{ "authkey": "key", "torrent_pass": "pass", @@ -298,6 +301,7 @@ func TestIndexersParseAndFilter(t *testing.T) { i, err := OpenAndProcessDefinition("./definitions/" + tt.fields.identifier + ".yaml") assert.NoError(t, err) + i.IdentifierExternal = tt.fields.identifierExternal i.SettingsMap = tt.fields.settings ll := zerolog.New(io.Discard) @@ -327,7 +331,7 @@ func TestIndexersParseAndFilter(t *testing.T) { return } - rls := domain.NewRelease(domain.IndexerMinimal{ID: i.ID, Name: i.Name, Identifier: i.Identifier}) + rls := domain.NewRelease(domain.IndexerMinimal{ID: i.ID, Name: i.Name, Identifier: i.Identifier, IdentifierExternal: i.IdentifierExternal}) rls.Protocol = domain.ReleaseProtocol(i.Protocol) // on lines matched diff --git a/internal/indexer/service.go b/internal/indexer/service.go index 4c72dd0..fab6389 100644 --- a/internal/indexer/service.go +++ b/internal/indexer/service.go @@ -275,6 +275,7 @@ func (s *service) mapIndexer(indexer domain.Indexer) (*domain.IndexerDefinition, d.ID = int(indexer.ID) d.Name = indexer.Name d.Identifier = indexer.Identifier + d.IdentifierExternal = indexer.IdentifierExternal d.Implementation = indexer.Implementation d.BaseURL = indexer.BaseURL d.Enabled = indexer.Enabled @@ -311,6 +312,7 @@ func (s *service) updateMapIndexer(indexer domain.Indexer) (*domain.IndexerDefin d.ID = int(indexer.ID) d.Name = indexer.Name d.Identifier = indexer.Identifier + d.IdentifierExternal = indexer.IdentifierExternal d.Implementation = indexer.Implementation d.BaseURL = indexer.BaseURL d.Enabled = indexer.Enabled diff --git a/internal/release/service.go b/internal/release/service.go index 9f44f41..ceddbcc 100644 --- a/internal/release/service.go +++ b/internal/release/service.go @@ -101,7 +101,7 @@ func (s *service) ProcessManual(ctx context.Context, req *domain.ReleaseProcessR return err } - rls := domain.NewRelease(domain.IndexerMinimal{ID: def.ID, Name: def.Name, Identifier: def.Identifier}) + rls := domain.NewRelease(domain.IndexerMinimal{ID: def.ID, Name: def.Name, Identifier: def.Identifier, IdentifierExternal: def.IdentifierExternal}) switch req.IndexerImplementation { case string(domain.IndexerImplementationIRC): diff --git a/web/src/forms/settings/IndexerForms.tsx b/web/src/forms/settings/IndexerForms.tsx index 0fe9ecf..6d17d82 100644 --- a/web/src/forms/settings/IndexerForms.tsx +++ b/web/src/forms/settings/IndexerForms.tsx @@ -718,6 +718,7 @@ interface IndexerUpdateInitialValues { name: string; enabled: boolean; identifier: string; + identifier_external: string; implementation: string; base_url: string; settings: { @@ -812,6 +813,7 @@ export function IndexerUpdateForm({ isOpen, toggle, indexer }: UpdateProps) { name: indexer.name, enabled: indexer.enabled || false, identifier: indexer.identifier, + identifier_external: indexer.identifier_external, implementation: indexer.implementation, base_url: indexer.base_url, settings: indexer.settings?.reduce( @@ -856,6 +858,21 @@ export function IndexerUpdateForm({ isOpen, toggle, indexer }: UpdateProps) { )} + + +

External Identifier for use with ARRs to get features like seed limits working.

+
+

This needs to match the indexer name in your ARR. If using Prowlarr it will likely be "{indexer.name} (Prowlarr)"

+
+ + + } + /> {indexer.implementation == "irc" && ( diff --git a/web/src/screens/dashboard/ActivityTable.tsx b/web/src/screens/dashboard/ActivityTable.tsx index 3a61302..a445b79 100644 --- a/web/src/screens/dashboard/ActivityTable.tsx +++ b/web/src/screens/dashboard/ActivityTable.tsx @@ -243,6 +243,7 @@ export const ActivityTable = () => { id: 0, name: index % 2 === 0 ? "distrowatch" : "linuxtracker", identifier: index % 2 === 0 ? "distrowatch" : "linuxtracker", + identifier_external: index % 2 === 0 ? "distrowatch" : "linuxtracker", }, })); setModifiedData(newData); @@ -323,6 +324,7 @@ export const ActivityTableContent = () => { id: 0, name: index % 2 === 0 ? "distrowatch" : "linuxtracker", identifier: index % 2 === 0 ? "distrowatch" : "linuxtracker", + identifier_external: index % 2 === 0 ? "distrowatch" : "linuxtracker", }, })); setModifiedData(newData); diff --git a/web/src/screens/releases/ReleaseTable.tsx b/web/src/screens/releases/ReleaseTable.tsx index ab9865a..db482d3 100644 --- a/web/src/screens/releases/ReleaseTable.tsx +++ b/web/src/screens/releases/ReleaseTable.tsx @@ -152,6 +152,7 @@ export const ReleaseTable = () => { id: 0, name: index % 2 === 0 ? "distrowatch" : "linuxtracker", identifier: index % 2 === 0 ? "distrowatch" : "linuxtracker", + identifier_external: index % 2 === 0 ? "distrowatch" : "linuxtracker", }, category: "Linux ISOs", size: index % 2 === 0 ? 4566784529 : (index % 3 === 0 ? 7427019812 : 2312122455), diff --git a/web/src/types/Indexer.d.ts b/web/src/types/Indexer.d.ts index 1d3065e..1a06cb8 100644 --- a/web/src/types/Indexer.d.ts +++ b/web/src/types/Indexer.d.ts @@ -7,6 +7,7 @@ interface Indexer { id: number; name: string; identifier: string; + identifier_external: string; enabled: boolean; implementation: string; base_url: string; @@ -17,12 +18,14 @@ interface IndexerMinimal { id: number; name: string; identifier: string; + identifier_external: string; } interface IndexerDefinition { id: number; name: string; identifier: string; + identifier_external: string; implementation: string; base_url: string; enabled?: boolean;