claudiob-yesradio 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1 +1,3 @@
1
1
  .DS_Store
2
+ doc/*
3
+ pkg/**/*
data/README.md CHANGED
@@ -5,18 +5,63 @@ Ruby gem to access Yes.com API
5
5
  <a name="rubygem_install" />
6
6
  ## Installation ##
7
7
 
8
- sudo gem install yesradio -s http://gems.github.com
8
+ sudo gem install claudiob-yesradio -s http://gems.github.com
9
+
10
+ ## Documentation ##
11
+
12
+ http://rdoc.info/projects/claudiob/yesradio
9
13
 
10
14
  ## Examples ##
11
15
 
12
16
  ### To show a list of 'Rock' stations ###
13
17
 
14
18
  require 'yesradio'
15
- query = Yesradio::StationsSearchCriteria.new
16
- query.match = "KWOF"
17
- result = Yesradio::search_stations query
19
+ Yesradio::search_stations :match => "Rock"
18
20
 
19
21
  ### To show details of 'WFNX' radio ###
20
22
 
21
23
  require 'yesradio'
22
- Yesradio::match_station "WFNX"
24
+ Yesradio::get_station "WFNX"
25
+
26
+ ### To show log of tracks played on 'WFNX' radio ###
27
+
28
+ require 'yesradio'
29
+ Yesradio::get_log "WFNX"
30
+
31
+ ### To show recent tracks played on 'WFNX' radio ###
32
+
33
+ require 'yesradio'
34
+ Yesradio::get_recent "WFNX"
35
+
36
+ ### To show a chart of popular Rock songs ###
37
+
38
+ require 'yesradio'
39
+ Yesradio::get_chart :genre => "Rock"
40
+
41
+ ### To show a list of songs by artist Rihanna ###
42
+
43
+ require 'yesradio'
44
+ Yesradio::get_media :aid => 610471
45
+
46
+ ### To show a list of songs related to Umbrella (Rihanna) ###
47
+
48
+ require 'yesradio'
49
+ Yesradio::get_related :mid => 11586843
50
+
51
+
52
+ ## History ##
53
+
54
+ v0.0.2 2009/09/15
55
+ Added support for actions: chart, media, related.
56
+ Added documentation through RDoc.
57
+ Added cucumber features for listing stations.
58
+
59
+ v0.0.1 2009/09/15
60
+ Added support for actions: log, recent.
61
+
62
+ v0.0.0 2009/09/14
63
+ Added support for actions: station, stations
64
+
65
+ ## Copyright ##
66
+
67
+ Copyright (c) 2009 Claudio Baccigalupo. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -0,0 +1,17 @@
1
+ Given /^nothing$/ do
2
+
3
+ end
4
+
5
+ When /^I look for ([0-9]+) stations called "([^\"]*)"$/ do |max, match|
6
+ @stations = Yesradio::search_stations :match => match, :max => max
7
+ end
8
+
9
+ Then /^I should see a radio with name "([^\"]*)" and market "([^\"]*)"$/ do |name, market|
10
+ @stations.collect do |station|
11
+ station.name == name && station.market == market
12
+ end.inject{ |sum, el| sum || el }.should be_true
13
+ end
14
+
15
+ Then /^I should see nothing$/ do
16
+ @stations.should be_nil
17
+ end
@@ -1,9 +1,14 @@
1
- Feature: something something
2
- In order to something something
3
- A user something something
4
- something something something
1
+ Feature: Call Yes.com API using Ruby
2
+ In order to retrieve Yes.com data in Ruby code
3
+ programmers
4
+ want a Ruby interface to Yes.com API
5
5
 
