gingerhendrix-scrobbler2 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README +5 -0
- data/Rakefile +8 -0
- data/VERSION.yml +4 -0
- data/generators/acceptance_test/USAGE +9 -0
- data/generators/acceptance_test/acceptance_test_generator.rb +57 -0
- data/generators/acceptance_test/templates/acceptance_test.rb.erb +14 -0
- data/generators/resource/USAGE +8 -0
- data/generators/resource/resource_generator.rb +47 -0
- data/generators/resource/templates/resource.rb.erb +11 -0
- data/generators/resource/templates/spec.rb.erb +22 -0
- data/lib/scrobbler2.rb +23 -0
- data/lib/scrobbler2/album.rb +11 -0
- data/lib/scrobbler2/artist.rb +29 -0
- data/lib/scrobbler2/auth.rb +19 -0
- data/lib/scrobbler2/base.rb +73 -0
- data/lib/scrobbler2/event.rb +12 -0
- data/lib/scrobbler2/geo.rb +15 -0
- data/lib/scrobbler2/group.rb +14 -0
- data/lib/scrobbler2/library.rb +12 -0
- data/lib/scrobbler2/playlist.rb +10 -0
- data/lib/scrobbler2/tag.rb +17 -0
- data/lib/scrobbler2/track.rb +13 -0
- data/lib/scrobbler2/user.rb +29 -0
- data/lib/scrobbler2/venue.rb +12 -0
- data/test/acceptance/album/info_test.rb +56 -0
- data/test/acceptance/artist/add_tags_test.rb +14 -0
- data/test/acceptance/artist/events_test.rb +47 -0
- data/test/acceptance/artist/info_test.rb +53 -0
- data/test/acceptance/artist/shouts_test.rb +48 -0
- data/test/acceptance/artist/similar_artists_test.rb +20 -0
- data/test/acceptance/artist/tags_test.rb +24 -0
- data/test/acceptance/artist/top_albums_test.rb +34 -0
- data/test/acceptance/artist/top_fans.rb +19 -0
- data/test/acceptance/artist/top_tags.rb +18 -0
- data/test/acceptance/artist/top_tracks.rb +47 -0
- data/test/acceptance/auth/auth_test.rb +21 -0
- data/test/acceptance/event/info_test.rb +66 -0
- data/test/acceptance/event/shouts_test.rb +49 -0
- data/test/acceptance/geo/events_test.rb +14 -0
- data/test/acceptance/geo/top_artists_test.rb +16 -0
- data/test/acceptance/geo/top_tracks_test.rb +16 -0
- data/test/acceptance/group/members_test.rb +60 -0
- data/test/acceptance/group/weekly_album_chart_test.rb +61 -0
- data/test/acceptance/group/weekly_artist_chart_test.rb +54 -0
- data/test/acceptance/group/weekly_chart_list_test.rb +39 -0
- data/test/acceptance/group/weekly_track_chart_test.rb +61 -0
- data/test/acceptance/library/albums_test.rb +34 -0
- data/test/acceptance/library/artists_test.rb +33 -0
- data/test/acceptance/library/tracks_test.rb +33 -0
- data/test/acceptance/playlist/fetch_test.rb +68 -0
- data/test/acceptance/shared/album.rb +41 -0
- data/test/acceptance/shared/artist.rb +16 -0
- data/test/acceptance/shared/paged_result.rb +16 -0
- data/test/acceptance/shared/top_fans.rb +29 -0
- data/test/acceptance/shared/top_tags.rb +23 -0
- data/test/acceptance/shared/track.rb +23 -0
- data/test/acceptance/tag/similar_test.rb +15 -0
- data/test/acceptance/tag/top_albums_test.rb +37 -0
- data/test/acceptance/tag/top_artists_test.rb +31 -0
- data/test/acceptance/tag/top_tags_test.rb +33 -0
- data/test/acceptance/tag/top_tracks_test.rb +33 -0
- data/test/acceptance/tag/weekly_artist_chart.rb +54 -0
- data/test/acceptance/tag/weekly_chart_list.rb +39 -0
- data/test/acceptance/test_helper.rb +12 -0
- data/test/acceptance/track/info_test.rb +47 -0
- data/test/acceptance/track/similar_test.rb +22 -0
- data/test/acceptance/track/top_fans_test.rb +23 -0
- data/test/acceptance/track/top_tags_test.rb +24 -0
- data/test/acceptance/user/events_test.rb +27 -0
- data/test/acceptance/user/friends_test.rb +14 -0
- data/test/acceptance/user/info_test.rb +24 -0
- data/test/acceptance/user/loved_tracks_test.rb +14 -0
- data/test/acceptance/user/neighbours_test.rb +14 -0
- data/test/acceptance/user/past_events_test.rb +14 -0
- data/test/acceptance/user/playlists_test.rb +14 -0
- data/test/acceptance/user/recent_tracks_test.rb +14 -0
- data/test/acceptance/user/recommended_artists_test.rb +16 -0
- data/test/acceptance/user/recommended_events_test.rb +16 -0
- data/test/acceptance/user/shouts_test.rb +14 -0
- data/test/acceptance/user/top_albums_test.rb +14 -0
- data/test/acceptance/user/top_artists_test.rb +14 -0
- data/test/acceptance/user/top_tags_test.rb +14 -0
- data/test/acceptance/user/top_tracks_test.rb +14 -0
- data/test/acceptance/user/weekly_album_chart_test.rb +14 -0
- data/test/acceptance/user/weekly_artist_chart_test.rb +14 -0
- data/test/acceptance/user/weekly_chart_list_test.rb +14 -0
- data/test/acceptance/user/weekly_track_chart_test.rb +14 -0
- data/test/acceptance/venue/events_test.rb +14 -0
- data/test/acceptance/venue/past_events_test.rb +14 -0
- data/test/generators/test_acceptance_test_generator.rb +46 -0
- data/test/generators/test_generator_helper.rb +29 -0
- data/test/generators/test_resource_generator.rb +71 -0
- data/test/unit/album_spec.rb +17 -0
- data/test/unit/artist_spec.rb +62 -0
- data/test/unit/auth_spec.rb +22 -0
- data/test/unit/base_spec.rb +193 -0
- data/test/unit/event_spec.rb +23 -0
- data/test/unit/geo_spec.rb +36 -0
- data/test/unit/group_spec.rb +38 -0
- data/test/unit/library_spec.rb +27 -0
- data/test/unit/playlist_spec.rb +18 -0
- data/test/unit/spec_helper.rb +7 -0
- data/test/unit/tag_spec.rb +50 -0
- data/test/unit/track_spec.rb +33 -0
- data/test/unit/user_spec.rb +148 -0
- data/test/unit/venue_spec.rb +29 -0
- metadata +259 -0
data/README
ADDED
data/Rakefile
ADDED
data/VERSION.yml
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
class AcceptanceTestGenerator < RubiGen::Base
|
2
|
+
|
3
|
+
# default_options :author => nil
|
4
|
+
|
5
|
+
attr_reader :resource
|
6
|
+
attr_reader :func
|
7
|
+
|
8
|
+
def initialize(runtime_args, runtime_options = {})
|
9
|
+
super
|
10
|
+
usage if args.empty? || args.length < 2
|
11
|
+
@resource = args.shift
|
12
|
+
@func = args.shift
|
13
|
+
extract_options
|
14
|
+
end
|
15
|
+
|
16
|
+
def manifest
|
17
|
+
record do |m|
|
18
|
+
# Ensure appropriate folder(s) exists
|
19
|
+
m.directory "test/acceptance/#{@resource}"
|
20
|
+
|
21
|
+
# Create stubs
|
22
|
+
m.template "acceptance_test.rb.erb", "test/acceptance/#{@resource}/#{@func}_test.rb"
|
23
|
+
# m.template_copy_each ["template.rb", "template2.rb"]
|
24
|
+
# m.template_copy_each ["template.rb", "template2.rb"], "some/path"
|
25
|
+
# m.file "file", "some_file_copied"
|
26
|
+
# m.file_copy_each ["path/to/file", "path/to/file2"]
|
27
|
+
# m.file_copy_each ["path/to/file", "path/to/file2"], "some/path"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
def banner
|
33
|
+
<<-EOS
|
34
|
+
Creates a scrobbler2 acceptance test
|
35
|
+
|
36
|
+
USAGE: #{$0} #{spec.name} resource func
|
37
|
+
EOS
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_options!(opts)
|
41
|
+
# opts.separator ''
|
42
|
+
# opts.separator 'Options:'
|
43
|
+
# For each option below, place the default
|
44
|
+
# at the top of the file next to "default_options"
|
45
|
+
# opts.on("-a", "--author=\"Your Name\"", String,
|
46
|
+
# "Some comment about this option",
|
47
|
+
# "Default: none") { |options[:author]| }
|
48
|
+
# opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
|
49
|
+
end
|
50
|
+
|
51
|
+
def extract_options
|
52
|
+
# for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
|
53
|
+
# Templates can access these value via the attr_reader-generated methods, but not the
|
54
|
+
# raw instance variable value.
|
55
|
+
# @author = options[:author]
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper.rb'
|
2
|
+
|
3
|
+
describe "<%=func%> for <%=resource%> ..." do
|
4
|
+
|
5
|
+
before(:all) do #We only want to hit the webservice once.
|
6
|
+
@<%=resource%> = Scrobbler2::<%=resource.classify%>.new "..."
|
7
|
+
@<%=func%> = @<%=resource%>.<%=func%>
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be hash" do
|
11
|
+
@<%=func%>.should be_kind_of Hash
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class ResourceGenerator < RubiGen::Base
|
2
|
+
|
3
|
+
default_options :author => nil
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :funcs
|
7
|
+
|
8
|
+
def initialize(runtime_args, runtime_options = {})
|
9
|
+
super
|
10
|
+
usage if args.empty?
|
11
|
+
@name = args.shift
|
12
|
+
@funcs = args
|
13
|
+
extract_options
|
14
|
+
end
|
15
|
+
|
16
|
+
def manifest
|
17
|
+
record do |m|
|
18
|
+
# Ensure appropriate folder(s) exists
|
19
|
+
m.directory 'lib/scrobbler2'
|
20
|
+
m.directory 'test/unit'
|
21
|
+
|
22
|
+
# Create stubs
|
23
|
+
m.template "resource.rb.erb", "lib/scrobbler2/#{name}.rb"
|
24
|
+
m.template "spec.rb.erb", "test/unit/#{name}_spec.rb"
|
25
|
+
|
26
|
+
# Create acceptance tests
|
27
|
+
funcs.each do |func|
|
28
|
+
m.dependency "acceptance_test", [name, func]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
def banner
|
35
|
+
<<-EOS
|
36
|
+
Creates a scrobbler2 resource
|
37
|
+
|
38
|
+
USAGE: #{$0} #{spec.name} name funcs
|
39
|
+
EOS
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_options!(opts)
|
43
|
+
end
|
44
|
+
|
45
|
+
def extract_options
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Scrobbler2
|
2
|
+
class <%= name.classify %> < Base
|
3
|
+
|
4
|
+
def initialize()
|
5
|
+
@query = {}#TODO eg. {:artist => artist, :track => track}
|
6
|
+
end
|
7
|
+
<% funcs.each do |func| %>
|
8
|
+
get_resource :<%=func%>, :root => "<%=func.camelize.downcase%>"
|
9
|
+
<% end %>
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/spec_helper.rb"
|
2
|
+
|
3
|
+
describe "<%=name.classify%>" do
|
4
|
+
before(:each) do
|
5
|
+
@<%=name%> = Scrobbler2::<%=name.classify%>.new "..."
|
6
|
+
@<%=name%>.class.stub!(:get).and_return Hash.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have a default query {TODO}" do
|
10
|
+
@<%=name%>.instance_variable_get(:@query).should == {}
|
11
|
+
end
|
12
|
+
|
13
|
+
<% funcs.each do |func| %>
|
14
|
+
|
15
|
+
it "<%=func%> should call get with '<%=name%>.get<%=func%>'" do
|
16
|
+
@<%=name%>.class.should_receive(:get).with('<%=name%>.get<%=func%>', anything(), anything()).and_return Hash.new
|
17
|
+
@<%=name%>.<%=func%>
|
18
|
+
end
|
19
|
+
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
end
|
data/lib/scrobbler2.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'httparty'
|
3
|
+
require 'active_support'
|
4
|
+
$: << File.dirname(__FILE__)
|
5
|
+
|
6
|
+
module Scrobbler2
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'scrobbler2/base.rb'
|
11
|
+
require 'scrobbler2/auth.rb'
|
12
|
+
require 'scrobbler2/album.rb'
|
13
|
+
require 'scrobbler2/artist.rb'
|
14
|
+
require 'scrobbler2/event.rb'
|
15
|
+
require 'scrobbler2/geo.rb'
|
16
|
+
require 'scrobbler2/group.rb'
|
17
|
+
require 'scrobbler2/library.rb'
|
18
|
+
require 'scrobbler2/playlist.rb'
|
19
|
+
require 'scrobbler2/tag.rb'
|
20
|
+
require 'scrobbler2/track.rb'
|
21
|
+
require 'scrobbler2/user.rb'
|
22
|
+
require 'scrobbler2/venue.rb'
|
23
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
module Scrobbler2
|
3
|
+
class Artist < Base
|
4
|
+
|
5
|
+
def initialize(artist)
|
6
|
+
@query = {:artist => artist}
|
7
|
+
end
|
8
|
+
|
9
|
+
get_resource :events, :root => 'events'
|
10
|
+
get_resource :info, :root => 'artist'
|
11
|
+
get_resource :shouts, :root => 'shouts'
|
12
|
+
get_resource :similar, :root => 'similarartists'
|
13
|
+
get_resource :top_albums, :root => 'topalbums'
|
14
|
+
get_resource :top_fans, :root => 'topfans'
|
15
|
+
get_resource :top_tags, :root => 'toptags'
|
16
|
+
get_resource :top_tracks, :root => 'toptracks'
|
17
|
+
|
18
|
+
def tags
|
19
|
+
return @tags if @tags
|
20
|
+
@tags = self.class.get_with_auth("artist.gettags", @query)["lfm"]["tags"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_tags(tags)
|
24
|
+
query = @query.merge :tags => tags.join(",")
|
25
|
+
self.class.post_with_auth("artist.addtags", query)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Scrobbler2
|
2
|
+
class Auth < Base
|
3
|
+
|
4
|
+
def token
|
5
|
+
return @token if @token
|
6
|
+
@token = self.class.get_with_auth("auth.gettoken")["lfm"]["token"]
|
7
|
+
end
|
8
|
+
|
9
|
+
def url
|
10
|
+
"http://www.last.fm/api/auth/?api_key=#{api_key}&token=#{token}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def session
|
14
|
+
return @session if @session
|
15
|
+
@session = self.class.get_with_auth("auth.getsession", {:token => token})["lfm"]["session"]
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Scrobbler2
|
4
|
+
class Base
|
5
|
+
cattr_accessor :api_key
|
6
|
+
cattr_accessor :api_secret
|
7
|
+
cattr_accessor :session_key
|
8
|
+
|
9
|
+
def self.get(method, query={}, options={})
|
10
|
+
query = query.merge({:api_key => api_key, :method => method, :format => 'json'})
|
11
|
+
options = options.merge({:query => query})
|
12
|
+
|
13
|
+
response = HTTParty.get('http://ws.audioscrobbler.com/2.0/', options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.get_resource(name, options = {})
|
17
|
+
define_method name do |*args|
|
18
|
+
query = args[1] || {}
|
19
|
+
local_options = args[0] || {}
|
20
|
+
local_value = instance_variable_get("@#{name.to_s}")
|
21
|
+
return local_value if local_value && !options[:force]
|
22
|
+
|
23
|
+
query = query.merge options[:query] if options[:query]
|
24
|
+
query = query.merge(@query) if @query && !options[:query]
|
25
|
+
|
26
|
+
method_name = options[:resource_name] || self.class.name.split("::").last.downcase + ".get#{name.to_s.tr('_', '').downcase}"
|
27
|
+
if options[:auth]
|
28
|
+
value = self.class.get_with_auth(method_name, query, local_options)
|
29
|
+
else
|
30
|
+
value = self.class.get(method_name, query, local_options)
|
31
|
+
end
|
32
|
+
value = value[options[:root]] if options[:root]
|
33
|
+
|
34
|
+
instance_variable_set("@#{name}", value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
#implements signed requests
|
39
|
+
def self.get_with_auth(method, query={}, options={})
|
40
|
+
http_with_auth(:get, method, query, options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.http_with_auth(http_method, method, query={}, options={})
|
44
|
+
query = query.merge({:api_key => api_key, :method => method})
|
45
|
+
query = query.merge({:sk => session_key}) if session_key
|
46
|
+
|
47
|
+
signature = sign(query)
|
48
|
+
query = query.merge({:api_sig => signature})
|
49
|
+
|
50
|
+
if(http_method == :get)
|
51
|
+
options = options.merge({:query => query})
|
52
|
+
else
|
53
|
+
options = options.merge({:body => query})
|
54
|
+
end
|
55
|
+
response = HTTParty.send(http_method, 'http://ws.audioscrobbler.com/2.0/', options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.post_with_auth(method, query={}, options={})
|
59
|
+
http_with_auth(:post, method, query, options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.sign(query)
|
63
|
+
signature = query_signature(query)
|
64
|
+
md5 = Digest::MD5.hexdigest(signature)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.query_signature(query)
|
68
|
+
signature = query.sort {|a,b| a[0].to_s <=> b[0].to_s }.map { |param| param.join('') }.join('')
|
69
|
+
signature = "#{signature}#{api_secret}"
|
70
|
+
signature
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Scrobbler2
|
2
|
+
class Geo < Base
|
3
|
+
|
4
|
+
def initialize()
|
5
|
+
@query = {}#TODO eg. {:artist => artist, :track => track}
|
6
|
+
end
|
7
|
+
|
8
|
+
get_resource :events, :root => "events"
|
9
|
+
|
10
|
+
get_resource :top_artists, :root => "topartists"
|
11
|
+
|
12
|
+
get_resource :top_tracks, :root => "toptracks"
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Scrobbler2
|
2
|
+
class Group < Base
|
3
|
+
|
4
|
+
def initialize(group_name)
|
5
|
+
@query = {:group => group_name}
|
6
|
+
end
|
7
|
+
|
8
|
+
get_resource :members, :root => 'members'
|
9
|
+
get_resource :weekly_album_chart, :root => 'weeklyalbumchart'
|
10
|
+
get_resource :weekly_artist_chart, :root => 'weeklyartistchart'
|
11
|
+
get_resource :weekly_track_chart, :root => 'weeklytrackchart'
|
12
|
+
get_resource :weekly_chart_list, :root => 'weeklychartlist'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
module Scrobbler2
|
3
|
+
class Tag < Base
|
4
|
+
|
5
|
+
def initialize(tag)
|
6
|
+
@query = {:tag => tag}
|
7
|
+
end
|
8
|
+
|
9
|
+
get_resource :similar, :root => 'similar'
|
10
|
+
get_resource :top_artists, :root => 'topartists'
|
11
|
+
get_resource :top_albums, :root => 'topalbums'
|
12
|
+
get_resource :top_tracks, :root => 'toptracks'
|
13
|
+
get_resource :top_tags, :root => 'toptags'
|
14
|
+
get_resource :weekly_artist_chart, :root => 'weeklyartistchart'
|
15
|
+
get_resource :weekly_chart_list, :root => 'weeklychartlist'
|
16
|
+
end
|
17
|
+
end
|