billboard 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.
data/History ADDED
@@ -0,0 +1 @@
1
+ 0.1.0 - initial release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Wynn Netherland
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,37 @@
1
+ # billboard
2
+
3
+ Ruby wrapper for the Billboard charts API. Great for cheating at trivia games.
4
+
5
+ ## Installation
6
+
7
+ sudo gem install billboard
8
+
9
+ ## Usage
10
+
11
+ api_key = 'OU812' # get yours at http://developer.billboard.com/apps/register
12
+ client = Billboard::Client.new(api_key)
13
+
14
+ ### Find a chart by type
15
+
16
+ charts = client.chart_specs(:type => 'Videos').charts
17
+
18
+ ### Find items on a chart
19
+
20
+ items = client.search(:id => charts.last.id).chart_items
21
+ items.last.song = "Lost: The Complete Third Season"
22
+ items.last.weeks_on = 21
23
+
24
+ ## Note on Patches/Pull Requests
25
+
26
+ * Fork the project.
27
+ * Make your feature addition or bug fix.
28
+ * Add tests for it. This is important so I don't break it in a
29
+ future version unintentionally.
30
+ * Commit, do not mess with rakefile, version, or history.
31
+ (if you want to have your own version, that is fine but
32
+ bump version in a commit by itself I can ignore when I pull)
33
+ * Send me a pull request. Bonus points for topic branches.
34
+
35
+ ## Copyright
36
+
37
+ Copyright (c) 2009 Wynn Netherland. See LICENSE for details.
@@ -0,0 +1,91 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "billboard"
8
+ gem.summary = %Q{Ruby wrapper for the Billboard charts API}
9
+ gem.description = %Q{Great for cheating at trivia games}
10
+ gem.email = "wynn@squeejee.com"
11
+ gem.homepage = "http://github.com/pengwynn/billboard"
12
+ gem.authors = ["Wynn Netherland"]
13
+ gem.rubyforge_project = "billboard"
14
+ gem.files = FileList["[A-Z]*", "{examples,lib,test}/**/*"]
15
+
16
+ gem.add_dependency('mash', '0.0.3')
17
+ gem.add_dependency('httparty', '0.4.3')
18
+
19
+ gem.add_development_dependency('thoughtbot-shoulda')
20
+ gem.add_development_dependency('jeremymcanally-matchy')
21
+ gem.add_development_dependency('mocha')
22
+ gem.add_development_dependency('fakeweb')
23
+ gem.add_development_dependency('mash')
24
+ end
25
+
26
+ rescue LoadError
27
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
28
+ end
29
+
30
+ require 'rake/testtask'
31
+ Rake::TestTask.new(:test) do |test|
32
+ test.libs << 'lib' << 'test'
33
+ test.pattern = 'test/**/*_test.rb'
34
+ test.verbose = true
35
+ end
36
+
37
+ begin
38
+ require 'rcov/rcovtask'
39
+ Rcov::RcovTask.new do |test|
40
+ test.libs << 'test'
41
+ test.pattern = 'test/**/*_test.rb'
42
+ test.verbose = true
43
+ end
44
+ rescue LoadError
45
+ task :rcov do
46
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
47
+ end
48
+ end
49
+
50
+ task :default => :test
51
+
52
+ require 'rake/rdoctask'
53
+ Rake::RDocTask.new do |rdoc|
54
+ if File.exist?('VERSION.yml')
55
+ config = YAML.load(File.read('VERSION.yml'))
56
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
57
+ else
58
+ version = ""
59
+ end
60
+
61
+ rdoc.rdoc_dir = 'rdoc'
62
+ rdoc.title = "billboard #{version}"
63
+ rdoc.rdoc_files.include('README*')
64
+ rdoc.rdoc_files.include('lib/**/*.rb')
65
+ end
66
+
67
+ begin
68
+ require 'rake/contrib/sshpublisher'
69
+ namespace :rubyforge do
70
+
71
+ desc "Release gem and RDoc documentation to RubyForge"
72
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
73
+
74
+ namespace :release do
75
+ desc "Publish RDoc to RubyForge."
76
+ task :docs => [:rdoc] do
77
+ config = YAML.load(
78
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
79
+ )
80
+
81
+ host = "#{config['username']}@rubyforge.org"
82
+ remote_dir = "/var/www/gforge-projects/remixr/rdoc"
83
+ local_dir = 'rdoc'
84
+
85
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
86
+ end
87
+ end
88
+ end
89
+ rescue LoadError
90
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
91
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 0
4
+ :minor: 1
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+
3
+ gem 'mash', '0.0.3'
4
+ require 'mash'
5
+
6
+ gem 'httparty', '0.4.3'
7
+ require 'httparty'
8
+
9
+ gem 'activesupport', '~> 2.3.2'
10
+ require 'activesupport'
11
+
12
+ class APIKeyNotSet < StandardError; end
13
+
14
+ module Billboard
15
+
16
+ # Get your API key from http://developer.billboard.com/apps/register
17
+ def self.api_key
18
+ raise APIKeyNotSet if @api_key.nil?
19
+
20
+ @api_key
21
+ end
22
+
23
+ def self.api_key=(api_key)
24
+ @api_key = api_key
25
+ end
26
+
27
+ end
28
+
29
+ class Hash
30
+
31
+ # Converts all of the keys to strings, optionally formatting key name
32
+ def rubyify_keys!
33
+ keys.each{|k|
34
+ v = delete(k)
35
+ new_key = k.to_s.underscore
36
+ self[new_key] = v
37
+ v.rubyify_keys! if v.is_a?(Hash)
38
+ v.each{|p| p.rubyify_keys! if p.is_a?(Hash)} if v.is_a?(Array)
39
+ }
40
+ self
41
+ end
42
+
43
+ end
44
+
45
+ directory = File.expand_path(File.dirname(__FILE__))
46
+
47
+ require File.join(directory, 'billboard', 'client')
@@ -0,0 +1,85 @@
1
+ module Billboard
2
+ class Client
3
+ include HTTParty
4
+ base_uri 'api.billboard.com/apisvc/chart/v1'
5
+ format :json
6
+
7
+ attr_reader :api_key
8
+
9
+ # Get your api_key found here http://developer.billboard.com/apps/register
10
+ def initialize(api_key=nil)
11
+ @api_key = api_key
12
+ @api_key ||= Billboard.api_key
13
+
14
+ @api_path = ''
15
+
16
+ end
17
+
18
+ # Use this resource to search Billboard data for chart items by
19
+ # id, by date, by artist, or by song.
20
+ #
21
+ # Parameters:
22
+ #
23
+ # id string(optional) Chart spec(format) id - this can be retrieved by spec service
24
+ # start_date string(optional) Chart issue date range start
25
+ # end_date string(optional) Chart issue date range end
26
+ # artist string(optional) Artist name to search
27
+ # song string(optional) Song name to search
28
+ #
29
+ # start default: 1 Start position of raw ResultSet
30
+ # count default: 50 number of data might be returned. Maximum 50
31
+ # sort default: date-, name+ Sort order desired, with "+" or "-" suffix to indicate ascending or descending. For example, date+
32
+ #
33
+ def search(query={})
34
+ results = Mash.new(self.class.get('/list', :query => scrub_query(query))['searchResults']).rubyify_keys!
35
+ results.chart_items = results.delete('chart_item')
36
+ results.chart_items = [] if results.chart_items.nil?
37
+ results
38
+ end
39
+
40
+
41
+ # Get chart data based on chart ID
42
+ #
43
+ # Parameters
44
+ #
45
+ # id String
46
+ #
47
+ def chart(id, query={})
48
+ chart = Mash.new(self.class.get('/item', :query => {:id => id}.merge(query).merge(self.default_options))).chart
49
+ chart.rubyify_keys!
50
+ chart.chart_items.items = chart.chart_items.delete('chart_item')
51
+ chart
52
+ end
53
+
54
+ # This resource returns data on the different chart names
55
+ # and chart types.
56
+ #
57
+ # The API orders the results ascending by ChartSpecId.
58
+ #
59
+ # Parameters
60
+ #
61
+ # name string(optional) chart name, for example: The Billboard Hot 100
62
+ # type string(optional) chart type, for example: Singles
63
+ #
64
+ def chart_specs(query={})
65
+ results = Mash.new(self.class.get('/list/spec', :query => query.merge(self.default_options))['chartSpecs'])
66
+ results.rubyify_keys!
67
+ results.charts = results.delete('chart_spec')
68
+ results
69
+ end
70
+
71
+ protected
72
+
73
+ def default_options
74
+ {:api_key => @api_key, :format => 'json'}
75
+ end
76
+
77
+ def scrub_query(query)
78
+ query[:sdate] = query[:start_date] unless query[:start_date].blank?
79
+ query[:edate] = query[:end_date] unless query[:end_date].blank?
80
+ query[:sort] = query[:sort].gsub('+', ' ') unless query[:sort].blank?
81
+ query.merge(self.default_options)
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ClientTest < Test::Unit::TestCase
4
+ include Billboard
5
+
6
+ context "Hitting the Billboard API" do
7
+ setup { @client = Billboard::Client.new('OU812') }
8
+
9
+ should "find chart data based on chart id" do
10
+ stub_get 'http://api.billboard.com/apisvc/chart/v1/item?id=3064446&format=json&api_key=OU812', 'chart.json'
11
+ chart = @client.chart(3064446)
12
+ chart.description.should == 'Chart'
13
+ chart.chart_items.items.size.should == 10
14
+ chart.chart_items.items.last.artist_name.should == 'Sade'
15
+ end
16
+
17
+ should "find chart data based on artist name and date range" do
18
+ stub_get 'http://api.billboard.com/apisvc/chart/v1/list?end_date=1975-12-31&format=json&sdate=1975-01-01&artist=Waylon%20Jennings&sort=date%20&edate=1975-12-31&start_date=1975-01-01&api_key=OU812', 'artist_search_with_date_range.json'
19
+ results = @client.search(:artist => 'Waylon Jennings', :start_date => '1975-01-01', :end_date => '1975-12-31', :sort => 'date+')
20
+ results.total_records.should == 927
21
+ results.chart_items.size.should == 50
22
+ results.chart_items.last.song.should == "Sweet Dream Woman"
23
+ results.chart_items.last.weeks_on.should == 13
24
+ end
25
+
26
+ should "find album charts" do
27
+ stub_get 'http://api.billboard.com/apisvc/chart/v1/list/spec?type=album&api_key=OU812&format=json', 'album_charts.json'
28
+ results = @client.chart_specs(:type => 'album')
29
+ results.total_records.should == 589
30
+ results.total_returned.should == 50
31
+ results.charts.last.name.should == 'Latin Rhythm Albums'
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,257 @@
1
+ {
2
+ "chartSpecs": {
3
+ "firstPosition": 1,
4
+ "totalReturned": 50,
5
+ "chartSpec": [{
6
+ "type": "Albums",
7
+ "name": "Billboard Comprehensive Albums",
8
+ "id": 292
9
+ },
10
+ {
11
+ "type": "Albums",
12
+ "name": "European Top 100 Albums",
13
+ "id": 293
14
+ },
15
+ {
16
+ "type": "Albums",
17
+ "name": "Heatseekers",
18
+ "id": 294
19
+ },
20
+ {
21
+ "type": "Albums",
22
+ "name": "Latin Pop Albums",
23
+ "id": 295
24
+ },
25
+ {
26
+ "type": "Albums",
27
+ "name": "Top Heatseekers (East North Central)",
28
+ "id": 296
29
+ },
30
+ {
31
+ "type": "Albums",
32
+ "name": "Top Heatseekers (Middle Atlantic)",
33
+ "id": 297
34
+ },
35
+ {
36
+ "type": "Albums",
37
+ "name": "Top Heatseekers (Mountain)",
38
+ "id": 298
39
+ },
40
+ {
41
+ "type": "Albums",
42
+ "name": "Top Heatseekers (Northeast)",
43
+ "id": 299
44
+ },
45
+ {
46
+ "type": "Albums",
47
+ "name": "Top Heatseekers (Pacific)",
48
+ "id": 300
49
+ },
50
+ {
51
+ "type": "Albums",
52
+ "name": "Top Heatseekers (South Atlantic)",
53
+ "id": 301
54
+ },
55
+ {
56
+ "type": "Albums",
57
+ "name": "Top Heatseekers (South Central)",
58
+ "id": 302
59
+ },
60
+ {
61
+ "type": "Albums",
62
+ "name": "Top Heatseekers (West North Central)",
63
+ "id": 303
64
+ },
65
+ {
66
+ "type": "Albums",
67
+ "name": "Regional Mexican Albums",
68
+ "id": 304
69
+ },
70
+ {
71
+ "type": "Albums",
72
+ "name": "The Billboard 200",
73
+ "id": 305
74
+ },
75
+ {
76
+ "type": "Albums",
77
+ "name": "The Billboard Classical 50",
78
+ "id": 306
79
+ },
80
+ {
81
+ "type": "Albums",
82
+ "name": "Top Bluegrass Albums",
83
+ "id": 307
84
+ },
85
+ {
86
+ "type": "Albums",
87
+ "name": "Top Blues Albums",
88
+ "id": 308
89
+ },
90
+ {
91
+ "type": "Albums",
92
+ "name": "Top Canadian Albums",
93
+ "id": 309
94
+ },
95
+ {
96
+ "type": "Albums",
97
+ "name": "Top Christian Albums",
98
+ "id": 310
99
+ },
100
+ {
101
+ "type": "Albums",
102
+ "name": "Top Classical Albums",
103
+ "id": 311
104
+ },
105
+ {
106
+ "type": "Albums",
107
+ "name": "Top Classical Budget Albums",
108
+ "id": 312
109
+ },
110
+ {
111
+ "type": "Albums",
112
+ "name": "Top Classical Crossover Albums",
113
+ "id": 313
114
+ },
115
+ {
116
+ "type": "Albums",
117
+ "name": "Top Classical Midline Albums",
118
+ "id": 314
119
+ },
120
+ {
121
+ "type": "Albums",
122
+ "name": "Top Comedy Albums",
123
+ "id": 315
124
+ },
125
+ {
126
+ "type": "Albums",
127
+ "name": "Top Compilation Albums",
128
+ "id": 316
129
+ },
130
+ {
131
+ "type": "Albums",
132
+ "name": "Top Contemporary Christian",
133
+ "id": 317
134
+ },
135
+ {
136
+ "type": "Albums",
137
+ "name": "Top Contemporary Jazz",
138
+ "id": 318
139
+ },
140
+ {
141
+ "type": "Albums",
142
+ "name": "Top Contemporary Jazz Albums",
143
+ "id": 319
144
+ },
145
+ {
146
+ "type": "Albums",
147
+ "name": "Top Country Albums",
148
+ "id": 320
149
+ },
150
+ {
151
+ "type": "Albums",
152
+ "name": "Top Country Catalog Albums",
153
+ "id": 321
154
+ },
155
+ {
156
+ "type": "Albums",
157
+ "name": "Top Electronic Albums",
158
+ "id": 322
159
+ },
160
+ {
161
+ "type": "Albums",
162
+ "name": "Top Gospel Albums",
163
+ "id": 323
164
+ },
165
+ {
166
+ "type": "Albums",
167
+ "name": "Top Heatseekers",
168
+ "id": 324
169
+ },
170
+ {
171
+ "type": "Albums",
172
+ "name": "Top Holiday Albums",
173
+ "id": 325
174
+ },
175
+ {
176
+ "type": "Albums",
177
+ "name": "Top Independent Albums",
178
+ "id": 326
179
+ },
180
+ {
181
+ "type": "Albums",
182
+ "name": "Top Internet Albums",
183
+ "id": 327
184
+ },
185
+ {
186
+ "type": "Albums",
187
+ "name": "Top Jazz Albums",
188
+ "id": 328
189
+ },
190
+ {
191
+ "type": "Albums",
192
+ "name": "Top Kid Audio",
193
+ "id": 329
194
+ },
195
+ {
196
+ "type": "Albums",
197
+ "name": "Top Latin Albums",
198
+ "id": 330
199
+ },
200
+ {
201
+ "type": "Albums",
202
+ "name": "Top New Age Albums",
203
+ "id": 331
204
+ },
205
+ {
206
+ "type": "Albums",
207
+ "name": "Top Pop Catalog",
208
+ "id": 332
209
+ },
210
+ {
211
+ "type": "Albums",
212
+ "name": "Top R&B\/Hip-Hop Albums",
213
+ "id": 333
214
+ },
215
+ {
216
+ "type": "Albums",
217
+ "name": "Top R&B\/Hip-Hop Catalog Albums",
218
+ "id": 334
219
+ },
220
+ {
221
+ "type": "Albums",
222
+ "name": "Top Rap Albums",
223
+ "id": 335
224
+ },
225
+ {
226
+ "type": "Albums",
227
+ "name": "Top Reggae Albums",
228
+ "id": 336
229
+ },
230
+ {
231
+ "type": "Albums",
232
+ "name": "Top Soundtracks",
233
+ "id": 337
234
+ },
235
+ {
236
+ "type": "Albums",
237
+ "name": "Latin Tropical Albums",
238
+ "id": 338
239
+ },
240
+ {
241
+ "type": "Albums",
242
+ "name": "Top World Albums",
243
+ "id": 339
244
+ },
245
+ {
246
+ "type": "Albums",
247
+ "name": "Tropical\/Salsa",
248
+ "id": 340
249
+ },
250
+ {
251
+ "type": "Albums",
252
+ "name": "Latin Rhythm Albums",
253
+ "id": 399
254
+ }],
255
+ "totalRecords": 589
256
+ }
257
+ }