worth_watching 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e35fd2e5e42565ad5098cfba862e9416a45201d1
4
- data.tar.gz: d6bb20f5f5d8ce4b1a2282057c1e937df33930cc
3
+ metadata.gz: 048abc5a75b5f585a50481cab76c699ec622a4a6
4
+ data.tar.gz: 7ed6a1134722d026b11ee25d54db2338a7c19e1a
5
5
  SHA512:
6
- metadata.gz: 67b77513e14d79377de17e6538500ca0f9d8061afdc975f4912f6f5474f185aa448ff5b803c9870b7b73f0a91529f59c7466cbed15a8abf965d52a178a1c83f9
7
- data.tar.gz: 185fd25dbff8bc88d45a93aa8b082c53d299daf9d564d2a0ddcbfc2ef0839562e922d9765aeec8d0e373ab3063eaccb0cf2a7b0b2359ebdd451ddcef62a71393
6
+ metadata.gz: 5903062650b35280dd7373b4ea9c8079936809ca8f554f92282599eac15dd8db00d20108021123c634fd8f14cd0b99432de91e42d0455b9f364fb7ffcba8ef09
7
+ data.tar.gz: 983f743ff6b0dd3e0ad3b640ea09c7874fca898305d3356b18249419e06f6d9eb2509566a4db123239e28725300d3fa9a5560ecdb95c4cdf4784100c6c73e679
data/.gitignore CHANGED
@@ -16,4 +16,6 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  config/config.yml
19
- spec/vcr_cassettes/
19
+ spec/vcr_cassettes/
20
+ todo.txt
21
+ config.yaml
data/README.md CHANGED
@@ -1,9 +1,43 @@
1
- # WorthWatching
1
+ ## WorthWatching
2
2
 
3
- WorthWatching is a gem that allows you to aggregate movie review data from a
3
+ WorthWatching is a gem that aggregates movie review data from a
4
4
  number of different sources.
5
5
 