6
- Scenario: something something
7
- Given inspiration
8
- When I create a sweet new gem
9
- Then everyone should see how awesome I am
6
+ Scenario: List Stations
7
+ Given nothing
8
+ When I look for 10 stations called "KEXP"
9
+ Then I should see a radio with name "KEXP" and market "Seattle - Tacoma, WA"
10
+
11
+ Scenario: List Stations Empty
12
+ Given nothing
13
+ When I look for 10 stations called "ABCDEFGH"
14
+ Then I should see nothing
data/lib/item.rb ADDED
@@ -0,0 +1,36 @@
1
+ # Author:: Claudio Baccigalupo
2
+ # Copyright:: Copyright (c) 2009 - see LICENSE file
3
+
4
+ require 'date'
5
+
6
+ module Yesradio
7
+ class Item
8
+ class << self
9
+ attr_accessor :elements
10
+ end
11
+
12
+ def initialize(element = nil)
13
+ self.class.elements.each do |name, type|
14
+ new_value = get_element_child element, name.gsub('_', '/'), type
15
+ self.instance_variable_set("@#{name}", new_value) unless new_value.nil?
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def get_element_child(element, child, type = :text)
22
+ return if element.nil? || element.elements[child].nil?
23
+ child = element.elements[child][0].to_s
24
+ return case type
25
+ when :int then child.to_i
26
+ when :float then child.to_f
27
+ when :datetime then DateTime.parse(child)
28
+ else child
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+
data/lib/main.rb CHANGED
@@ -1,24 +1,7 @@
1
- #=============================================================================
2
- #
3
- # 2009 Claudio Baccigalupo
4
- #
5
- # Licensed under the Ruby License
6
- #
7
- #=============================================================================
1
+ # Author:: Claudio Baccigalupo
2
+ # Copyright:: Copyright (c) 2009 - see LICENSE file
8
3
 
9
4
  require 'yesradio'
10
5
 
11
- # get the list of radio stations
12
- query = Yesradio::StationsSearchCriteria.new
13
- query.match = "KWOF"
14
- stations = Yesradio::search_stations query
15
- p stations
16
-
17
- # get the details of a radio station
18
- Yesradio::match_station "WFNX"
19
-
20
- # get the log of songs played on a radio
21
- Yesradio::get_log "KEXP"
22
-
23
- # get the recent songs played on a radio
24
- Yesradio::get_recent "KEXP"
6
+ # TODO: a file that prompts the user for the action to take
7
+ # and the parameters, and returns the result (as a shell command)
data/lib/song.rb CHANGED
@@ -1,20 +1,14 @@
1
- #=============================================================================
2
- #
3
- # 2009 Claudio Baccigalupo
4
- #
5
- # Licensed under the Ruby License
6
- #
7
- #=============================================================================
1
+ # Author:: Claudio Baccigalupo
2
+ # Copyright:: Copyright (c) 2009 - see LICENSE file
8
3
 
4
+ require 'item'
9
5
  module Yesradio
10
- class Song
11
- @@elements = {'at' => :datetime, 'by' => :text, 'title' => :text,
6
+ class Song < Item
7
+ @elements = {'at' => :datetime, 'by' => :text, 'title' => :text,
12
8
  'id' => :int, 'type' => :text, 'rank' => :int,
13
- 'cover' => :text, 'video' => :text, 'ago' => :int}
14
- attr_accessor *@@elements.keys
15
- def elements
16
- @@elements
17
- end
9
+ 'cover' => :text, 'video' => :text, 'link' => :text,
10
+ 'ago' => :int}
11
+ attr_accessor *@elements.keys
18
12
  end
19
13
  end
20
14
 
data/lib/station.rb CHANGED
@@ -1,22 +1,15 @@
1
- #=============================================================================
2
- #
3
- # 2009 Claudio Baccigalupo
4
- #
5
- # Licensed under the Ruby License
6
- #
7
- #=============================================================================
1
+ # Author:: Claudio Baccigalupo
2
+ # Copyright:: Copyright (c) 2009 - see LICENSE file
8
3
 
4
+ require 'item'
9
5
  module Yesradio
