Skip to content

Commit

Permalink
(fix) improve flawed tv filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
tphoney committed May 6, 2024
1 parent 5e76834 commit c9029eb
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 88 deletions.
5 changes: 2 additions & 3 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@

## bugs

- add plex name hover over for tv/movies/music, so we can identify if there is a mismatch between the plex name and the search name
- allow amazon tv search for indivdual series
- remove links to tv series we already have in plex. eg dont show adventure time series 1 and 2 ?
- remove dead fields from the tv data types

## done

Expand All @@ -26,3 +23,5 @@
- add ui for music search
- spotify search
- bastille is showing "give me the future" as an album. wrong !!
- remove dead fields from the tv data types
- remove links to tv series we already have in plex. eg dont show adventure time series 1 and 2 ?
14 changes: 7 additions & 7 deletions cinemaparadiso/cinemaparadiso.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ func SearchCinemaParadisoTV(plexTVShow *types.PlexTVShow) (tvSearchResult types.
// now we can get the series information for each best match
for i := range tvSearchResult.TVSearchResults {
if tvSearchResult.TVSearchResults[i].BestMatch {
tvSearchResult.TVSearchResults[i].Series, _ = findTVSeriesInfo(tvSearchResult.TVSearchResults[i].URL)
tvSearchResult.TVSearchResults[i].Seasons, _ = findTVSeriesInfo(tvSearchResult.TVSearchResults[i].URL)
}
}
return tvSearchResult, nil
}

