Skip to content

Commit

Permalink
Merge pull request #26 from tphoney/parallelise-cinema-paradiso
Browse files Browse the repository at this point in the history
(feat) parallelise cinema-paradiso movie search
  • Loading branch information
tphoney committed May 17, 2024
2 parents a4d7a50 + 7461c5a commit e57c8d7
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 118 deletions.
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

0 comments on commit e57c8d7

Please sign in to comment.