10
- class Station
11
- @@elements = {'name' => :text, 'desc' => :text, 'genre' => :text,
6
+ class Station < Item
7
+ @elements = {'name' => :text, 'desc' => :text, 'genre' => :text,
12
8
  'market' => :text, 'type' => :text, 'id' => :int,
13
9
  'tz' => :text, 'stream' => :text, 'yes' => :text,
14
10
  'relay' => :text, 'audiostream' => :text, 'array_id' => :int,
15
11
  'array_song' => :text, 'array_artist' => :text}
16
- attr_accessor *@@elements.keys
17
- def elements
18
- @@elements
19
- end
12
+ attr_accessor *@elements.keys
20
13
  end
21
14
  end
22
15
 
data/lib/yesradio.rb CHANGED
@@ -1,15 +1,9 @@
1
- #=============================================================================
2
- #
3
- # 2009 Claudio Baccigalupo
4
- #
5
- # Licensed under the Ruby License
6
- #
7
- #=============================================================================
1
+ # Author:: Claudio Baccigalupo
2
+ # Copyright:: Copyright (c) 2009 - see LICENSE file
8
3
 
9
4
  require 'cgi'
10
5
  require 'net/http'
11
6
  require 'rexml/document'
12
- require 'date'
13
7
 
14
8
  require 'station'
15
9
  require 'stations_search_criteria'
@@ -20,103 +14,136 @@ module Yesradio
20
14
  YESRADIO_VERSION = 1
21
15
  YESRADIO_SERVER = "http://api.yes.com/#{YESRADIO_VERSION}"
22
16
 
23
- def self.element_to_station(element)
24
- station = Station.new
25
- station.elements.each do |name, type|
26
- new_value = get_element_child element, name.gsub('_', '/'), type
27
- station.instance_variable_set("@#{name}", new_value) unless new_value.nil?
28
- end
29
- station
17
+ # Get current information about a single station including now playing song,
18
+ # slogan, frequency, market, and links to any known webcast stream or site.
19
+ #
20
+ # == Parameters
21
+ # [+name+] The station name (for AM/FM it is just the call letters).
22
+ #
23
+ # == Examples
24
+ # get_station :name => "KEXP"
25
+ #--
26
+ def self.get_station(query_hash)
27
+ array = self.search('Station', "station", "//api", query_hash)
28
+ array[0] unless array.nil? || array[0].name.nil?
30
29
  end
31
30
 
32
- # TO DO, dry with the previous function
33
- def self.element_to_song(element)
34
- song = Song.new
35
- song.elements.each do |name, type|
36
- new_value = get_element_child element, name.gsub('_', '/'), type
37
- song.instance_variable_set("@#{name}", new_value) unless new_value.nil?
38
- end
39
- song
31
+ # Search and find a list of stations by name, frequency, genre, artist,
32
+ # or location.
33
+ #
34
+ # == Parameters
35
+ # [+match+] [optional] Used to search station names, call letters, slogans, frequency, or cities/states.
36
+ # [+freq+] [optional] Also match an exact AM/FM frequency.
37
+ # [+mid+] [optional] Also match only stations that have this media id (see #media call) in their top 100 charts.
38
+ # [+genre+] [optional] Also match any genre keywords like pop, rock, etc.
39
+ # [+loc+] [optional] Also match stations within 60 miles of the given zip code, "lat,lon", or city/state names.
40
+ # [+max+] [optional] Defaults to 10 stations returned.
41
+ #
42
+ # == Examples
43
+ # search_stations :match => "KEX"
44
+ #--
45
+ def self.search_stations(query_hash)
46
+ self.search('Station', "stations", "//api/array/stations", query_hash)
40
47
  end
41
48
 
42
- def self.search_stations(search_criteria)
43
- stations = Array.new
49
+ # Get the log of all the songs played on the given station in a selected day
50
+ # within the last week.
51
+ #
52
+ # == Parameters
53
+ # [+name+] The station name.
54
+ # [+ago+] [optional] The days ago from now for the given date you want, an integer from 0-6 and defaults to 0 (the log today so far).
55
+ #
56
+ # == Examples
57
+ # get_log :name => "KEXP", :ago => 3
58
+ #--
59
+ def self.get_log(query_hash)
60
+ self.search('Song', "log", "//api/array/songs", query_hash)
61
+ end
44
62
 
45
- url = Yesradio::YESRADIO_SERVER + "/stations?type=xml"
46
- url = url + search_criteria.to_query_params_string
47
- uri = URI.parse(url)
48
- req = Net::HTTP::Get.new(uri.path + '?' + uri.query)
49
- res = Net::HTTP.start(uri.host, uri.port) { |http|
50
- http.request(req)
51
- }
52
- doc = REXML::Document.new res.body
53
- doc.elements.each("//api/array/stations") do |element|
54
- stations << element_to_station(element)
55
- end
56
- stations
63
+ # Get the most recent songs played on any station.
64
+ #
65
+ # == Parameters
66
+ # [+name+] The station name.
67
+ # [+max+] How many recent songs to return (default is 10).
68
+ #
69
+ # == Examples
70
+ # get_recent :name => "KEXP", :max => 3
71
+ #--
72
+ def self.get_recent(query_hash)
73
+ self.search('Song', "recent", "//api/array/songs", query_hash)
57
74
  end
58
75
 
59
- def self.get_station(station_name)
60
- url = Yesradio::YESRADIO_SERVER + "/station?type=xml"
61
- url = url + "&name=" + CGI::escape(station_name)
62
- uri = URI.parse(url)
63
- req = Net::HTTP::Get.new(uri.path + '?' + uri.query)
64
- res = Net::HTTP.start(uri.host, uri.port) { |http|
65
- http.request(req)
66
- }
67
- doc = REXML::Document.new res.body
68
- element_to_station(doc.elements["//api"])
76
+ # Get the current top 100 songs for any station based on number of times
77
+ # played and user voting (calculated daily).
78
+ #
79
+ # == Parameters
80
+ # [+name+] [optional] The station name, defaults to US national top 100 if none given.
81
+ # [+date+] [optional] Return just the charts from a specific date in the format year-mm-dd (April 2008 and newer).
82
+ # [+genre+] [optional] Filter any request to a specific Genre ( Americana Blues Christian Classical Country Electronica Hip-Hop Jazz Latin Metal New Age Pop Punk R&B/Soul Rock Smooth Jazz World ).
83
+ # [+hot+] [optional] Alternative sorting, must be either "fresh" (by most increase in charts day-to-day, not supported in combination with date field) or "vote" (most votes via yes.com).
84
+ # [+max+] How many songs to return (default is 10).
85
+ #
86
+ # == Examples
87
+ # get_chart :genre => "Rock"
88
+ #--
89
+ def self.get_chart(query_hash)
90
+ self.search('Song', "chart", "//api/array/songs", query_hash)
69
91
  end
70
92
 
71
- def self.get_log(station_name, ago = nil)
72
- songs = Array.new
73
-
74
- url = Yesradio::YESRADIO_SERVER + "/log?type=xml"
75
- url = url + "&name=" + CGI::escape(station_name)
76
- url = url + "&ago=" + CGI::escape(ago.to_s) unless ago.nil?
77
- uri = URI.parse(url)
78
- req = Net::HTTP::Get.new(uri.path + '?' + uri.query)
79
- res = Net::HTTP.start(uri.host, uri.port) { |http|
80
- http.request(req)
81
- }
82
- doc = REXML::Document.new res.body
83
- doc.elements.each("//api/array/songs") do |element|
84
- songs << element_to_song(element)
85
- end
86
- songs
93
+ # Get a list of any matching artist names or song titles based on airtime
94
+ # popularity.
95
+ #
96
+ # == Parameters
97
+ # [+q+] The string to search with, can be partial (used for autocomplete) or full names.
98
+ # [+aid+] [optional] Instead of a general query, a known Artist ID can be passed to return just media from that artist.
99
+ # [+mid+] [optional] Instead of a general query, a known Media ID can be passed to return extra information (lyrics from Lyric Wiki and matching videos from YouTube and MTV) about just that song.
100
+ # [+max+] How many songs to return (default is 10, max is 50).
101
+ #
102
+ # == Examples
103
+ # get_media :aid => 610471
104
+ #--
105
+ # Run test with http://api.yes.com/1/media?mid=12812281&type=xml
106
+ # which returns an XML error (Yes.com's fault)
107
+ def self.get_media(query_hash)
108
+ self.search('Song', "media", "//api/array/songs", query_hash)
109
+ end
110
+
111
+ # Given a song, return a list of related songs based on airtime in the last
112
+ # week.
113
+ #
114
+ # == Parameters
115
+ # [+mid+] The media ID (use media call to search for IDs).
116
+ # [+max+] Maximum number of related songs to return (default is 20).
117
+ #
118
+ # == Examples
119
+ # get_related :mid => 11586843
120
+ #--
121
+ def self.get_related(query_hash)
122
+ self.search('Song', "related", "//api/array/songs", query_hash)
87
123
  end
88
124
 
89
- def self.get_recent(station_name, max = nil)
90
- songs = Array.new
91
-
92
- url = Yesradio::YESRADIO_SERVER + "/recent?type=xml"
93
- url = url + "&name=" + CGI::escape(station_name)
94
- url = url + "&max=" + CGI::escape(max.to_s) unless max.nil?
125
+ protected
126
+
127
+ def self.search(item_class, action, xml_element, query_hash)
128
+ url = create_url(action, query_hash)
95
129
  uri = URI.parse(url)
96
130
  req = Net::HTTP::Get.new(uri.path + '?' + uri.query)
97
131
  res = Net::HTTP.start(uri.host, uri.port) { |http|
98
132
  http.request(req)
99
133
  }
100
134
  doc = REXML::Document.new res.body
101
- doc.elements.each("//api/array/songs") do |element|
102
- songs << element_to_song(element)
135
+ return if doc.elements[xml_element].nil?
136
+ doc.elements.collect(xml_element) do |element|
137
+ eval "#{item_class}.new(element)"
103
138
  end
104
- songs
105
139
  end
106
-
107
- protected
108
-
109
- def self.get_element_child(element, child, type = :text)
110
- return if element.elements[child].nil?
111
- child = element.elements[child][0].to_s
112
- return case type
113
- when :int then child.to_i
114
- when :float then child.to_f
115
- when :datetime then DateTime.parse(child)
116
- else child
140
+
141
+ def self.create_url(action, query_hash)
142
+ url = Yesradio::YESRADIO_SERVER + "/#{action}?type=xml"
143
+ query_hash.each do |name, value|
144
+ url = url + "&#{name}=" + CGI::escape(value.to_s) unless value.nil?
117
145
  end
118
-
146
+ url
119
147
  end
120
148
 
121
149
  end
122
-
data/yesradio.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{yesradio}
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Claudio Baccigalupo"]
@@ -25,10 +25,10 @@ Gem::Specification.new do |s|
25
25
  "features/step_definitions/yesradio_steps.rb",
26
26
  "features/support/env.rb",
27
27
  "features/yesradio.feature",
28
+ "lib/item.rb",
28
29
  "lib/main.rb",
29
30
  "lib/song.rb",
30
31
  "lib/station.rb",
31
- "lib/stations_search_criteria.rb",
32
32
  "lib/yesradio.rb",
33
33
  "test/test_helper.rb",
34
34
  "test/yesradio_test.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: claudiob-yesradio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claudio Baccigalupo
@@ -40,10 +40,10 @@ files:
40
40
  - features/step_definitions/yesradio_steps.rb
41
41
  - features/support/env.rb
42
42
  - features/yesradio.feature
43
+ - lib/item.rb
43
44
  - lib/main.rb
44
45
  - lib/song.rb
45
46
  - lib/station.rb
46
- - lib/stations_search_criteria.rb
47
47
  - lib/yesradio.rb
48
48
  - test/test_helper.rb
49
49
  - test/yesradio_test.rb
@@ -1,33 +0,0 @@
1
- #=============================================================================
2
- #
3
- # 2009 Claudio Baccigalupo
4
- #
5
- # Licensed under the Ruby License
6
- #
7
- #=============================================================================
8
-
9
- module Yesradio
10
- class StationsSearchCriteria
11
-
12
- attr_accessor :match, :freq, :mid, :genre, :loc, :max
13
-
14
- def initialize(options = {})
15
- options.each do |key, value|
16
- eval("@#{key} = '#{value.to_s}'")
17
- end
18
- end
19
-
20
- def to_query_params_string
21
- url = ''
22
- url = url + "&match=" + CGI::escape(@match) if !@match.nil?
23
- url = url + "&freq=" + CGI::escape(@freq) if !@freq.nil?
24
- url = url + "&mid=" + CGI::escape(@mid.to_s) if !@mid.nil?
25
- url = url + "&genre=" + CGI::escape(@genre) if !@genre.nil?
26
- url = url + "&loc=" + CGI::escape(@loc) if !@loc.nil?
27
- url = url + "&max=" + CGI::escape(@max.to_s) if !@max.nil?
28
- url
29
- end
30
- end
31
- end
32
-
33
-