func findTVSeriesInfo(seriesURL string) (tvSeries []types.TVSeriesResult, err error) {
func findTVSeriesInfo(seriesURL string) (tvSeries []types.TVSeasonResult, err error) {
// make a request to the url
req, err := http.NewRequestWithContext(context.Background(), "GET", seriesURL, bytes.NewBuffer([]byte{}))
if err != nil {
Expand Down Expand Up @@ -118,18 +118,18 @@ func makeSearchRequest(urlEncodedTitle string) (rawResponse string, err error) {
return rawData, nil
}

func findTVSeriesInResponse(response string) (tvSeries []types.TVSeriesResult) {
func findTVSeriesInResponse(response string) (tvSeries []types.TVSeasonResult) {
// look for the series in the response
r := regexp.MustCompile(`<li data-filmId="(\d*)">`)
match := r.FindAllStringSubmatch(response, -1)
for i, m := range match {
tvSeries = append(tvSeries, types.TVSeriesResult{Number: i, URL: m[1]})
tvSeries = append(tvSeries, types.TVSeasonResult{Number: i, URL: m[1]})
}
// remove the first entry as it is general information
results := make([]types.TVSeriesResult, 0, len(tvSeries))
results := make([]types.TVSeasonResult, 0, len(tvSeries))
if len(tvSeries) > 0 {
tvSeries = tvSeries[1:]
ch := make(chan *types.TVSeriesResult, len(tvSeries))
ch := make(chan *types.TVSeasonResult, len(tvSeries))

semaphore := make(chan struct{}, types.ConcurrencyLimit)
for i := range tvSeries {
Expand All @@ -152,7 +152,7 @@ func findTVSeriesInResponse(response string) (tvSeries []types.TVSeriesResult) {
return results
}

func makeSeriesRequest(tv types.TVSeriesResult, ch chan<- *types.TVSeriesResult) {
func makeSeriesRequest(tv types.TVSeasonResult, ch chan<- *types.TVSeasonResult) {
content := []byte(fmt.Sprintf("FilmID=%s", tv.URL))
req, err := http.NewRequestWithContext(context.Background(), "POST", cinemaparadisoSeriesURL, bytes.NewBuffer(content))
if err != nil {
Expand Down
8 changes: 4 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ func initializeFlags() {

func initializePlexMovies() []types.PlexMovie {
var allMovies []types.PlexMovie
allMovies = append(allMovies, plex.GetPlexMovies(plexIP, plexMovieLibraryID, plexToken, "sd", nil)...)
allMovies = append(allMovies, plex.GetPlexMovies(plexIP, plexMovieLibraryID, plexToken, "480", nil)...)
allMovies = append(allMovies, plex.GetPlexMovies(plexIP, plexMovieLibraryID, plexToken, "576", nil)...)
allMovies = append(allMovies, plex.GetPlexMovies(plexIP, plexMovieLibraryID, plexToken, "720", nil)...)
allMovies = append(allMovies, plex.GetPlexMovies(plexIP, plexMovieLibraryID, plexToken, types.PlexResolution240, nil)...)
allMovies = append(allMovies, plex.GetPlexMovies(plexIP, plexMovieLibraryID, plexToken, types.PlexResolution480, nil)...)
allMovies = append(allMovies, plex.GetPlexMovies(plexIP, plexMovieLibraryID, plexToken, types.PlexResolution576, nil)...)
allMovies = append(allMovies, plex.GetPlexMovies(plexIP, plexMovieLibraryID, plexToken, types.PlexResolution720, nil)...)

fmt.Printf("\nThere are a total of %d movies in the library.\n\nMovies available:\n", len(allMovies))
return allMovies
Expand Down
2 changes: 1 addition & 1 deletion musicbrainz/musicbrainz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestSearchMusicBrainzArtist(t *testing.T) {
{
Name: "AC/DC",
ID: "66c662b6-6e2f-4930-8610-912e24c63ed1",
Albums: make([]types.MusicSearchAlbumResult, 17),
Albums: make([]types.MusicSearchAlbumResult, 18),
},
},
},
Expand Down
53 changes: 38 additions & 15 deletions plex/plex.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ func GetPlexMovies(ipAddress, libraryID, plexToken, resolution string, filters [
return movieList
}

func GetPlexTV(ipAddress, libraryID, plexToken string, resolutions []string) (tvShowList []types.PlexTVShow) {
func GetPlexTV(ipAddress, libraryID, plexToken string) (tvShowList []types.PlexTVShow) {
url := fmt.Sprintf("http://%s:32400/library/sections/%s/all", ipAddress, libraryID)

req, err := http.NewRequestWithContext(context.Background(), "GET", url, http.NoBody)
Expand Down Expand Up @@ -547,7 +547,7 @@ func GetPlexTV(ipAddress, libraryID, plexToken string, resolutions []string) (tv
tvShowList = extractTVShows(string(body))
// now we need to get the episodes for each TV show
for i := range tvShowList {
tvShowList[i].Seasons = GetPlexTVSeasons(ipAddress, plexToken, tvShowList[i].RatingKey, resolutions)
tvShowList[i].Seasons = GetPlexTVSeasons(ipAddress, plexToken, tvShowList[i].RatingKey)
}
// remove TV shows with no seasons
var filteredTVShows []types.PlexTVShow
Expand Down Expand Up @@ -677,7 +677,7 @@ func extractMusicArtists(xmlString string) (artists []types.PlexMusicArtist, err
return artists, nil
}

func GetPlexTVSeasons(ipAddress, plexToken, ratingKey string, resolutions []string) (seasonList []types.PlexTVSeason) {
func GetPlexTVSeasons(ipAddress, plexToken, ratingKey string) (seasonList []types.PlexTVSeason) {
url := fmt.Sprintf("http://%s:32400/library/metadata/%s/children?", ipAddress, ratingKey)

req, err := http.NewRequestWithContext(context.Background(), "GET", url, http.NoBody)
Expand Down Expand Up @@ -707,7 +707,7 @@ func GetPlexTVSeasons(ipAddress, plexToken, ratingKey string, resolutions []stri
// os.WriteFile("seasons.xml", body, 0644)
// now we need to get the episodes for each TV show
for i := range seasonList {
episodes := GetPlexTVEpisodes(ipAddress, plexToken, seasonList[i].RatingKey, resolutions)
episodes := GetPlexTVEpisodes(ipAddress, plexToken, seasonList[i].RatingKey)
if len(episodes) > 0 {
seasonList[i].Episodes = episodes
}
Expand All @@ -716,13 +716,46 @@ func GetPlexTVSeasons(ipAddress, plexToken, ratingKey string, resolutions []stri
var filteredSeasons []types.PlexTVSeason
for i := range seasonList {
if len(seasonList[i].Episodes) > 0 {
// lets add all of the resolutions for the episodes
var listOfResolutions []string
for j := range seasonList[i].Episodes {
listOfResolutions = append(listOfResolutions, seasonList[i].Episodes[j].Resolution)
}
// now we have all of the resolutions for the episodes
seasonList[i].LowestResolution = findLowestResolution(listOfResolutions)

filteredSeasons = append(filteredSeasons, seasonList[i])
}
}
return filteredSeasons
}

func GetPlexTVEpisodes(ipAddress, plexToken, ratingKey string, resolutions []string) (episodeList []types.PlexTVEpisode) {
func findLowestResolution(resolutions []string) (lowestResolution string) {
if slices.Contains(resolutions, types.PlexResolutionSD) {
return types.PlexResolutionSD
}
if slices.Contains(resolutions, types.PlexResolution240) {
return types.PlexResolution240
}
if slices.Contains(resolutions, types.PlexResolution480) {
return types.PlexResolution480
}
if slices.Contains(resolutions, types.PlexResolution576) {
return types.PlexResolution576
}
if slices.Contains(resolutions, types.PlexResolution720) {
return types.PlexResolution720
}
if slices.Contains(resolutions, types.PlexResolution1080) {
return types.PlexResolution1080
}
if slices.Contains(resolutions, types.PlexResolution4K) {
return types.PlexResolution4K
}
return ""
}

func GetPlexTVEpisodes(ipAddress, plexToken, ratingKey string) (episodeList []types.PlexTVEpisode) {
url := fmt.Sprintf("http://%s:32400/library/metadata/%s/children?", ipAddress, ratingKey)

req, err := http.NewRequestWithContext(context.Background(), "GET", url, http.NoBody)
Expand All @@ -749,16 +782,6 @@ func GetPlexTVEpisodes(ipAddress, plexToken, ratingKey string, resolutions []str
}

episodeList = extractTVEpisodes(string(body))
if len(resolutions) > 0 {
// filter out episodes that don't match the resolution
var filteredEpisodes []types.PlexTVEpisode
for i := range episodeList {
if slices.Contains(resolutions, episodeList[i].Resolution) {
filteredEpisodes = append(filteredEpisodes, episodeList[i])
}
}
episodeList = filteredEpisodes
}
return episodeList
}

Expand Down
48 changes: 47 additions & 1 deletion plex/plex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func TestGetPlexTV(t *testing.T) {
if plexIP == "" || plexTVLibraryID == "" || plexToken == "" {
t.Skip("ACCEPTANCE TEST: PLEX environment variables not set")
}
result := GetPlexTV(plexIP, plexTVLibraryID, plexToken, []string{})
result := GetPlexTV(plexIP, plexTVLibraryID, plexToken)

if len(result) == 0 {
t.Errorf("Expected at least one TV show, but got %d", len(result))
Expand All @@ -78,6 +78,21 @@ func TestGetPlexTV(t *testing.T) {
}
}

func TestDebugGetPlexTVSeasons(t *testing.T) {
if plexIP == "" || plexTVLibraryID == "" || plexToken == "" {
t.Skip("ACCEPTANCE TEST: PLEX environment variables not set")
}
result := GetPlexTVSeasons(plexIP, plexToken, "5383")

if len(result) == 0 {
t.Errorf("Expected at least one TV show, but got %d", len(result))
}

if len(result[0].Episodes) == 0 {
t.Errorf("Expected at least one episode, but got %d", len(result[0].Episodes))
}
}

func TestGetPlexMusic(t *testing.T) {
if plexIP == "" || plexMusicLibraryID == "" || plexToken == "" {
t.Skip("ACCEPTANCE TEST: PLEX environment variables not set")
Expand All @@ -96,3 +111,34 @@ func TestGetPlexMusic(t *testing.T) {
t.Errorf("Expected at least one album, but got %d", len(result[0].Albums))
}
}

func Test_findLowestResolution(t *testing.T) {
tests := []struct {
name string
resolutions []string
wantLowestResolution string
}{
{
name: "SD is lowest",
resolutions: []string{types.PlexResolutionSD, types.PlexResolution240, types.PlexResolution720, types.PlexResolution1080},
wantLowestResolution: types.PlexResolutionSD,
},
{
name: "4k is lowest",
resolutions: []string{types.PlexResolution4K, types.PlexResolution4K},
wantLowestResolution: types.PlexResolution4K,
},
{
name: "720 is lowest",
resolutions: []string{types.PlexResolution720, types.PlexResolution1080, types.PlexResolution720, types.PlexResolution1080},
wantLowestResolution: types.PlexResolution720,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if gotLowestResolution := findLowestResolution(tt.resolutions); gotLowestResolution != tt.wantLowestResolution {
t.Errorf("findLowestResolution() = %v, want %v", gotLowestResolution, tt.wantLowestResolution)
}
})
}
}
30 changes: 19 additions & 11 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ package types
import "time"

const (
DiskBluray = "Blu-ray"
DiskDVD = "DVD"
Disk4K = "4K Blu-ray"
PlexMovieType = "Movie"
ConcurrencyLimit = 10
DiskBluray = "Blu-ray"
DiskDVD = "DVD"
Disk4K = "4K Blu-ray"
PlexMovieType = "Movie"
PlexResolutionSD = "sd"
PlexResolution240 = "240"
PlexResolution480 = "480"
PlexResolution576 = "576"
PlexResolution720 = "720"
PlexResolution1080 = "1080"
PlexResolution4K = "4k"
ConcurrencyLimit = 10
)

type SearchResults struct {
Expand Down Expand Up @@ -60,10 +67,11 @@ type PlexTVShow struct {
}

type PlexTVSeason struct {
Title string
Number int
RatingKey string
Episodes []PlexTVEpisode
Title string
Number int
RatingKey string
LowestResolution string
Episodes []PlexTVEpisode
}

type PlexTVEpisode struct {
Expand All @@ -82,10 +90,10 @@ type TVSearchResult struct {
ReleaseDate time.Time
NewRelease bool
BoxSet bool
Series []TVSeriesResult
Seasons []TVSeasonResult
}

type TVSeriesResult struct {
type TVSeasonResult struct {
Number int
URL string
Format []string
Expand Down
4 changes: 2 additions & 2 deletions web/movies.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ func moviesHandler(w http.ResponseWriter, _ *http.Request) {
func processMoviesHTML(w http.ResponseWriter, r *http.Request) {
lookup := r.FormValue("lookup")
// plex resolutions
sd := r.FormValue("sd")
sd := r.FormValue("SD")
r240 := r.FormValue("240p")
r480 := r.FormValue("480p")
r576 := r.FormValue("576p")
r720 := r.FormValue("720p")
r1080 := r.FormValue("1080p")
r4k := r.FormValue("4k")
r4k := r.FormValue("4K")
plexResolutions := []string{sd, r240, r480, r576, r720, r1080, r4k}
// remove empty resolutions
var filteredResolutions []string
Expand Down
14 changes: 7 additions & 7 deletions web/movies.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,28 @@ <h1 class="container">Movies</h1>
<fieldset>
<legend><strong>Plex Filter:</strong> only compare movies that match the following criteria.</legend>
<label for="title" data-sort="title">
<input type="checkbox" id="sd" name="sd" value="sd">
<input type="checkbox" id="SD" name="SD" value="sd">
SD
</label>
<label for="title" data-sort="title">
<input type="checkbox" id="480p" name="480p" value="480">
<input type="checkbox" id="480" name="480" value="480">
480p
</label>
<label for="title" data-sort="title">
<input type="checkbox" id="576p" name="576p" value="576">
<input type="checkbox" id="576" name="576" value="576">
576p
</label>
<label for="title" data-sort="title">
<input type="checkbox" id="720p" name="720p" value="720">
<input type="checkbox" id="720" name="720" value="720">
720p
</label>
<label for="title" data-sort="title">
<input type="checkbox" id="1080p" name="1080p" value="1080">
<input type="checkbox" id="1080" name="1080" value="1080">
1080p
</label>
<label for="title" data-sort="title">
<input type="checkbox" id="4k" name="4k" value="4k">
4k
<input type="checkbox" id="4K" name="4K" value="4k">
4K
</label>
</fieldset>
<fieldset>
Expand Down
Loading

0 comments on commit c9029eb

Please sign in to comment.