shortwave 0.0.1
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/.document +5 -0
- data/.gitignore +10 -0
- data/.gitmodules +3 -0
- data/LICENSE +20 -0
- data/README.rdoc +74 -0
- data/Rakefile +133 -0
- data/VERSION +1 -0
- data/lib/shortwave.rb +12 -0
- data/lib/shortwave/authentication.rb +107 -0
- data/lib/shortwave/facade.rb +3 -0
- data/lib/shortwave/facade/build/facade_builder.rb +199 -0
- data/lib/shortwave/facade/build/facade_template.erb +17 -0
- data/lib/shortwave/facade/lastfm.rb +878 -0
- data/lib/shortwave/facade/remote.rb +86 -0
- data/lib/shortwave/model/album.rb +33 -0
- data/lib/shortwave/model/artist.rb +62 -0
- data/lib/shortwave/model/base_model.rb +112 -0
- data/lib/shortwave/model/chart_dates.rb +15 -0
- data/lib/shortwave/model/comparison.rb +15 -0
- data/lib/shortwave/model/event.rb +55 -0
- data/lib/shortwave/model/group.rb +26 -0
- data/lib/shortwave/model/location.rb +45 -0
- data/lib/shortwave/model/playlist.rb +36 -0
- data/lib/shortwave/model/shout.rb +21 -0
- data/lib/shortwave/model/tag.rb +47 -0
- data/lib/shortwave/model/track.rb +71 -0
- data/lib/shortwave/model/user.rb +70 -0
- data/lib/shortwave/model/venue.rb +37 -0
- data/lib/shortwave/model/weekly_charts.rb +31 -0
- data/lib/shortwave/providers.rb +161 -0
- data/shortwave.gemspec +178 -0
- data/test/authentication_test.rb +64 -0
- data/test/build/build_test.rb +25 -0
- data/test/build/data/intro.yml +2 -0
- data/test/build/data/screens/album_addTags.html +1238 -0
- data/test/build/data/screens/intro_truncated.html +426 -0
- data/test/build/data/screens/tasteometer_compare.html +1274 -0
- data/test/build/data/screens/user_getLovedTracks.html +1278 -0
- data/test/build/data/screens/venue_search.html +1261 -0
- data/test/build/facade_builder_test.rb +23 -0
- data/test/build/parameter_test.rb +43 -0
- data/test/build/remote_method_test.rb +47 -0
- data/test/build/ruby_class_test.rb +12 -0
- data/test/build/ruby_method_test.rb +137 -0
- data/test/helper.rb +35 -0
- data/test/model/album_test.rb +62 -0
- data/test/model/artist_test.rb +103 -0
- data/test/model/chart_dates_test.rb +11 -0
- data/test/model/comparison_test.rb +18 -0
- data/test/model/data/album_info.xml +38 -0
- data/test/model/data/album_search.xml +210 -0
- data/test/model/data/artist_info.xml +58 -0
- data/test/model/data/artist_search.xml +109 -0
- data/test/model/data/artist_shouts.xml +546 -0
- data/test/model/data/artist_top_fans.xml +405 -0
- data/test/model/data/event_info.xml +47 -0
- data/test/model/data/group_members.xml +242 -0
- data/test/model/data/group_weekly_album_chart.xml +1754 -0
- data/test/model/data/group_weekly_artist_chart.xml +604 -0
- data/test/model/data/group_weekly_track_chart.xml +1005 -0
- data/test/model/data/location_events.xml +383 -0
- data/test/model/data/ok.xml +2 -0
- data/test/model/data/playlist_fetch.xml +227 -0
- data/test/model/data/tag_search.xml +110 -0
- data/test/model/data/tag_similar.xml +254 -0
- data/test/model/data/tag_top_albums.xml +805 -0
- data/test/model/data/tag_top_artists.xml +605 -0
- data/test/model/data/tag_top_tags.xml +1254 -0
- data/test/model/data/tag_top_tracks.xml +843 -0
- data/test/model/data/tag_weekly_chart_list.xml +57 -0
- data/test/model/data/tasteometer_compare.xml +54 -0
- data/test/model/data/track_info.xml +53 -0
- data/test/model/data/track_search.xml +195 -0
- data/test/model/data/user_chartlist.xml +90 -0
- data/test/model/data/user_info.xml +16 -0
- data/test/model/data/user_neighbours.xml +484 -0
- data/test/model/data/user_playlists.xml +17 -0
- data/test/model/data/user_recent_tracks.xml +124 -0
- data/test/model/data/user_recommended_artists.xml +454 -0
- data/test/model/data/user_shouts.xml +9 -0
- data/test/model/data/user_weekly_artist_chart.xml +478 -0
- data/test/model/data/venue_events.xml +556 -0
- data/test/model/data/venue_past_events.xml +1778 -0
- data/test/model/data/venue_search.xml +355 -0
- data/test/model/event_test.rb +63 -0
- data/test/model/group_test.rb +45 -0
- data/test/model/location_test.rb +25 -0
- data/test/model/playlist_test.rb +51 -0
- data/test/model/shout_test.rb +23 -0
- data/test/model/tag_test.rb +39 -0
- data/test/model/track_test.rb +67 -0
- data/test/model/user_test.rb +125 -0
- data/test/model/venue_test.rb +60 -0
- data/test/provider/album_provider_test.rb +26 -0
- data/test/provider/artist_provider_test.rb +25 -0
- data/test/provider/group_provider_test.rb +9 -0
- data/test/provider/location_provider_test.rb +9 -0
- data/test/provider/playlist_provider_test.rb +12 -0
- data/test/provider/tag_provider_test.rb +24 -0
- data/test/provider/track_provider_test.rb +26 -0
- data/test/provider/user_provider_test.rb +11 -0
- data/test/provider/venue_provider_test.rb +15 -0
- data/test/provider_test_helper.rb +27 -0
- data/test/remote_test.rb +26 -0
- metadata +209 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'restclient'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'forwardable'
|
|
4
|
+
|
|
5
|
+
module Shortwave
|
|
6
|
+
# Includes thin wrapper classes around the Last.fm web services API.
|
|
7
|
+
#
|
|
8
|
+
# These classes map one-to-one to the Last.fm API, and are in fact generated from the
|
|
9
|
+
# HTML documentation the Last.fm provide. They make no attempt to OOify or XMLify the
|
|
10
|
+
# responses - the results of these methods are just the string responses from Last.fm.
|
|
11
|
+
# As such, they are a suitable base for building a "real" API on top of, which is
|
|
12
|
+
# what classes in Shortwave::Model do.
|
|
13
|
+
#
|
|
14
|
+
# The general use is:
|
|
15
|
+
#
|
|
16
|
+
# # Create a session for your platform
|
|
17
|
+
# session = Shortwave::Authentication::Mobile.new("api_key", "app_secret")
|
|
18
|
+
#
|
|
19
|
+
# # Authenticate if necessary (if you want to use write methods)
|
|
20
|
+
# session.authenticate("user", "password")
|
|
21
|
+
#
|
|
22
|
+
# # Create a facade, passing in the session
|
|
23
|
+
# facade = Shortwave::Facade::Artist.new(session)
|
|
24
|
+
#
|
|
25
|
+
# # Call methods on the facade
|
|
26
|
+
# facade.top_tags("The feelies")
|
|
27
|
+
# # => returns <lfm status="ok"> ... etc.
|
|
28
|
+
#
|
|
29
|
+
# Required method parameters in the web api are real method parameters - if the method
|
|
30
|
+
# has optional parameters, these appear in an options hash after all the required parameters.
|
|
31
|
+
# You do not need to provide any authentication parameters (+api_key+, +api_sig+ & +sk+) - these
|
|
32
|
+
# are merged in from the session for you automatically.
|
|
33
|
+
#
|
|
34
|
+
# If the request fails, the facade method will raise a RemoteError.
|
|
35
|
+
#
|
|
36
|
+
# Each of the facades has further documentation, taken directly from the Last.fm documentation
|
|
37
|
+
# at http://last.fm/api
|
|
38
|
+
module Facade
|
|
39
|
+
# Wraps a RestClient::RequestFailed exception, and delegates +message+, +http_code+
|
|
40
|
+
# and +response+ to the wrapped exception.
|
|
41
|
+
#
|
|
42
|
+
# This class is mainly provided for api stability in case we switch from using RestClient.
|
|
43
|
+
class RemoteError < RuntimeError
|
|
44
|
+
extend Forwardable
|
|
45
|
+
def_delegators :@cause, :message, :to_s, :http_code, :response
|
|
46
|
+
|
|
47
|
+
def initialize(cause)
|
|
48
|
+
@cause = cause
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Base class for each remote facade.
|
|
53
|
+
#
|
|
54
|
+
# Remote methods may raise a RemoteError if an http error response is returned from
|
|
55
|
+
# the Last.fm service.
|
|
56
|
+
class Remote
|
|
57
|
+
attr_reader :session
|
|
58
|
+
|
|
59
|
+
# Creates a new facade, given a user session
|
|
60
|
+
def initialize(session)
|
|
61
|
+
@session = session
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
protected
|
|
65
|
+
|
|
66
|
+
BASE_URI = "http://ws.audioscrobbler.com/2.0/"
|
|
67
|
+
DISALLOWED = Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
|
|
68
|
+
AGENT = "Shortwave 0.0.1 http://shortwave.rubyforge.org/"
|
|
69
|
+
|
|
70
|
+
def get(type, data)
|
|
71
|
+
@session.merge!(type, data)
|
|
72
|
+
uri = BASE_URI + "?" + data.map {|k,v| "#{k.to_s}=#{URI.escape(v.to_s, DISALLOWED)}"}.join("&")
|
|
73
|
+
RestClient.get uri, {"User-Agent" => AGENT}
|
|
74
|
+
rescue RestClient::RequestFailed => e
|
|
75
|
+
raise RemoteError.new(e)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def post(type, data)
|
|
79
|
+
@session.merge!(type, data, {"User-Agent" => AGENT})
|
|
80
|
+
RestClient.post BASE_URI, data
|
|
81
|
+
rescue RestClient::RequestFailed => e
|
|
82
|
+
raise RemoteError.new(e)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Shortwave
|
|
2
|
+
module Model
|
|
3
|
+
# An album on Last.fm
|
|
4
|
+
#
|
|
5
|
+
# === Attributes
|
|
6
|
+
#
|
|
7
|
+
# +name+:: Album name
|
|
8
|
+
# +url+:: Last.fm site url
|
|
9
|
+
# +id+:: Last.fm id
|
|
10
|
+
# +release_date+:: Release date
|
|
11
|
+
# +listeners+:: Number of listeners
|
|
12
|
+
# +play_count+:: Number of times tracks from this album have been played
|
|
13
|
+
# +images+:: An array of album images
|
|
14
|
+
# +mbid+:: Musicbrainz ID
|
|
15
|
+
# +artist_name+:: Album's artist
|
|
16
|
+
# +tags+:: Last.fm user tags
|
|
17
|
+
class Album < BaseModel
|
|
18
|
+
element :name, String, :tag => "name|title"
|
|
19
|
+
element :url, String
|
|
20
|
+
element :id, Integer
|
|
21
|
+
element :release_date, Time, :tag => "releasedate"
|
|
22
|
+
element :listeners, Integer
|
|
23
|
+
element :play_count, Integer, :tag => "playcount"
|
|
24
|
+
element :images, String, :tag => "image", :single => false
|
|
25
|
+
element :mbid, String
|
|
26
|
+
element :artist_name, String, :tag => "artist"
|
|
27
|
+
has_many :tags, "Shortwave::Model::Tag", :tag => "toptags/tag"
|
|
28
|
+
|
|
29
|
+
identified_by :artist_name, :name
|
|
30
|
+
taggable
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Shortwave
|
|
2
|
+
module Model
|
|
3
|
+
# An artist. Artists are taggable, shoutable and sharable by a user.
|
|
4
|
+
#
|
|
5
|
+
# === Attributes
|
|
6
|
+
#
|
|
7
|
+
# +name+:: Artist name
|
|
8
|
+
# +mbid+:: Musicbrainz ID
|
|
9
|
+
# +url+:: Url of artist page on the Last.fm site
|
|
10
|
+
# +play_count+:: The number of times this artist has been played
|
|
11
|
+
# +listeners+:: The number of listeners this artist has
|
|
12
|
+
# +biography_summary+:: Textual description of this artist
|
|
13
|
+
# +biography+:: Full textual description of this artist
|
|
14
|
+
# +images+:: Images of this artist
|
|
15
|
+
class Artist < BaseModel
|
|
16
|
+
element :name, String
|
|
17
|
+
element :mbid, String
|
|
18
|
+
element :url, String
|
|
19
|
+
element :streamable, Boolean
|
|
20
|
+
element :play_count, Integer, :tag => "stats/playcount"
|
|
21
|
+
element :listeners, Integer, :tag => "stats/listeners"
|
|
22
|
+
element :biography_summary, String, :tag => "bio/content"
|
|
23
|
+
element :biography, String, :tag => "bio/content"
|
|
24
|
+
element :images, String, :tag => "image", :single => false
|
|
25
|
+
|
|
26
|
+
identified_by :name
|
|
27
|
+
taggable
|
|
28
|
+
shoutable
|
|
29
|
+
sharable
|
|
30
|
+
|
|
31
|
+
# Events this artist is playing at.
|
|
32
|
+
def events
|
|
33
|
+
link :events, :Event, name
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Artists similar to this one.
|
|
37
|
+
def similar
|
|
38
|
+
link :similar, :Artist, name
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# This artist's top albums
|
|
42
|
+
def albums
|
|
43
|
+
link :top_albums, :Album, name
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# This artist's top fans
|
|
47
|
+
def fans
|
|
48
|
+
link :top_fans, :User, name
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# This artist's top tags
|
|
52
|
+
def tags
|
|
53
|
+
link :top_tags, :Tag, name
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# This artist's top tracks
|
|
57
|
+
def tracks
|
|
58
|
+
link :top_tracks, :Track, name
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module Shortwave
|
|
2
|
+
module Model
|
|
3
|
+
# Root class for all Shortwave models.
|
|
4
|
+
class BaseModel
|
|
5
|
+
# Sets the session on this model, and all nested models
|
|
6
|
+
def session=(session)
|
|
7
|
+
@session = session
|
|
8
|
+
self.class.has_ones.each do |sym|
|
|
9
|
+
obj = send(sym)
|
|
10
|
+
obj.session = session if obj
|
|
11
|
+
end
|
|
12
|
+
self.class.has_manys.each {|s| (send(s) || []).each {|o| o.session = session } }
|
|
13
|
+
session
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def facade_name
|
|
18
|
+
@facade_name ||= (name.split("::").last.downcase + "_facade").to_sym
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def identified_by(*methods)
|
|
22
|
+
@lastfm_keys = methods
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Adds methods to a model to deal with shouts: shouts and shout
|
|
26
|
+
def shoutable
|
|
27
|
+
class_eval <<-EOV
|
|
28
|
+
def shout(message)
|
|
29
|
+
@session.#{facade_name}.shout(#{@lastfm_keys.join(",")}, message)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
link_to "Shout", :shouts
|
|
33
|
+
EOV
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Adds methods to a model to deal with tags: tags, add_tags and remove_tag
|
|
37
|
+
#
|
|
38
|
+
# Up to ten tags can be added, either strings, or Tag models
|
|
39
|
+
# A single tag can be removed
|
|
40
|
+
def taggable
|
|
41
|
+
class_eval <<-EOV
|
|
42
|
+
def add_tags(*tags)
|
|
43
|
+
tag_param = tags[0...10].map {|t| t.to_s }.join(",")
|
|
44
|
+
@session.#{facade_name}.add_tags(#{@lastfm_keys.join(",")}, tag_param)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def remove_tag(tag)
|
|
48
|
+
@session.#{facade_name}.remove_tag(#{@lastfm_keys.join(",")}, tag.to_s)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
link_to "Tag", :my_tags, :tags
|
|
52
|
+
EOV
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def sharable
|
|
56
|
+
class_eval <<-EOV
|
|
57
|
+
def share(recipients, message=nil)
|
|
58
|
+
params = {}
|
|
59
|
+
params[:message] = message if message
|
|
60
|
+
@session.#{facade_name}.share(#{@lastfm_keys.join(",")}, recipients[0...10].map{|r| r.to_s }.join(','), params)
|
|
61
|
+
end
|
|
62
|
+
EOV
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def link_to(klass, method, remote_method=nil)
|
|
66
|
+
remote_method ||= method
|
|
67
|
+
class_eval <<-EOV
|
|
68
|
+
def #{method}
|
|
69
|
+
response = @session.#{facade_name}.#{remote_method}(#{@lastfm_keys.join(',')})
|
|
70
|
+
#{klass}.parse(response).each {|obj| obj.session = @session }
|
|
71
|
+
end
|
|
72
|
+
EOV
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def inherited(klass)
|
|
76
|
+
klass.send(:include, HappyMapper)
|
|
77
|
+
klass.send(:tag, klass.name.split("::").last.downcase)
|
|
78
|
+
|
|
79
|
+
# Store every has_one/has_many declaration and use this information
|
|
80
|
+
# to decide which attributes need a session adding
|
|
81
|
+
class << klass
|
|
82
|
+
def has_ones
|
|
83
|
+
@has_ones ||= []
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def has_manys
|
|
87
|
+
@has_manys ||= []
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def has_one(sym, *args)
|
|
91
|
+
super
|
|
92
|
+
has_ones << sym
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def has_many(sym, *args)
|
|
96
|
+
super
|
|
97
|
+
has_manys << sym
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
protected
|
|
104
|
+
|
|
105
|
+
def link(remote_method, klass, *args)
|
|
106
|
+
response = @session.send(self.class.facade_name).send(remote_method, *args)
|
|
107
|
+
klass = ::Shortwave::Model.const_get(klass)
|
|
108
|
+
klass.parse(response).each {|obj| obj.session = @session }
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Shortwave
|
|
2
|
+
module Model
|
|
3
|
+
# A chart date range. This is only really used internally.
|
|
4
|
+
#
|
|
5
|
+
# === Attributes
|
|
6
|
+
#
|
|
7
|
+
# from:: the date the chart starts
|
|
8
|
+
# to:: the date the chart finishes
|
|
9
|
+
class ChartDates < BaseModel
|
|
10
|
+
tag "chart"
|
|
11
|
+
attribute :from, Time
|
|
12
|
+
attribute :to, Time
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Shortwave
|
|
2
|
+
module Model
|
|
3
|
+
# A comparison between two Last.fm users
|
|
4
|
+
#
|
|
5
|
+
# === Attributes
|
|
6
|
+
#
|
|
7
|
+
# +score+:: A number between 0 and 1 representing how similar users are.
|
|
8
|
+
# +artists+:: Artists both users have in common
|
|
9
|
+
class Comparison < BaseModel
|
|
10
|
+
tag "comparison"
|
|
11
|
+
element :score, Float, :tag => "result/score"
|
|
12
|
+
has_many :artists, "Model::Artist", :tag => "result/artists/artist"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Shortwave
|
|
2
|
+
module Model
|
|
3
|
+
# An event.
|
|
4
|
+
#
|
|
5
|
+
# == Attributes
|
|
6
|
+
# +id+:: Last.fm id
|
|
7
|
+
# +name+:: Event name
|
|
8
|
+
# +description+:: Event description
|
|
9
|
+
# +attendance_count+:: Number of last.fm user's attending
|
|
10
|
+
# +review_count+:: Number of reviews
|
|
11
|
+
# +starts_at+:: The start time
|
|
12
|
+
# +url+:: Last.fm site url
|
|
13
|
+
# +venue+:: Event venue
|
|
14
|
+
class Event < BaseModel
|
|
15
|
+
element :id, Integer
|
|
16
|
+
element :description, String
|
|
17
|
+
element :url, String
|
|
18
|
+
element :attendance_count, Integer, :tag => "attendance"
|
|
19
|
+
element :review_count, Integer, :tag => "reviews"
|
|
20
|
+
element :starts_at, Time, :tag => "startDate"
|
|
21
|
+
element :name, String, :tag => "title"
|
|
22
|
+
element :headliner_raw, String, :tag => "artists/headliner"
|
|
23
|
+
element :artists_raw, String, :tag => "artists/artist", :single => false
|
|
24
|
+
has_one :venue, "Model::Venue"
|
|
25
|
+
|
|
26
|
+
identified_by :id
|
|
27
|
+
shoutable
|
|
28
|
+
sharable
|
|
29
|
+
|
|
30
|
+
# Returns the list of users attending this event
|
|
31
|
+
def attendees
|
|
32
|
+
link :attendees, :User, id
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Mark the current session user's attendance at this event
|
|
36
|
+
#
|
|
37
|
+
# Possible statuses are +:yes+, +:no+ and +:maybe+
|
|
38
|
+
def attend(status=:yes)
|
|
39
|
+
i = [:yes, :maybe, :no].index(status)
|
|
40
|
+
@session.event_facade.attend(id, i)
|
|
41
|
+
true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Returns the headline act for this event
|
|
45
|
+
def headliner
|
|
46
|
+
@headliner ||= artists.detect {|a| a.name == headliner_raw }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns the list of artists playing at this event
|
|
50
|
+
def artists
|
|
51
|
+
@artists ||= artists_raw.map {|a| @session.artist.build(:name => a) }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + "/weekly_charts"
|
|
2
|
+
|
|
3
|
+
module Shortwave
|
|
4
|
+
module Model
|
|
5
|
+
# A Last.fm user group.
|
|
6
|
+
#
|
|
7
|
+
# === Attributes
|
|
8
|
+
#
|
|
9
|
+
# name:: the group name
|
|
10
|
+
class Group < BaseModel
|
|
11
|
+
attr_accessor :name
|
|
12
|
+
identified_by :name
|
|
13
|
+
include WeeklyCharts
|
|
14
|
+
|
|
15
|
+
# Returns the group's members. Currently only 50 users are returned
|
|
16
|
+
def members
|
|
17
|
+
link :members, "User", name
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# The group name
|
|
21
|
+
def to_s
|
|
22
|
+
name
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Shortwave
|
|
2
|
+
module Model
|
|
3
|
+
# A location
|
|
4
|
+
#
|
|
5
|
+
# === Attributes
|
|
6
|
+
# +latitude+:: Latitude
|
|
7
|
+
# +longitude+:: Longitude
|
|
8
|
+
# +street_address+:: Street address
|
|
9
|
+
# +city+:: City
|
|
10
|
+
# +postcode+:: Post code
|
|
11
|
+
# +country+:: Country name
|
|
12
|
+
class Location < BaseModel
|
|
13
|
+
tag "location"
|
|
14
|
+
element :latitude, Float, :tag => "geo:point/geo:lat"
|
|
15
|
+
element :longitude, Float, :tag => "geo:point/geo:long"
|
|
16
|
+
element :city, String
|
|
17
|
+
element :country, String
|
|
18
|
+
element :street_address, String, :tag => "street"
|
|
19
|
+
element :postcode, String, :tag => "postalcode"
|
|
20
|
+
|
|
21
|
+
# Popular artists in this country. Needs country to be defined
|
|
22
|
+
def artists
|
|
23
|
+
link :top_artists, :Artist, country
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Popular tracks in this location
|
|
27
|
+
def tracks
|
|
28
|
+
args = [country]
|
|
29
|
+
args << {:location => city} if city
|
|
30
|
+
link :top_tracks, :Track, *args
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Return events near this location
|
|
34
|
+
def events
|
|
35
|
+
if latitude && longitude
|
|
36
|
+
link :events, :Event, :lat => latitude, :long => longitude
|
|
37
|
+
elsif city
|
|
38
|
+
link :events, :Event, :location => city
|
|
39
|
+
elsif country
|
|
40
|
+
link :events, :Event, :location => country
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|