Documentation
¶
Overview ¶
Package arrapi provides typed, resilient clients for the Sonarr and Radarr v3 HTTP APIs. It covers read access, connectivity checks, and the rescan/refresh commands.
Two constructors return two concrete client types, so an operation can only be called against the instance that supports it: NewSonarr returns a *Sonarr (GetSeries, GetEpisodes, RescanSeries, RefreshSeries) and NewRadarr returns a *Radarr (GetMovies, RescanMovie, RefreshMovie). Both embed a shared core that exposes the endpoints common to either service (GetTags, GetSystemStatus, Ping, Close).
Every request is authenticated with the instance's X-Api-Key, bounded by a per-request timeout, and retried on transient failures (HTTP 429, any 5xx, and transient transport errors) with jittered exponential backoff via github.com/cplieger/httpx/v2. Non-2xx responses surface as a *StatusError, which reports whether it was transient and lets callers detect a 404 with IsNotFound.
Response bodies are size-bounded before decoding to guard against oversized or malicious payloads. The clients own no goroutines and hold no locks; a single client is safe for concurrent use.
Index ¶
- func HasAnyTag(itemTags []int, ids map[int]struct{}) bool
- func IsNotFound(err error) bool
- func IsRateLimited(err error) bool
- func TagIDs(tags []Tag, labels ...string) map[int]struct{}
- func UnmatchedLabels(tags []Tag, labels ...string) []string
- type AlternateTitle
- type Command
- type Episode
- type EpisodeFile
- type EventType
- type HistoryOptions
- type HistoryPage
- type HistoryRecord
- type Language
- type MediaInfo
- type Movie
- type MovieFile
- type Option
- type QualityProfile
- type Radarr
- func (c Radarr) Close()
- func (c Radarr) GetCommandByID(ctx context.Context, id int) (Command, error)
- func (c Radarr) GetHistory(ctx context.Context, opts HistoryOptions) (HistoryPage, error)
- func (c Radarr) GetHistorySince(ctx context.Context, since time.Time, eventTypes ...EventType) ([]HistoryRecord, error)
- func (r *Radarr) GetMovieByID(ctx context.Context, movieID int) (Movie, error)
- func (r *Radarr) GetMovies(ctx context.Context) ([]Movie, error)
- func (c Radarr) GetQualityProfiles(ctx context.Context) ([]QualityProfile, error)
- func (c Radarr) GetRootFolders(ctx context.Context) ([]RootFolder, error)
- func (c Radarr) GetSystemStatus(ctx context.Context) (SystemStatus, error)
- func (c Radarr) GetTags(ctx context.Context) ([]Tag, error)
- func (c Radarr) Ping(ctx context.Context) error
- func (r *Radarr) RefreshMovie(ctx context.Context, movieID int) (Command, error)
- func (r *Radarr) RescanMovie(ctx context.Context, movieID int) (Command, error)
- func (c Radarr) ResolveTagIDs(ctx context.Context, labels ...string) (ids map[int]struct{}, unmatched []string, err error)
- type ResponseTooLargeError
- type RootFolder
- type Season
- type SeasonStatistics
- type Series
- type SeriesStatistics
- type Sonarr
- func (c Sonarr) Close()
- func (c Sonarr) GetCommandByID(ctx context.Context, id int) (Command, error)
- func (s *Sonarr) GetEpisodeByID(ctx context.Context, episodeID int) (Episode, error)
- func (s *Sonarr) GetEpisodes(ctx context.Context, seriesID int) ([]Episode, error)
- func (c Sonarr) GetHistory(ctx context.Context, opts HistoryOptions) (HistoryPage, error)
- func (c Sonarr) GetHistorySince(ctx context.Context, since time.Time, eventTypes ...EventType) ([]HistoryRecord, error)
- func (c Sonarr) GetQualityProfiles(ctx context.Context) ([]QualityProfile, error)
- func (c Sonarr) GetRootFolders(ctx context.Context) ([]RootFolder, error)
- func (s *Sonarr) GetSeries(ctx context.Context) ([]Series, error)
- func (s *Sonarr) GetSeriesByID(ctx context.Context, seriesID int) (Series, error)
- func (c Sonarr) GetSystemStatus(ctx context.Context) (SystemStatus, error)
- func (c Sonarr) GetTags(ctx context.Context) ([]Tag, error)
- func (c Sonarr) Ping(ctx context.Context) error
- func (s *Sonarr) RefreshSeries(ctx context.Context, seriesID int) (Command, error)
- func (s *Sonarr) RescanSeries(ctx context.Context, seriesID int) (Command, error)
- func (c Sonarr) ResolveTagIDs(ctx context.Context, labels ...string) (ids map[int]struct{}, unmatched []string, err error)
- type StatusError
- type SystemStatus
- type Tag
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func HasAnyTag ¶
HasAnyTag reports whether itemTags contains any of the tag IDs in ids. It is the companion to TagIDs for include/exclude filtering of series and movies.
func IsNotFound ¶
IsNotFound reports whether err is (or wraps) a *StatusError with a 404 status.
func IsRateLimited ¶ added in v1.1.0
IsRateLimited reports whether err is (or wraps) a *StatusError with a 429 status. When true, the *StatusError's RetryAfter carries the server's hint if it sent one.
func TagIDs ¶
TagIDs returns the set of tag IDs whose labels match any of the given labels. Matching is case-insensitive and trims surrounding whitespace (Sonarr and Radarr store tag labels lowercased). Labels with no matching tag are simply absent from the result. It returns nil when no labels are supplied.
Example ¶
ExampleTagIDs shows resolving tag labels to IDs and using the result to filter items by tag.
package main
import (
"fmt"
"github.com/cplieger/arrapi"
)
func main() {
tags := []arrapi.Tag{
{ID: 1, Label: "anime"},
{ID: 2, Label: "4k"},
{ID: 3, Label: "kids"},
}
want := arrapi.TagIDs(tags, "anime", "kids")
fmt.Println(arrapi.HasAnyTag([]int{3, 9}, want)) // carries "kids"
fmt.Println(arrapi.HasAnyTag([]int{2}, want)) // only "4k"
}
Output: true false
func UnmatchedLabels ¶ added in v1.4.0
UnmatchedLabels returns the labels (verbatim, in input order) that match no tag in tags, following the same case-insensitive, whitespace-trimmed rule as TagIDs. Empty or whitespace-only labels are ignored. It returns nil when every non-empty label matches or none is supplied, and is the companion to TagIDs for surfacing a misconfigured tag name.
Types ¶
type AlternateTitle ¶
type AlternateTitle struct {
Title string `json:"title"`
}
AlternateTitle is an alternate title for a series or movie.
type Command ¶ added in v1.1.0
Command is a Sonarr/Radarr command resource. The endpoint queues the command and returns it with an ID and a Status ("queued", "started", "completed", or "failed"); poll GetCommandByID to follow it to completion.
type Episode ¶
type Episode struct {
EpisodeFile *EpisodeFile `json:"episodeFile"`
Title string `json:"title"`
AirDate string `json:"airDate"`
ID int `json:"id"`
SeriesID int `json:"seriesId"`
SeasonNumber int `json:"seasonNumber"`
EpisodeNumber int `json:"episodeNumber"`
AbsoluteEpisodeNumber int `json:"absoluteEpisodeNumber"`
SceneSeasonNumber int `json:"sceneSeasonNumber"`
SceneEpisodeNumber int `json:"sceneEpisodeNumber"`
HasFile bool `json:"hasFile"`
Monitored bool `json:"monitored"`
}
Episode is a Sonarr episode.
type EpisodeFile ¶
type EpisodeFile struct {
MediaInfo *MediaInfo `json:"mediaInfo"`
RelativePath string `json:"relativePath"`
Path string `json:"path"`
SceneName string `json:"sceneName"`
ReleaseGroup string `json:"releaseGroup"`
ID int `json:"id"`
Size int64 `json:"size"`
}
EpisodeFile holds file details for a Sonarr episode.
type EventType ¶
type EventType int
EventType identifies a Sonarr/Radarr history event. Its integer values follow Sonarr's HistoryEventType enum; Radarr's string encoding is mapped to the same semantic values (see eventTypeByName). Decode with UnmarshalJSON, which accepts either the integer (Sonarr) or the string (Radarr) form.
const ( // EventGrabbed is a release grabbed from an indexer. EventGrabbed EventType = 1 // EventFolderImported is a download folder imported at the series or movie // level (Sonarr "seriesFolderImported", Radarr "movieFolderImported"). EventFolderImported EventType = 2 // EventDownloadImported is a downloaded file imported into the library // (the "downloadFolderImported" event). EventDownloadImported EventType = 3 // EventDownloadFailed is a failed download. EventDownloadFailed EventType = 4 // EventFileDeleted is an episode-file or movie-file deletion. EventFileDeleted EventType = 5 // EventFileRenamed is an episode-file or movie-file rename. EventFileRenamed EventType = 6 // EventDownloadIgnored is a grabbed download that was ignored. EventDownloadIgnored EventType = 7 )
func (EventType) String ¶ added in v1.1.0
String returns a stable, human-readable name for the event type, suitable for structured logs. Known types return a service-agnostic label (which for single-name events matches the arr wire token); any other value (including the zero/unknown type) returns the Go-style EventType(<n>).
func (*EventType) UnmarshalJSON ¶
UnmarshalJSON decodes the integer form (Sonarr) or the string form (Radarr). The integer path uses Sonarr's numbering, which is safe because Radarr encodes the event as a string. An unknown string, negative integer, or unmodeled positive integer decodes to 0 (unknown); HistoryRecord preserves the raw token in RawEventType.
type HistoryOptions ¶ added in v1.1.0
HistoryOptions parameterizes a paged GetHistory call. A zero Page or PageSize uses the arr default (page 1; the server's default page size).
type HistoryPage ¶ added in v1.1.0
type HistoryPage struct {
Records []HistoryRecord `json:"records"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
TotalRecords int `json:"totalRecords"`
}
HistoryPage is one page from the paged /history endpoint (newest first).
type HistoryRecord ¶
type HistoryRecord struct {
Date time.Time `json:"date"`
Data map[string]string `json:"data"`
SourceTitle string `json:"sourceTitle"`
RawEventType string `json:"-"`
EventType EventType `json:"eventType"`
ID int `json:"id"`
SeriesID int `json:"seriesId"`
EpisodeID int `json:"episodeId"`
MovieID int `json:"movieId"`
}
HistoryRecord is a single Sonarr or Radarr history event. Sonarr populates SeriesID/EpisodeID; Radarr populates MovieID. Data carries event-specific key/value detail (e.g. "importedPath"). RawEventType holds the original wire token when the event is one arrapi does not model (EventType is then 0).
func (*HistoryRecord) ImportedPath ¶
func (h *HistoryRecord) ImportedPath() string
ImportedPath returns the imported file path from a download-import event's data dictionary, or "" when absent.
func (*HistoryRecord) UnmarshalJSON ¶ added in v1.1.0
func (h *HistoryRecord) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes a history record and, when the event is not one arrapi models, preserves the raw eventType token in RawEventType so a new upstream event stays identifiable in logs rather than collapsing silently to 0.
type Language ¶ added in v1.2.0
Language is a Sonarr/Radarr language reference, such as a series' or movie's original language. Only the identity fields (name + id) are modeled; the arr resource carries no further language detail this client needs.
type MediaInfo ¶
type MediaInfo struct {
AudioLanguages string `json:"audioLanguages"`
Subtitles string `json:"subtitles"`
VideoCodec string `json:"videoCodec"`
AudioCodec string `json:"audioCodec"`
}
MediaInfo holds media-analysis details for an episode or movie file.
type Movie ¶
type Movie struct {
MovieFile *MovieFile `json:"movieFile"`
OriginalLanguage *Language `json:"originalLanguage"`
Title string `json:"title"`
SortTitle string `json:"sortTitle"`
ImdbID string `json:"imdbId"`
InCinemas string `json:"inCinemas"`
DigitalRelease string `json:"digitalRelease"`
Path string `json:"path"`
RootFolderPath string `json:"rootFolderPath"`
Status string `json:"status"`
AlternateTitles []AlternateTitle `json:"alternateTitles"`
Tags []int `json:"tags"`
ID int `json:"id"`
TmdbID int `json:"tmdbId"`
Year int `json:"year"`
QualityProfileID int `json:"qualityProfileId"`
HasFile bool `json:"hasFile"`
Monitored bool `json:"monitored"`
}
Movie is a Radarr movie.
func (*Movie) WebURL ¶ added in v1.5.0
WebURL returns the Radarr web-UI deep-link to this movie for the given Radarr base URL, or "" when the base URL is empty or the movie has no TMDB id. Radarr's per-movie route is /movie/{titleSlug}, and Radarr sets that slug to the TMDB id, so the numeric TMDB id resolves the page directly.
type MovieFile ¶
type MovieFile struct {
MediaInfo *MediaInfo `json:"mediaInfo"`
RelativePath string `json:"relativePath"`
Path string `json:"path"`
SceneName string `json:"sceneName"`
ReleaseGroup string `json:"releaseGroup"`
ID int `json:"id"`
Size int64 `json:"size"`
}
MovieFile holds file details for a Radarr movie.
type Option ¶
type Option func(*config)
Option configures a Sonarr or Radarr client at construction time.
func WithBaseDelay ¶
WithBaseDelay sets the base delay for the exponential backoff between retries. Default: 1s.
func WithHTTPClient ¶
WithHTTPClient sets the underlying *http.Client. When set, the caller owns the client's transport, timeout, and redirect policy; arrapi's defaults are not applied. A nil client is ignored. Use this to share a connection pool, pin a custom CA (see github.com/cplieger/httpx/v2.CATransport), or inject a test server client.
Security: arrapi's default client restricts redirects to the same host and refuses https->http downgrades, so the X-Api-Key (sent on every request) is never forwarded to another origin or onto a cleartext hop. Go forwards custom headers across redirects, stripping only Authorization and Cookie. A client supplied here that follows cross-host redirects (for example one using net/http's default policy) leaks the X-Api-Key to the redirect target, and a same-host downgrade sends it over cleartext. Set CheckRedirect to a policy such as httpx.RedirectPolicyFunc(httpx.WithSameHost(), httpx.WithMaxHops(10)) from github.com/cplieger/httpx/v2; that policy keeps both guards unless WithAllowSchemeDowngrade is explicitly enabled.
func WithMaxAttempts ¶
WithMaxAttempts sets the total number of HTTP attempts (including the first) for a transient failure. Values below 1 are clamped to 1 (try exactly once). Default: 3.
func WithTimeout ¶
WithTimeout sets the per-request timeout applied when the caller's context carries no deadline of its own. When the caller's context has a deadline, it is authoritative and used as-is; arrapi imposes no separate client-level ceiling on top of it. Default: 120s.
type QualityProfile ¶
QualityProfile is a Sonarr or Radarr quality profile. Only the identity fields are modeled; the profile's item/cutoff detail is out of scope.
type Radarr ¶
type Radarr struct {
// contains filtered or unexported fields
}
Radarr is a client for a single Radarr v3 instance. The zero value is not usable; construct one with NewRadarr. A Radarr is safe for concurrent use.
func NewRadarr ¶
NewRadarr returns a Radarr client for the given base URL (e.g. "http://radarr:7878") and API key. It returns an error if the URL is not an absolute http(s) URL or the key is empty.
func (Radarr) Close ¶
func (c Radarr) Close()
Close releases idle connections held by the client's HTTP transport. It is safe to call more than once.
func (Radarr) GetCommandByID ¶ added in v1.1.0
GetCommandByID returns the current state of a previously issued command, so a caller can poll a rescan or refresh to completion. It returns a *StatusError for which IsNotFound reports true when no command has that ID. Available on both Sonarr and Radarr.
func (Radarr) GetHistory ¶ added in v1.1.0
func (c Radarr) GetHistory(ctx context.Context, opts HistoryOptions) (HistoryPage, error)
GetHistory returns one page of history from the paged /history endpoint, newest first. Unlike GetHistorySince it is bounded by page size, so it suits backfills and large scans. Filter the returned records by EventType client-side; the arr eventType query parameter is numbered per service and is not portable. Available on both Sonarr and Radarr.
func (Radarr) GetHistorySince ¶
func (c Radarr) GetHistorySince(ctx context.Context, since time.Time, eventTypes ...EventType) ([]HistoryRecord, error)
GetHistorySince returns history records on or after since (the arr endpoint orders newest first). Pass one or more event types to filter the result; pass none to return every type. Available on both Sonarr and Radarr.
A zero-value/unset EventType in the filter is ignored, so a filter made up only of unset values behaves the same as passing none (returns every type).
Filtering is client-side: the arr eventType query parameter is numbered per service (Sonarr and Radarr disagree on the integers), so a server-side filter is not portable. Note that /history/since is unbounded, so a wide since window can return a large payload (subject to the response size cap); use GetHistory for bounded, paged scans.
func (*Radarr) GetMovieByID ¶ added in v1.1.0
GetMovieByID returns the single movie with the given Radarr ID. It returns a *StatusError for which IsNotFound reports true when no movie has that ID.
func (Radarr) GetQualityProfiles ¶
func (c Radarr) GetQualityProfiles(ctx context.Context) ([]QualityProfile, error)
GetQualityProfiles returns every quality profile defined on the instance.
func (Radarr) GetRootFolders ¶
func (c Radarr) GetRootFolders(ctx context.Context) ([]RootFolder, error)
GetRootFolders returns every root folder configured on the instance.
func (Radarr) GetSystemStatus ¶
func (c Radarr) GetSystemStatus(ctx context.Context) (SystemStatus, error)
GetSystemStatus returns the instance's system status (version, app name).
func (Radarr) Ping ¶
Ping verifies connectivity and credentials against the instance's system-status endpoint. It returns nil on success, a *StatusError (a 401 for an invalid API key), or a transport error. A short timeout bounds it so config validation fails fast; it does not retry.
func (*Radarr) RefreshMovie ¶
RefreshMovie asks Radarr to refresh the movie's metadata and rescan its files. It returns the queued command.
func (*Radarr) RescanMovie ¶
RescanMovie asks Radarr to rescan the movie's folder for new or changed files. It returns the queued command.
func (Radarr) ResolveTagIDs ¶ added in v1.4.0
func (c Radarr) ResolveTagIDs(ctx context.Context, labels ...string) (ids map[int]struct{}, unmatched []string, err error)
ResolveTagIDs fetches the instance's tags and resolves the given labels to their tag IDs. It returns the set of matched IDs and, separately, the labels that matched no tag, so a caller filtering by configured tag names can flag a misconfiguration rather than silently ignore it. Matching is case-insensitive and trims surrounding whitespace. Passing no labels returns (nil, nil, nil) without issuing a request. It is the network-backed convenience over GetTags + TagIDs + UnmatchedLabels. Available on both Sonarr and Radarr.
type ResponseTooLargeError ¶ added in v1.1.0
ResponseTooLargeError is returned when a response body exceeds the client's size cap for that endpoint. The body is rejected rather than truncated, so a caller never decodes a silently-cut payload.
func (*ResponseTooLargeError) Error ¶ added in v1.1.0
func (e *ResponseTooLargeError) Error() string
Error implements the error interface.
type RootFolder ¶
type RootFolder struct {
Path string `json:"path"`
ID int `json:"id"`
FreeSpace int64 `json:"freeSpace"`
Accessible bool `json:"accessible"`
}
RootFolder is a configured root folder on a Sonarr or Radarr instance.
type Season ¶
type Season struct {
Statistics *SeasonStatistics `json:"statistics"`
SeasonNumber int `json:"seasonNumber"`
Monitored bool `json:"monitored"`
}
Season is per-season metadata on a Sonarr series.
type SeasonStatistics ¶
type SeasonStatistics struct {
EpisodeFileCount int `json:"episodeFileCount"`
EpisodeCount int `json:"episodeCount"`
TotalEpisodeCount int `json:"totalEpisodeCount"`
}
SeasonStatistics holds per-season episode counts.
type Series ¶
type Series struct {
Statistics *SeriesStatistics `json:"statistics"`
OriginalLanguage *Language `json:"originalLanguage"`
Title string `json:"title"`
SortTitle string `json:"sortTitle"`
TitleSlug string `json:"titleSlug"`
ImdbID string `json:"imdbId"`
FirstAired string `json:"firstAired"`
Path string `json:"path"`
RootFolderPath string `json:"rootFolderPath"`
Status string `json:"status"`
Seasons []Season `json:"seasons"`
AlternateTitles []AlternateTitle `json:"alternateTitles"`
Tags []int `json:"tags"`
ID int `json:"id"`
TvdbID int `json:"tvdbId"`
TmdbID int `json:"tmdbId"`
Year int `json:"year"`
QualityProfileID int `json:"qualityProfileId"`
Monitored bool `json:"monitored"`
}
Series is a Sonarr series.
func (*Series) WebURL ¶ added in v1.5.0
WebURL returns the Sonarr web-UI deep-link to this series for the given Sonarr base URL (e.g. "https://sonarr.example.com"), or "" when the base URL or the series title slug is empty. Sonarr's only per-series route is /series/{titleSlug}, where the slug is a TheTVDB text slug (set from the metadata provider) that is not derivable from any ID, so the slug must come from the series record.
type SeriesStatistics ¶
type SeriesStatistics struct {
SeasonCount int `json:"seasonCount"`
EpisodeFileCount int `json:"episodeFileCount"`
EpisodeCount int `json:"episodeCount"`
TotalEpisodeCount int `json:"totalEpisodeCount"`
}
SeriesStatistics holds series-level episode counts.
type Sonarr ¶
type Sonarr struct {
// contains filtered or unexported fields
}
Sonarr is a client for a single Sonarr v3 instance. The zero value is not usable; construct one with NewSonarr. A Sonarr is safe for concurrent use.
func NewSonarr ¶
NewSonarr returns a Sonarr client for the given base URL (e.g. "http://sonarr:8989") and API key. It returns an error if the URL is not an absolute http(s) URL or the key is empty.
Example ¶
ExampleNewSonarr shows the construct → ping → fetch flow. It is compiled as documentation but not run (no Output comment), so it needs no live instance.
package main
import (
"context"
"fmt"
"github.com/cplieger/arrapi"
)
func main() {
ctx := context.Background()
sonarr, err := arrapi.NewSonarr("http://sonarr:8989", "your-api-key")
if err != nil {
return
}
defer sonarr.Close()
if err := sonarr.Ping(ctx); err != nil {
return
}
series, err := sonarr.GetSeries(ctx)
if err != nil {
return
}
fmt.Printf("%d series\n", len(series))
}
Output:
func (Sonarr) Close ¶
func (c Sonarr) Close()
Close releases idle connections held by the client's HTTP transport. It is safe to call more than once.
func (Sonarr) GetCommandByID ¶ added in v1.1.0
GetCommandByID returns the current state of a previously issued command, so a caller can poll a rescan or refresh to completion. It returns a *StatusError for which IsNotFound reports true when no command has that ID. Available on both Sonarr and Radarr.
func (*Sonarr) GetEpisodeByID ¶ added in v1.1.0
GetEpisodeByID returns the single episode with the given Sonarr ID. It returns a *StatusError for which IsNotFound reports true when no episode has that ID.
func (*Sonarr) GetEpisodes ¶
GetEpisodes returns all episodes for the given series, including episode-file details (release group, size, media info) where present.
func (Sonarr) GetHistory ¶ added in v1.1.0
func (c Sonarr) GetHistory(ctx context.Context, opts HistoryOptions) (HistoryPage, error)
GetHistory returns one page of history from the paged /history endpoint, newest first. Unlike GetHistorySince it is bounded by page size, so it suits backfills and large scans. Filter the returned records by EventType client-side; the arr eventType query parameter is numbered per service and is not portable. Available on both Sonarr and Radarr.
func (Sonarr) GetHistorySince ¶
func (c Sonarr) GetHistorySince(ctx context.Context, since time.Time, eventTypes ...EventType) ([]HistoryRecord, error)
GetHistorySince returns history records on or after since (the arr endpoint orders newest first). Pass one or more event types to filter the result; pass none to return every type. Available on both Sonarr and Radarr.
A zero-value/unset EventType in the filter is ignored, so a filter made up only of unset values behaves the same as passing none (returns every type).
Filtering is client-side: the arr eventType query parameter is numbered per service (Sonarr and Radarr disagree on the integers), so a server-side filter is not portable. Note that /history/since is unbounded, so a wide since window can return a large payload (subject to the response size cap); use GetHistory for bounded, paged scans.
func (Sonarr) GetQualityProfiles ¶
func (c Sonarr) GetQualityProfiles(ctx context.Context) ([]QualityProfile, error)
GetQualityProfiles returns every quality profile defined on the instance.
func (Sonarr) GetRootFolders ¶
func (c Sonarr) GetRootFolders(ctx context.Context) ([]RootFolder, error)
GetRootFolders returns every root folder configured on the instance.
func (*Sonarr) GetSeriesByID ¶ added in v1.1.0
GetSeriesByID returns the single series with the given Sonarr ID. It returns a *StatusError for which IsNotFound reports true when no series has that ID.
func (Sonarr) GetSystemStatus ¶
func (c Sonarr) GetSystemStatus(ctx context.Context) (SystemStatus, error)
GetSystemStatus returns the instance's system status (version, app name).
func (Sonarr) Ping ¶
Ping verifies connectivity and credentials against the instance's system-status endpoint. It returns nil on success, a *StatusError (a 401 for an invalid API key), or a transport error. A short timeout bounds it so config validation fails fast; it does not retry.
func (*Sonarr) RefreshSeries ¶
RefreshSeries asks Sonarr to refresh the series' metadata and rescan its files. It returns the queued command.
func (*Sonarr) RescanSeries ¶
RescanSeries asks Sonarr to rescan the series' folder for new or changed files (for example after an external tool wrote a subtitle). It does not re-fetch metadata; use RefreshSeries for that. It returns the queued command.
func (Sonarr) ResolveTagIDs ¶ added in v1.4.0
func (c Sonarr) ResolveTagIDs(ctx context.Context, labels ...string) (ids map[int]struct{}, unmatched []string, err error)
ResolveTagIDs fetches the instance's tags and resolves the given labels to their tag IDs. It returns the set of matched IDs and, separately, the labels that matched no tag, so a caller filtering by configured tag names can flag a misconfiguration rather than silently ignore it. Matching is case-insensitive and trims surrounding whitespace. Passing no labels returns (nil, nil, nil) without issuing a request. It is the network-backed convenience over GetTags + TagIDs + UnmatchedLabels. Available on both Sonarr and Radarr.
type StatusError ¶
StatusError is a non-2xx HTTP response from a Sonarr or Radarr API. It implements the httpx.Transient interface, so the httpx retry helpers treat a 429 or any 5xx as retryable and every 4xx as permanent. RetryAfter carries the server's Retry-After hint (capped) whenever the response includes a Retry-After header (in practice a 429 or a 503); it is zero otherwise. Only a transient status actually consults it during retry.
func (*StatusError) Error ¶
func (e *StatusError) Error() string
Error implements the error interface.
func (*StatusError) IsTransient ¶
func (e *StatusError) IsTransient() bool
IsTransient reports whether the response is retryable: HTTP 429 (rate limited) or any 5xx (server error).
func (*StatusError) RetryAfterHint ¶ added in v1.3.0
func (e *StatusError) RetryAfterHint() time.Duration
RetryAfterHint implements httpx.RetryAfterHint: it exposes the capped Retry-After hint so httpx.RetryWithBackoff waits it out before the next retry instead of its jittered backoff. It is zero when the response carried no Retry-After (in practice, anything but a 429 or a 503), in which case RetryWithBackoff falls back to the jittered exponential backoff.
type SystemStatus ¶
type SystemStatus struct {
Version string `json:"version"`
AppName string `json:"appName"`
InstanceName string `json:"instanceName"`
}
SystemStatus is the subset of a Sonarr/Radarr system-status response used for connectivity checks and version reporting.