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 +4 -4
- data/.gitignore +3 -1
- data/README.md +233 -28
- data/lib/worth_watching/aggregator.rb +110 -122
- data/lib/worth_watching/movie.rb +20 -1
- data/lib/worth_watching/version.rb +1 -1
- data/lib/worth_watching/written_review.rb +12 -5
- data/spec/support/json_responses/0_movie_search_result.json +1 -0
- data/spec/support/json_responses/1_movie_search_result.json +1 -0
- data/spec/support/json_responses/3_movie_search_result.json +1 -0
- data/spec/support/json_responses/rt_top_16_dvd_rentals.json +0 -33
- data/spec/support/json_responses/rt_top_16_in_cinemas.json +0 -33
- data/spec/support/json_responses/toy_story_reviews_rt.json +0 -34
- data/spec/unit/aggregator_spec.rb +57 -6
- data/spec/unit/movie_spec.rb +12 -1
- data/spec/unit/written_review_spec.rb +52 -0
- data/worth_watching.gemspec +3 -3
- metadata +13 -6
- data/config/example_config.yml +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 048abc5a75b5f585a50481cab76c699ec622a4a6
|
4
|
+
data.tar.gz: 7ed6a1134722d026b11ee25d54db2338a7c19e1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5903062650b35280dd7373b4ea9c8079936809ca8f554f92282599eac15dd8db00d20108021123c634fd8f14cd0b99432de91e42d0455b9f364fb7ffcba8ef09
|
7
|
+
data.tar.gz: 983f743ff6b0dd3e0ad3b640ea09c7874fca898305d3356b18249419e06f6d9eb2509566a4db123239e28725300d3fa9a5560ecdb95c4cdf4784100c6c73e679
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,43 @@
|
|
1
|
-
|
1
|
+
## WorthWatching
|
2
2
|
|
3
|
-
WorthWatching is a gem that
|
3
|
+
WorthWatching is a gem that aggregates movie review data from a
|
4
4
|
number of different sources.
|
5
5
|
|
6
|
-
|
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
|
-
|
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
|
-
#
|
35
|
-
toy_story_3 = movie_aggregator.
|
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
|
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
|
-
=>
|
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
|
52
|
-
|
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
|
-
|
199
|
+
a_review.source
|
200
|
+
=> "Little White Lies"
|
55
201
|
|
56
|
-
|
57
|
-
=> "
|
202
|
+
a_review.link
|
203
|
+
=> "http://www.littlewhitelies.co.uk/theatrical-reviews/toy-story-3/"
|
58
204
|
|
59
|
-
|
60
|
-
|
61
|
-
=> "
|
62
|
-
|
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
|
-
|
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
|
-
|
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
|
23
|
-
uri = "#{RT_API_BASE_URL}/movies/#{rt_id}.json?apikey=#{rt_api_key}"
|
24
|
-
movie_hash =
|
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
|
-
|
29
|
+
@movie = Movie.new(movie_hash)
|
30
|
+
aggregate
|
27
31
|
end
|
28
32
|
|
29
|
-
# Retrieve a list of movies
|
30
|
-
#
|
31
|
-
# @
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
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
|
-
#
|
58
|
-
#
|
59
|
-
# @param
|
60
|
-
# @
|
61
|
-
|
62
|
-
|
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
|
-
|
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
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
# @return [
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
106
|
-
|
107
|
-
omdb_response =
|
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
|
-
|
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
|
-
#
|
136
|
-
def
|
137
|
-
|
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
|
-
|
140
|
-
|
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
|
-
|
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
|
-
#
|
149
|
-
|
150
|
-
|
151
|
-
|
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
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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
|
-
|
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
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
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
|