6
- Current supported sources are Rotten Tomatoes, IMDb and Metacritic.
6
+ Currently, the supported info sources are [Rotten Tomatoes](http://rottentomatoes.com), [IMDb](http://imdb.com) and [Metacritic](http://metacritic.com).
7
+
8
+ ### What info does WorthWatching aggregate?
9
+
10
+ The gem was designed to retrieve the overall rating form each source. But it also
11
+ retrieves extra info that may be useful.
12
+
13
+ The full list of info retrieved for each movie:
14
+
15
+ - title
16
+ - plot (no spoilers, just the general description)
17
+ - director
18
+ - cast
19
+ - genre
20
+ - release date
21
+ - **Rotten Tomatoes rating (n out of 100)**
22
+ - **IMDb rating (n out of 10)**
23
+ - **Metacritic rating (n out of 100)**
24
+ - Rotten Tomatoes movie URL
25
+ - IMDb movie URL
26
+ - Metacritic movie URL
27
+ - Rotten Tomaotes movie ID
28
+ - IMDb movie ID
29
+ - poster image URL
30
+ - reviews
31
+
32
+ Note that the success of the aggregation process is entirely dependent on knowing
33
+ the Rotten Tomatoes ID *first*.
34
+
35
+ However, you can use the `search_by_title` method to first search for a movie.
36
+ The search results include the Rotten Tomatoes ID, which you can then use aggregate movie info as
37
+ usual with the `aggregate_movie` method.
38
+
39
+ If you would like to know why this is the case, or are just interested in how aggregation happens,
40
+ [read here]() for some extra information.
7
41
 
8
42
  ## Installation
9
43
 
@@ -21,52 +55,223 @@ Or install it yourself as:
21
55
 
22
56
  ## Setup
23
57
 
24
- * Apply for the required API keys. You will need a [Rotten Tomatoes API Key](http://developer.rottentomatoes.com/) and a [TMDB API key](http://docs.themoviedb.apiary.io/).
58
+ - Apply for the required API keys. You will need a [Rotten Tomatoes API Key](http://developer.rottentomatoes.com/) and a [TMDB API key](http://docs.themoviedb.apiary.io/).
25
59
 
26
- * Fill in the details of your API keys in config/config.yml
27
60
 
28
61
  ## Usage
29
62
 
63
+ ### Getting started
64
+ ```ruby
65
+ # Create a new aggregator, passing in your API keys
66
+ movie_aggregator = WorthWatching::Aggregator.new("rotten_tomato_api_key", "tmdb_api_key")
67
+ ```
68
+
69
+ ### Searching for a movie by title
70
+
71
+ Pass the title of the movie, and the maximum number of results to return
72
+
73
+ ```ruby
74
+ # Search for movies by title. Returns an array of hashes, each hash representing
75
+ # a movie in the search result
76
+ # Note that it returns the Rotten Tomatoes ID for each movie, which is vital to aggregation
77
+ movie_aggregator.search_by_title("the godfather", 4)
78
+ => [{:title=>"The Godfather", :rt_id=>"12911", :year=>"1972"},
79
+ {:title=>"The Godfather, Part II", :rt_id=>"12926", :year=>"1974"},
80
+ {:title=>"The Godfather, Part III", :rt_id=>"13476", :year=>"1990"},
81
+ {:title=>"The Godfather of Green Bay", :rt_id=>"341816359", :year=>"2005"}]
82
+ ```
83
+
84
+ ### Retrieving info for a single movie
30
85
  ```ruby
31
- # Create a new aggregator
32
- movie_aggregator = WorthWatching::Aggregator.new("rotten_tomatoes_api_key", "tmdb_api_key")
33
86
 
34
- # Search for movie by Rotten Tomatoes ID
35
- toy_story_3 = movie_aggregator.movie_info('770672122')
87
+ # Pass the movie's Rotten Tomatoes ID
88
+ toy_story_3 = movie_aggregator.aggregate_movie("770672122")
36
89
 
37
- # We now have a Movie object and can access many attributes, including rating information
38
- toy_story_3.title
90
+ # We now have a Movie object and can access many attributes...
91
+ toy_story_3.title
39
92
  => "Toy Story 3"
93
+ ```
40
94
 
95
+ ### Rating Info
96
+ ```ruby
97
+ # Access ratings individually
41
98
  toy_story_3.rt_rating
42
99
  => 99
43
100
 
44
101
  toy_story_3.imdb_rating
45
- => 85
102
+ => 8.5
46
103
 
47
104
  toy_story_3.metacritic_rating
48
105
  => 92
49
106
 
107
+ # Get the rating summary as a string
108
+ puts toy_story_3.rating_summary
109
+ => "Rotten Tomatoes rating: 99
110
+ IMDB rating: 8.5
111
+ Metacritic rating: 92"
112
+ ```
113
+ ### General movie info
114
+ ```ruby
115
+ toy_story_3.plot
116
+ => "Pixar returns to their first success with Toy Story 3. The movie begins with
117
+ Andy leaving for college and donating his beloved toys -- including Woody
118
+ (Tom Hanks) and Buzz (Tim Allen) -- to a daycare. While the crew meets new friends,
119
+ including Ken (Michael Keaton), they soon grow to hate their new surroundings and
120
+ plan an escape. The film was directed by Lee Unkrich from a script co-authored by
121
+ Little Miss Sunshine scribe Michael Arndt. ~ Perry Seibert, Rovi"
122
+
123
+ toy_story_3.director
124
+ => "Lee Unkrich"
125
+
126
+ toy_story_3.cast
127
+ => "Tom Hanks, Tim Allen, Joan Cusack, Ned Beatty"
128
+
129
+ toy_story_3.genre
130
+ => "Animation"
131
+
132
+ toy_story_3.release_date
133
+ => #<Date: 2010-06-18 ((2455366j,0s,0n),+0s,2299161j)>
134
+
135
+ # Rotten Tomatoes URL
136
+ toy_story_3.rt_url
137
+ => "http://www.rottentomatoes.com/m/toy_story_3/"
138
+
139
+ toy_story_3.imdb_url
140
+ => "http://www.imdb.com/title/tt0435761/"
141
+
142
+ toy_story_3.metacritic_url
143
+ => "http://www.metacritic.com/movie/toy-story-3"
144
+
145
+ # Rotten Tomatoes ID
146
+ toy_story_3.rt_id
147
+ => "770672122"
148
+
149
+ toy_story_3.imdb_id
150
+ => "0435761"
151
+
152
+ toy_story_3.poster
153
+ => "http://cf2.imgobject.com/t/p/original/tOwAAVeL1p3ls9dhOBo45ElodU3.jpg"
50
154
 
51
- # Get a short 5-film list of movies currently on release
52
- recent_movies = movie_aggregator.in_cinemas(5)
155
+ # Get a general summary
156
+ puts toy_story_3.summary
157
+ => "Toy Story 3
158
+ ------------------------------------------------------------
159
+ Released: 18 Jun 2010
160
+ ------------------------------------------------------------
161
+ Pixar returns to their first success with Toy Story 3. The movie begins with Andy
162
+ leaving for college and donating his beloved toys -- including Woody (Tom Hanks)
163
+ and Buzz (Tim Allen) -- to a daycare. While the crew meets new friends,
164
+ including Ken (Michael Keaton), they soon grow to hate their new surroundings
165
+ and plan an escape. The film was directed by Lee Unkrich from a script
166
+ co-authored by Little Miss Sunshine scribe Michael Arndt. ~ Perry Seibert, Rovi
167
+ ------------------------------------------------------------
168
+ Cast: Tom Hanks, Tim Allen, Joan Cusack, Ned Beatty
169
+ ------------------------------------------------------------
170
+ Rotten Tomatoes rating: 99
171
+ IMDB rating: 8.5
172
+ Metacritic rating: 92"
173
+ ```
174
+
175
+ ### Movie reviews
176
+ Sourced from Rotten Tomatoes. ``Movie`` object has an instance variable ``reviews``,
177
+ which is an array of ``WrittenReview`` objects.
178
+
179
+ ```ruby
180
+ # Get the first review
181
+ a_review = toy_story_3.reviews.last
182
+ a_review.author
183
+ => "Ailsa Caine"
184
+
185
+ a_review.date
186
+ => #<Date: 2010-07-22 ((2455400j,0s,0n),+0s,2299161j)>
187
+
188
+ a_review.quote
189
+ => "By [Pixar's] high standards this isn't the best, but by anyone else's, it's close to perfection."
190
+
191
+ # Reviews are those collated by Rotten Tomatoes, where the review scale is binary ("fresh" or "rotten")
192
+ a_review.rating
193
+ => "fresh"
194
+
195
+ # The review's original score (not always available)
196
+ a_review.original_score
197
+ => "4/5"
53
198
 
54
- iron_man = recent_movies.first
199
+ a_review.source
200
+ => "Little White Lies"
55
201
 
56
- iron_man.title
57
- => "Iron Man 3"
202
+ a_review.link
203
+ => "http://www.littlewhitelies.co.uk/theatrical-reviews/toy-story-3/"
58
204
 
59
- critic_review = iron_man.reviews.first
60
- critic_review.quote
61
- => "The trouble is that, as the plot quickens, any cleverness withdraws, to make
62
- way for the firecrackers of the climax. That is not Black's forte, and his
63
- movie duly slumps into a mess."
205
+ # Convenience method to summarise the review as a string
206
+ a_review.to_s
207
+ => "Ailsa Caine wrote on 2010-07-22 : By [Pixar's] high standards this isn't the best, but by anyone else's, it's close to perfection.
208
+ Rating: 4/5"
64
209
  ```
65
210
 
66
- ## Contributing
211
+ ### Aggregating a list of movies
212
+ The Rotten Tomatoes API supports a number of pre-defined lists for both cinema/theater
213
+ releases and DVD releases. For example, if you want to aggregate info for each movie
214
+ on the Box Office list (best performing cinema releases), WorthWatching supports this.
215
+
216
+ Pass the name of the list you would like to process (as a Symbol), the country code
217
+ (ISO 3166-1 alpha-2) of the country you would like info to be localised to (as a Symbol),
218
+ and finally, the maximum number of movies on the list you are interested in.
219
+
220
+ The available lists mirror those available through the Rotten Tomatoes API.
221
+
222
+ They are:
223
+
224
+ - ``:box_office`` - top box office earning movies, sorted by most recent weekend gross
225
+ ticket sales
226
+ - ``:in_theaters`` - movies currently in theaters/cinemas
227
+ - ``:opening`` - current opening movies in the theaters/cinema
228
+ - ``:upcoming`` - upcoming movies in theaters/cinema
229
+ - ``:top_rentals`` - top DVD rentals
230
+ - ``:current_releases`` - current DVD releases
231
+ - ``:new_releases`` - new DVD releases
232
+ - ``:upcoming_dvd`` - upcoming DVD releases
233
+
234
+ **Be careful using this feature! Since WorthWatching will aggregate info for each movie on the list,
235
+ there is the potential to make a significant number of API calls through repeated use.**
236
+
237
+ **The Rotten Tomatoes API
238
+ does have rate limits (as of March 2014: 5 calls a second, 10,000 calls a day)**
239
+
240
+
241
+ ```ruby
242
+
243
+ # Aggregate the top 4 box office movies in the UK
244
+ top_movies = movie_aggregator.aggregate_list(:box_office, :uk, 4)
245
+
246
+ # Or the top 6 releases on DVD in the US
247
+ top_dvds = movie_aggregator.aggregate_list(:top_rentals, :us, 6)
248
+
249
+ # The above list-based methods return an array of Movie objects
250
+ number_1_movie = top_movies.first
251
+
252
+ number_1_movie.title
253
+ => "Captain America: The Winter Soldier"
254
+
255
+ number_1_movie.metacritic_rating
256
+ => 71
257
+ ```
258
+
259
+ ### Why is the returned list empty?
260
+
261
+ This may be because some movies do not have the minimum amount of data available
262
+ in order to aggregate their rating info, and are therefore 'discarded' during the aggregation
263
+ process.
264
+
265
+ If a movie's IMDb ID is not available through the Rotten Tomatoes API, rating info
266
+ cannot be retrieved.
267
+
268
+ During testing I also noticed that movies with no available release date were likely
269
+ to be very obscure and not have any rating info associated with them either. This is
270
+ the other criteria for a movie being discarded.
271
+
272
+ This only tends to happen with very small release independent films, particularly foreign ones.
273
+
274
+ The lists where the above is most likely are ``:upcoming`` and ``:upcoming_dvd``, since they
275
+ contain movies that probably don't have any rating info yet, as they haven't been released.
67
276
 
68
- 1. Fork it
69
- 2. Create your feature branch (`git checkout -b my-new-feature`)
70
- 3. Commit your changes (`git commit -am 'Add some feature'`)
71
- 4. Push to the branch (`git push origin my-new-feature`)
72
- 5. Create new Pull Request
277
+ The opposite is true for lists like ``:box_office`` and ``top_rentals``.
@@ -1,11 +1,13 @@
1
- require 'httparty'
2
1
  require 'nokogiri'
3
2
  require 'open-uri'
3
+ require 'typhoeus'
4
+ require 'json'
4
5
 
5
6
  module WorthWatching
6
7
  class Aggregator
7
8
 
8
9
  attr_accessor :rt_api_key, :tmdb_api_key
10
+ attr_reader :movie
9
11
 
10
12
  RT_API_BASE_URL = 'http://api.rottentomatoes.com/api/public/v1.0'
11
13
  TMDB_API_BASE_URL = 'http://api.themoviedb.org/3'
@@ -17,152 +19,129 @@ module WorthWatching
17
19
  end
18
20
 
19
21
  # Retrieve the details of a specific movie using its IMDB ID
22
+ #
20
23
  # @param rt_id [String] the Rotten Tomatoes ID of the movie
21
24
  # @return [Movie] a Movie object representing the movie
22
- def movie_info(rt_id)
23
- uri = "#{RT_API_BASE_URL}/movies/#{rt_id}.json?apikey=#{rt_api_key}"
24
- movie_hash = HTTParty.get(uri)
25
+ def aggregate_movie(rt_id)
26
+ uri = "#{RT_API_BASE_URL}/movies/#{rt_id}.json?apikey=#{@rt_api_key}"
27
+ movie_hash = JSON.parse(Typhoeus.get(uri).body)
25
28
 
26
- aggregate(Movie.new(movie_hash))
29
+ @movie = Movie.new(movie_hash)
30
+ aggregate
27
31
  end
28
32
 
29
- # Retrieve a list of movies that are currently in cinemas
30
- # @param result_limit [Integer] the maximum number of results to return
31
- # @return [Array] an Array of Movie objects
32
- def in_cinemas(result_limit, type)
33
-
34
- case type
35
- when :cinema
36
- uri = "#{RT_API_BASE_URL}/lists/movies/in_theaters.json?page_limit=#{result_limit}"\
37
- "&page=1&country=uk&apikey=#{rt_api_key}"
38
- when :dvd
39
- uri = "#{RT_API_BASE_URL}/lists/dvds/top_rentals.json?page_limit=#{result_limit}"\
40
- "&page=1&country=uk&apikey=#{rt_api_key}"
33
+ # Retrieve a list of movies, then aggregate info for each one
34
+ #
35
+ # @param list_name[Symbol] the name of the Rotten Tomato list. Possible values: :box_office,
36
+ # :in_theaters, :opening, :upcoming, :top_rentals, :current_releases, :new_releases, :upcoming_dvd
37
+ # @param country [Symbol] Localised data for the selected country (ISO 3166-1 alpha-2)
38
+ # @param result_limit [Integer] the max number of movies to return in the list
39
+ # @return [Array] an array of Movie objects
40
+ def aggregate_list(list_name, country, result_limit)
41
+ case list_name
42
+
43
+ # Build the appropriate URI based on the list name.
44
+ # Some enpoints use 'limit' to specify max results to return, some use 'page_limit'.
45
+ # Pass both to make the code simpler
46
+ when :box_office, :in_theaters, :opening, :upcoming
47
+ uri = "#{RT_API_BASE_URL}/lists/movies/#{list_name.to_s}.json?limit=#{result_limit}"\
48
+ "&page_limit=#{result_limit}&page=1&country=#{country.to_s}&apikey=#{@rt_api_key}"
49
+ when :top_rentals, :current_releases, :new_releases, :upcoming_dvd
50
+
51
+ # The API endpoint uses 'upcoming' for both DVD and cinema releases
52
+ # Need to avoid this clash by using ':upcoming_dvd' as possible method param,
53
+ # but change back when building the URI
54
+ list_name = :upcoming if list_name == :upcoming_dvd
55
+ uri = "#{RT_API_BASE_URL}/lists/dvds/#{list_name.to_s}.json?limit=#{result_limit}"\
56
+ "&page_limit=#{result_limit}&page=1&country=#{country.to_s}&apikey=#{@rt_api_key}"
41
57
  end
42
58
 
43
- movie_list = HTTParty.get(uri)
44
- movie_list = movie_list["movies"]
45
- in_theaters = []
46
-
47
- movie_list.each do |movie|
48
- if enough_info?(movie)
49
- movie = movie_info(movie['id'])
50
- in_theaters << movie
51
- end
52
- end
53
- Aggregator.clean_up(in_theaters)
54
- return in_theaters
59
+ get_movie_list(uri)
55
60
  end
56
61
 
57
- # Aggregates exta information about a movie that cannot be derived directly from the
58
- # Rotten Tomatoes API e.g IMDb/Metacritic rating, HQ posters
59
- # @param movie [Movie] the movie to aggregate information for
60
- # @return [Movie] the movie passed in with aggregated info completed
61
- def aggregate(movie)
62
- extra_info = get_extra_info_via_omdb(movie.imdb_id)
62
+ # Search for movies using a query string. Returns a max of 4 results
63
+ #
64
+ # @param movie_title [String] the title of the movie to search for
65
+ # @param result_limit [Integer] the max number of results to return
66
+ # @return [Array, false] an array containing hashes represting each movie in the search results, or
67
+ # false if no results are found.
68
+ def search_by_title(movie_title, result_limit)
69
+ uri = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=#{@rt_api_key}&q=#{CGI.escape(movie_title)}&page_limit=#{result_limit}"
63
70
 
64
- movie.imdb_rating = extra_info[:imdb_rating]
65
- movie.metacritic_rating = extra_info[:metacritic_rating]
66
- movie.metacritic_url = extra_info[:metacritic_url]
71
+ response = JSON.parse(Typhoeus.get(uri).body)
67
72
 
68
- movie.poster = get_poster(movie.imdb_id)
69
- movie.reviews = get_reviews(movie.rt_id)
70
-
71
- return movie
73
+ if response["total"] == 0
74
+ return false
75
+ else
76
+ # Build the array of movie serach results. Have to use a regexp to extract the Rotten Tomatoes
77
+ # ID from the movie link since the API does not return it directly.
78
+ return response["movies"].inject([]) do |movie_list, movie|
79
+ movie_list << { :title => movie["title"], :rt_id => movie["links"]["self"].match(/\/[0-9]+\./).to_s.gsub(/[\/\.]/, ""), :year => movie["year"].to_s }
80
+ movie_list
81
+ end
82
+ end
72
83
  end
73
84
 
74
85
  private
75
86
 
76
- # Retrieves extra info about a particular movie that cannot be found using
77
- # the Rotten Tomatoes API. All facilitated by its IMDb ID.
78
- # @params imdb_id [String] the IMDb ID of the required movie (without 'tt' prefixed)
79
- # @return [Hash] a hash containing IMDb rating, Metacritic rating and movie URL
80
- def get_extra_info(imdb_id)
81
- imdb_url = "http://m.imdb.com/title/tt#{imdb_id}"
82
-
83
- imdb_page = Nokogiri::HTML(open(imdb_url))
84
- extra_info = {}
85
-
86
- # Extract IMDB rating
87
- extra_info[:imdb_rating] = imdb_page.css('.votes strong').text
88
-
89
- # Extract Metacritic rating (IMDB has a page listing MC reviews)
90
- imdb_mc_page = Nokogiri::HTML(open("http://www.imdb.com/title/tt#{imdb_id}/criticreviews"))
91
-
92
- mc_rating = imdb_mc_page.css(".metascore > span").text
93
-
94
- if mc_rating != ""
95
- extra_info[:metacritic_rating] = mc_rating
96
- extra_info[:metacritic_url] = imdb_mc_page.css(".see-more .offsite-link")[0]["href"]
97
- else
98
- extra_info[:metacritic_rating] = "No Rating"
99
- extra_info[:metacritic_url] = "No URL"
100
- end
101
-
102
- return extra_info
87
+ # Aggregates extra info about @movie that cannot be derived directly from the
88
+ # Rotten Tomatoes API e.g IMDb/Metacritic rating, HQ posters
89
+ #
90
+ # @return [Movie] the movie with aggregated info completed
91
+ def aggregate
92
+ retrieve_imdb_info
93
+ retrieve_metacritic_info
94
+ get_poster
95
+ get_reviews
96
+ return @movie
103
97
  end
104
98
 
105
- def get_extra_info_via_omdb(imdb_id)
106
- extra_info = {}
107
- omdb_response = HTTParty.get("http://www.omdbapi.com/?i=tt#{imdb_id}")
99
+ # Retrieves and updates the current movie's IMDb rating
100
+ def retrieve_imdb_info
101
+ omdb_response = JSON.parse(Typhoeus.get("http://www.omdbapi.com/?i=tt#{@movie.imdb_id}").body)
108
102
 
109
103
  if omdb_response["Response"] == "True"
110
- imdb_rating = omdb_response["imdbRating"]
111
- movie_title = omdb_response["Title"]
112
-
113
- mc_info = scrape_metacritic_info(movie_title)
114
-
115
- mc_rating = mc_info[:mc_rating]
116
- mc_link = mc_info[:mc_url]
117
- else
118
- imdb_rating = "Unavailable"
119
- end
120
-
121
- # Extract IMDB rating
122
- extra_info[:imdb_rating] = imdb_rating
123
-
124
- if mc_rating != ""
125
- extra_info[:metacritic_rating] = mc_rating
126
- extra_info[:metacritic_url] = mc_link
104
+ @movie.imdb_rating = omdb_response["imdbRating"]
127
105
  else
128
- extra_info[:metacritic_rating] = "Unavailable"
129
- extra_info[:metacritic_url] = "No URL"
106
+ @movie.imdb_rating = "Unavailable"
130
107
  end
131
-
132
- return extra_info
133
108
  end
134
109
 
135
- # Scrapes the metacritic rating and URL, returning a hash containing the info
136
- def scrape_metacritic_info(movie_title)
137
- mc_info = {}
110
+ # Retrieves and updates the current movie's Metacritic rating and URL
111
+ def retrieve_metacritic_info
112
+ metacritic_page = Nokogiri::HTML(open("http://www.metacritic.com/search/"\
113
+ "movie/#{CGI.escape(@movie.title)}/results"))
138
114
 
139
- # Extract Metacritic rating (IMDB has a page listing MC reviews)
140
- metacritic_page = Nokogiri::HTML(open("http://www.metacritic.com/search/"\
141
- "movie/#{CGI.escape(movie_title)}/results"))
142
- mc_info[:mc_rating] = metacritic_page.css('.first_result .metascore_w').text
143
- mc_info[:mc_url] = "http://www.metacritic.com#{metacritic_page.at_css('.first_result a').attr(:href)}"
115
+ scraped_rating = metacritic_page.css('.first_result .metascore_w').text
116
+ metacritic_url = "http://www.metacritic.com#{metacritic_page.at_css('.first_result a').attr(:href)}"
144
117
 
145
- return mc_info
118
+ # If attempt to scrape results in empty string, info must not be available
119
+ if scraped_rating == ""
120
+ scraped_rating = "No Rating"
121
+ metacritic_url = "No URL"
122
+ end
123
+
124
+ @movie.metacritic_rating = scraped_rating
125
+ @movie.metacritic_url = metacritic_url
146
126
  end
147
127
 
148
- # Retrieves the URL of a high resolution poster of a movie
149
- # @params imdb_id [String] the IMDb ID of the required movie (without 'tt' prefixed)
150
- # @return [String] the URL of the poster as a string
151
- def get_poster(imdb_id)
152
- uri = "#{TMDB_API_BASE_URL}/movie/tt#{imdb_id}?api_key=#{tmdb_api_key}"
153
- movie_info = HTTParty.get(uri, :headers => { 'Accept' => 'application/json'})
128
+ # Updates the current movie's high resolution poster URL
129
+ def get_poster
130
+ uri = "#{TMDB_API_BASE_URL}/movie/tt#{@movie.imdb_id}?api_key=#{tmdb_api_key}"
131
+ movie_info = JSON.parse(Typhoeus.get(uri).body)
154
132
 
155
133
  if movie_info.has_key?("poster_path")
156
- "http://cf2.imgobject.com/t/p/original" + movie_info["poster_path"]
134
+ @movie.poster = "http://cf2.imgobject.com/t/p/original" + movie_info["poster_path"]
157
135
  else
158
- "No poster available"
136
+ @movie.poster = "No poster available"
159
137
  end
160
138
  end
161
139
 
162
- def get_reviews(rt_id)
163
- uri = "#{RT_API_BASE_URL}/movies/#{rt_id}/reviews.json?review_type=top_critic"\
164
- "&page_limit=5&page=1&country=uk&apikey=#{rt_api_key}"
165
- review_hash = HTTParty.get(uri)
140
+ # Retrieves and updates the current movie's reviews
141
+ def get_reviews
142
+ uri = "#{RT_API_BASE_URL}/movies/#{@movie.rt_id}/reviews.json?review_type=top_critic"\
143
+ "&page_limit=5&page=1&country=uk&apikey=#{@rt_api_key}"
144
+ review_hash = JSON.parse(Typhoeus.get(uri).body)
166
145
 
167
146
  review_list = []
168
147
 
@@ -170,11 +149,12 @@ module WorthWatching
170
149
  review_list << WrittenReview.new(review)
171
150
  end
172
151
 
173
- return review_list
152
+ @movie.reviews = review_list
174
153
  end
175
154
 
176
155
  # Checks that a given movie has enough information available via API to aggregate
177
156
  # data. It MUST have an IMDb id and a release date.
157
+ #
178
158
  # @param [Hash] the hash representation of the movie to check
179
159
  # @return [Boolean] whether the movie has a theater release date and IMDb ID
180
160
  def enough_info?(movie)
@@ -197,13 +177,21 @@ module WorthWatching
197
177
  return has_release_date && has_imdb_id
198
178
  end
199
179
 
200
- # Removes movies from an array that do no have the required rating information
201
- # @param movie_list [Array] the list to clean up
202
- # @return [Array] the pruned list of movies
203
- def self.clean_up(movie_list)
204
- movie_list.delete_if do |movie|
205
- movie.metacritic_rating == "No Rating"
206
- end
180
+ # Retrieves a list of movies from the Rotten Tomatoes API, then aggregates
181
+ # info for each one
182
+ #
183
+ # @param uri [String] the Rotten Tomatoes API endpoint for the list
184
+ # @return [Array] an array of Movie objects
185
+ def get_movie_list(uri)
186
+ response = JSON.parse(Typhoeus.get(uri).body)
187
+ movie_list_response = response["movies"]
188
+
189
+ movie_list = movie_list_response.inject([]) do |list, movie|
190
+ list << aggregate_movie(movie['id']) if enough_info?(movie)
191
+ list
192
+ end
193
+
194
+ return movie_list
207
195
  end
208
196
  end
209
197
  end