golift.io/starr@v1.0.0/sonarr/episodefile.go (about) 1 package sonarr 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "net/url" 9 "path" 10 "time" 11 12 "golift.io/starr" 13 ) 14 15 const bpEpisodeFile = APIver + "/episodeFile" 16 17 // EpisodeFile is the output from the /api/v3/episodeFile endpoint. 18 type EpisodeFile struct { 19 ID int64 `json:"id"` 20 SeriesID int64 `json:"seriesId"` 21 SeasonNumber int `json:"seasonNumber"` 22 RelativePath string `json:"relativePath"` 23 Path string `json:"path"` 24 Size int64 `json:"size"` 25 DateAdded time.Time `json:"dateAdded"` 26 SceneName string `json:"sceneName"` 27 ReleaseGroup string `json:"releaseGroup"` 28 Language *starr.Value `json:"language"` 29 Quality *starr.Quality `json:"quality"` 30 MediaInfo *MediaInfo `json:"mediaInfo"` 31 QualityCutoffNotMet bool `json:"qualityCutoffNotMet"` 32 LanguageCutoffNotMet bool `json:"languageCutoffNotMet"` 33 CustomFormats []*CustomFormatOutput `json:"customFormats"` // v4 only 34 } 35 36 // MediaInfo is part of an EpisodeFile. 37 type MediaInfo struct { 38 AudioBitrate int `json:"audioBitrate"` 39 AudioChannels float64 `json:"audioChannels"` 40 AudioCodec string `json:"audioCodec"` 41 AudioLanguages string `json:"audioLanguages"` 42 AudioStreamCount int `json:"audioStreamCount"` 43 VideoBitDepth int `json:"videoBitDepth"` 44 VideoBitrate int `json:"videoBitrate"` 45 VideoCodec string `json:"videoCodec"` 46 VideoFPS float64 `json:"videoFps"` 47 Resolution string `json:"resolution"` 48 RunTime starr.PlayTime `json:"runTime"` 49 ScanType string `json:"scanType"` 50 Subtitles string `json:"subtitles"` 51 } 52 53 // GetEpisodeFiles returns information about episode files by episode file IDs. 54 func (s *Sonarr) GetEpisodeFiles(episodeFileIDs ...int64) ([]*EpisodeFile, error) { 55 return s.GetEpisodeFilesContext(context.Background(), episodeFileIDs...) 56 } 57 58 // GetEpisodeFilesContext returns information about episode files by episode file IDs. 59 func (s *Sonarr) GetEpisodeFilesContext(ctx context.Context, episodeFileIDs ...int64) ([]*EpisodeFile, error) { 60 var ids string 61 for _, efID := range episodeFileIDs { 62 ids += fmt.Sprintf("%d,", efID) // the extra comma is ok. 63 } 64 65 req := starr.Request{URI: bpEpisodeFile, Query: make(url.Values)} 66 req.Query.Add("episodeFileIds", ids) 67 68 var output []*EpisodeFile 69 if err := s.GetInto(ctx, req, &output); err != nil { 70 return nil, fmt.Errorf("api.Get(%s): %w", &req, err) 71 } 72 73 return output, nil 74 } 75 76 // GetSeriesEpisodeFile returns information about all episode files in a series. 77 func (s *Sonarr) GetSeriesEpisodeFiles(seriesID int64) ([]*EpisodeFile, error) { 78 return s.GetSeriesEpisodeFilesContext(context.Background(), seriesID) 79 } 80 81 // GetSeriesEpisodeFilesContext returns information about episode files by episode file ID. 82 func (s *Sonarr) GetSeriesEpisodeFilesContext(ctx context.Context, seriesID int64) ([]*EpisodeFile, error) { 83 var output []*EpisodeFile 84 85 req := starr.Request{URI: bpEpisodeFile, Query: make(url.Values)} 86 req.Query.Add("seriesId", fmt.Sprint(seriesID)) 87 88 if err := s.GetInto(ctx, req, &output); err != nil { 89 return nil, fmt.Errorf("api.Get(%s): %w", &req, err) 90 } 91 92 return output, nil 93 } 94 95 // UpdateEpisodeFile updates an episode file's quality. Use GetQualityProfiles() to find the available IDs. 96 func (s *Sonarr) UpdateEpisodeFileQuality(episodeFileID, qualityID int64) (*EpisodeFile, error) { 97 return s.UpdateEpisodeFileQualityContext(context.Background(), episodeFileID, qualityID) 98 } 99 100 // UpdateEpisodeFileQualityContext updates an episode file, and takes a context. 101 func (s *Sonarr) UpdateEpisodeFileQualityContext( 102 ctx context.Context, 103 episodeFileID int64, 104 qualityID int64, 105 ) (*EpisodeFile, error) { 106 var body bytes.Buffer 107 108 err := json.NewEncoder(&body).Encode(&EpisodeFile{ 109 ID: episodeFileID, 110 Quality: &starr.Quality{Quality: &starr.BaseQuality{ID: qualityID}}, 111 }) 112 if err != nil { 113 return nil, fmt.Errorf("json.Marshal(%s): %w", bpEpisodeFile, err) 114 } 115 116 var output EpisodeFile 117 118 req := starr.Request{URI: path.Join(bpEpisodeFile, fmt.Sprint(episodeFileID)), Body: &body} 119 if err := s.PutInto(ctx, req, &output); err != nil { 120 return nil, fmt.Errorf("api.Put(%s): %w", &req, err) 121 } 122 123 return &output, nil 124 } 125 126 // DeleteEpisodeFile deletes an episode file. 127 func (s *Sonarr) DeleteEpisodeFile(episodeFileID int64) error { 128 return s.DeleteEpisodeFileContext(context.Background(), episodeFileID) 129 } 130 131 // DeleteEpisodeFileContext deletes an episode file, and takes a context. 132 func (s *Sonarr) DeleteEpisodeFileContext(ctx context.Context, episodeFileID int64) error { 133 req := starr.Request{URI: path.Join(bpEpisodeFile, fmt.Sprint(episodeFileID))} 134 if err := s.DeleteAny(ctx, req); err != nil { 135 return fmt.Errorf("api.Delete(%s): %w", &req, err) 136 } 137 138 return nil 139 }