Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat) parallelise cinema-paradiso movie search #26

Merged
merged 3 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@

- allow amazon tv search for indivdual series
- allow amazon tv search for newer series
- update movies to use tv like search
- update movies, remove the plex resolution filter add plex resolution as a column
- music, a-ha/ash doesnt match as an artist why ?
- move language filtering out of plex search,should only happens in web tv & movie

## done

Expand All @@ -30,3 +29,7 @@
- write a function to calculate plex dates
- similar artist search for music
- parallel requests for spotify search
- update movies, remove the plex resolution filter add plex resolution as a column
- parallelise cinema-paradiso movie search 6m20 to 2m25
- parallelise cinema-paradiso tv search
- for movies/tc dont refresh plex list every time, unless necessary
132 changes: 90 additions & 42 deletions cinemaparadiso/cinemaparadiso.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,103 @@ const (
cinemaparadisoSeriesURL = "https://www.cinemaparadiso.co.uk/ajax/CPMain.wsFilmDescription,CPMain.ashx?_method=ShowSeries&_session=r"
)

func SearchCinemaParadisoMovie(plexMovie types.PlexMovie) (movieSearchResult types.SearchResults, err error) {
var (
numberMoviesProcessed int = 0
numberTVProcessed int = 0
)

func GetCinemaParadisoMoviesInParallel(plexMovies []types.PlexMovie) (searchResults []types.SearchResults) {
ch := make(chan types.SearchResults, len(plexMovies))
semaphore := make(chan struct{}, types.ConcurrencyLimit)

for i := range plexMovies {
go func(i int) {
semaphore <- struct{}{}
defer func() { <-semaphore }()
searchCinemaParadisoMovie(plexMovies[i], ch)
}(i)
}

searchResults = make([]types.SearchResults, 0, len(plexMovies))
for range plexMovies {
result := <-ch
searchResults = append(searchResults, result)
numberMoviesProcessed++
}
numberMoviesProcessed = 0 // job is done
return searchResults
}

func GetCinemaParadisoTVInParallel(plexTVShows []types.PlexTVShow) (searchResults []types.SearchResults) {
ch := make(chan types.SearchResults, len(plexTVShows))
semaphore := make(chan struct{}, types.ConcurrencyLimit)

for i := range plexTVShows {
go func(i int) {
semaphore <- struct{}{}
defer func() { <-semaphore }()
searchCinemaParadisoTV(&plexTVShows[i], ch)
}(i)
}

searchResults = make([]types.SearchResults, 0, len(plexTVShows))
for range plexTVShows {
result := <-ch
searchResults = append(searchResults, result)
numberTVProcessed++
}
numberTVProcessed = 0 // job is done
return searchResults
}

func GetMovieJobProgress() int {
return numberMoviesProcessed
}

func GetTVJobProgress() int {
return numberTVProcessed
}

func searchCinemaParadisoMovie(plexMovie types.PlexMovie, movieSearchResult chan<- types.SearchResults) {
result := types.SearchResults{}
result.PlexMovie = plexMovie
urlEncodedTitle := url.QueryEscape(plexMovie.Title)
movieSearchResult.PlexMovie = plexMovie
movieSearchResult.SearchURL = cinemaparadisoSearchURL + "?form-search-field=" + urlEncodedTitle
result.SearchURL = cinemaparadisoSearchURL + "?form-search-field=" + urlEncodedTitle
rawData, err := makeSearchRequest(urlEncodedTitle)
if err != nil {
fmt.Println("Error making web request:", err)
return movieSearchResult, err
movieSearchResult <- result
return
}

moviesFound, _ := findTitlesInResponse(rawData, true)
movieSearchResult.MovieSearchResults = moviesFound
movieSearchResult = utils.MarkBestMatch(&movieSearchResult)

return movieSearchResult, nil
result.MovieSearchResults = moviesFound
result = utils.MarkBestMatch(&result)
movieSearchResult <- result
}

func SearchCinemaParadisoTV(plexTVShow *types.PlexTVShow) (tvSearchResult types.SearchResults, err error) {
func searchCinemaParadisoTV(plexTVShow *types.PlexTVShow, tvSearchResult chan<- types.SearchResults) {
result := types.SearchResults{}
urlEncodedTitle := url.QueryEscape(plexTVShow.Title)
tvSearchResult.PlexTVShow = *plexTVShow
tvSearchResult.SearchURL = cinemaparadisoSearchURL + "?form-search-field=" + urlEncodedTitle
result.PlexTVShow = *plexTVShow
result.SearchURL = cinemaparadisoSearchURL + "?form-search-field=" + urlEncodedTitle
rawData, err := makeSearchRequest(urlEncodedTitle)
if err != nil {
fmt.Println("Error making web request:", err)
return tvSearchResult, err
fmt.Println("searchCinemaParadisoTV: Error making web request:", err)
tvSearchResult <- result
return
}

_, tvFound := findTitlesInResponse(rawData, false)
tvSearchResult.TVSearchResults = tvFound
tvSearchResult = utils.MarkBestMatch(&tvSearchResult)
result.TVSearchResults = tvFound
result = utils.MarkBestMatch(&result)
// now we can get the series information for each best match
for i := range tvSearchResult.TVSearchResults {
if tvSearchResult.TVSearchResults[i].BestMatch {
tvSearchResult.TVSearchResults[i].Seasons, _ = findTVSeriesInfo(tvSearchResult.TVSearchResults[i].URL)
for i := range result.TVSearchResults {
if result.TVSearchResults[i].BestMatch {
result.TVSearchResults[i].Seasons, _ = findTVSeriesInfo(result.TVSearchResults[i].URL)
}
}
return tvSearchResult, nil
tvSearchResult <- result
}

func findTVSeriesInfo(seriesURL string) (tvSeries []types.TVSeasonResult, err error) {
Expand Down Expand Up @@ -129,20 +189,14 @@ func findTVSeriesInResponse(response string) (tvSeries []types.TVSeasonResult) {
results := make([]types.TVSeasonResult, 0, len(tvSeries))
if len(tvSeries) > 0 {
tvSeries = tvSeries[1:]
ch := make(chan *types.TVSeasonResult, len(tvSeries))

semaphore := make(chan struct{}, types.ConcurrencyLimit)
for i := range tvSeries {
go func() {
semaphore <- struct{}{}
defer func() { <-semaphore }()
makeSeriesRequest(tvSeries[i], ch)
}()
}

for i := 0; i < len(tvSeries); i++ {
result := <-ch
results = append(results, *result)
seriesResult, err := makeSeriesRequest(tvSeries[i])
if err != nil {
fmt.Println("Error making series request:", err)
continue
}
results = append(results, seriesResult)
}
}
// sort the results by number
Expand All @@ -152,30 +206,24 @@ func findTVSeriesInResponse(response string) (tvSeries []types.TVSeasonResult) {
return results
}

func makeSeriesRequest(tv types.TVSeasonResult, ch chan<- *types.TVSeasonResult) {
func makeSeriesRequest(tv types.TVSeasonResult) (types.TVSeasonResult, error) {
content := []byte(fmt.Sprintf("FilmID=%s", tv.URL))
req, err := http.NewRequestWithContext(context.Background(), "POST", cinemaparadisoSeriesURL, bytes.NewBuffer(content))
if err != nil {
fmt.Println("Error creating request:", err)
ch <- &tv
return
return tv, fmt.Errorf("makeSeriesRequest: error creating request: %w", err)
}

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
ch <- &tv
return
return tv, fmt.Errorf("makeSeriesRequest: error sending request: %w", err)
}

defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
ch <- &tv
return
return tv, fmt.Errorf("makeSeriesRequest: error reading response body: %w", err)
}
rawData := string(body)
// write the raw data to a file
Expand All @@ -194,7 +242,7 @@ func makeSeriesRequest(tv types.TVSeasonResult, ch chan<- *types.TVSeasonResult)
}
tv.ReleaseDate = releaseDate
}
ch <- &tv
return tv, nil
}

func findTitlesInResponse(response string, movie bool) (movieResults []types.MovieSearchResult, tvResults []types.TVSearchResult) {
Expand Down
22 changes: 15 additions & 7 deletions cinemaparadiso/cinemaparadiso_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,15 @@ func TestSearchCinemaParadisoTV(t *testing.T) {
Title: "Adventure Time",
Year: "2010",
}
result, err := SearchCinemaParadisoTV(&show)
if err != nil {
t.Errorf("Error searching for TV show: %s", err)
ch := make(chan types.SearchResults, 1)
searchCinemaParadisoTV(&show, ch)
got := <-ch

if len(got.TVSearchResults) == 0 {
t.Errorf("Expected search results, but got none")
}
if result.SearchURL == "" {

if got.SearchURL == "" {
t.Errorf("Expected searchurl, but got none")
}
}
Expand All @@ -120,10 +124,14 @@ func TestSearchCinemaParadisoMovies(t *testing.T) {
Title: "Cats",
Year: "1998",
}
result, err := SearchCinemaParadisoMovie(movie)
if err != nil {
t.Errorf("Error searching for Movie show: %s", err)
ch := make(chan types.SearchResults, 1)
searchCinemaParadisoMovie(movie, ch)
result := <-ch

if len(result.MovieSearchResults) == 0 {
t.Errorf("Expected search results, but got none")
}

if result.SearchURL == "" {
t.Errorf("Expected searchurl, but got none")
}
Expand Down
15 changes: 6 additions & 9 deletions cmd/cinemaparadiso.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,13 @@ func performCinemaParadisoLookup() {
if libraryType == types.PlexMovieType {
plexMovies := initializePlexMovies()
// lets search movies in cinemaparadiso
for _, movie := range plexMovies {
movieResult, err := cinemaparadiso.SearchCinemaParadisoMovie(movie)
if err != nil {
fmt.Printf("Error searching for movie %s: %s\n", movieResult.PlexMovie.Title, err)
continue
}
// if hit, and contains any format that isnt dvd, print the movie
for _, individualResult := range movieResult.MovieSearchResults {
searchResults := cinemaparadiso.GetCinemaParadisoMoviesInParallel(plexMovies)
// if hit, and contains any format that isnt dvd, print the movie
for i := range searchResults {
for _, individualResult := range searchResults[i].MovieSearchResults {
if individualResult.BestMatch && (individualResult.Format == types.DiskBluray || individualResult.Format == types.Disk4K) {
fmt.Printf("%s %v: %s\n", movieResult.PlexMovie.Title, movieResult.PlexMovie.Year, individualResult.URL)
fmt.Printf("%s - %s (%s): %s\n", searchResults[i].PlexMovie.Title, individualResult.Format,
searchResults[i].PlexMovie.Year, individualResult.URL)
}
}
}
Expand Down
Loading
Loading