bandsintown 0.1.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.
@@ -0,0 +1,18 @@
1
+ == 0.1.1 2009-09-08
2
+ * fixed escaping issue with / and ? in artist urls
3
+
4
+ == 0.1.0 2009-09-05
5
+ * Full Bandsintown API support
6
+ * Added Artists - Events API method
7
+ * Added Events - Recommended API method
8
+ * Updated Bandsintown::Connection class
9
+ * Added attributes for on_sale_datetime and ticket_status to Bandsintown::Event class
10
+ * Lots of documentation
11
+
12
+ == 0.0.2 2009-06-03
13
+ * Added the daily events API method
14
+
15
+ == 0.0.1 2009-02-20
16
+
17
+ * 1 major enhancement:
18
+ * Initial release
@@ -0,0 +1,27 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/bandsintown.rb
6
+ lib/bandsintown/artist.rb
7
+ lib/bandsintown/base.rb
8
+ lib/bandsintown/connection.rb
9
+ lib/bandsintown/event.rb
10
+ lib/bandsintown/venue.rb
11
+ script/console
12
+ script/destroy
13
+ script/generate
14
+ script/txt2html
15
+ spec/bandsintown/artist_spec.rb
16
+ spec/bandsintown/base_spec.rb
17
+ spec/bandsintown/connection_spec.rb
18
+ spec/bandsintown/event_spec.rb
19
+ spec/bandsintown/venue_spec.rb
20
+ spec/bandsintown_spec.rb
21
+ spec/spec.opts
22
+ spec/spec_helper.rb
23
+ website/index.html
24
+ website/index.txt
25
+ website/javascripts/rounded_corners_lite.inc.js
26
+ website/stylesheets/screen.css
27
+ website/template.html.erb
@@ -0,0 +1,88 @@
1
+ = bandsintown
2
+
3
+ == Description
4
+
5
+ Bandsintown.com API gem
6
+
7
+ A Ruby library for accessing the Bandsintown API.
8
+
9
+ The Bandsintown API lets any developer access the largest database of upcoming concert listings and concert tickets in the world.
10
+
11
+ For more information visit http://www.bandsintown.com/api/requests.
12
+
13
+ == Installing
14
+
15
+ sudo gem install bandsintown
16
+
17
+ == Usage
18
+
19
+ === Requiring
20
+
21
+ require 'bandsintown'
22
+
23
+ === Setting the bandsintown app_id parameter
24
+
25
+ Bandsintown.app_id = 'YOUR_APP_ID'
26
+
27
+ === Find all upcoming events for a given artist
28
+
29
+ artist = Bandsintown::Artist.new("The Killers")
30
+ events = artist.events
31
+
32
+ === Find events this week around Boston, MA
33
+
34
+ events = Bandsintown::Event.search({
35
+ :location => 'Boston, MA',
36
+ :start_date => Time.now,
37
+ :end_date => 1.week.from_now
38
+ })
39
+
40
+ === Find events this week for Mos Def and Talib Kweli
41
+
42
+ events = Bandsintown::Event.search({
43
+ :artists => ['Mos Def', 'Talib Kweli'],
44
+ :start_date => Time.now,
45
+ :end_date => 1.week.from_now
46
+ })
47
+
48
+ === Find recommended events around Boston, MA for fans of Led Zeppelin
49
+
50
+ events = Bandsintown::Event.recommended({
51
+ :artists => ['Led Zeppelin'],
52
+ :location => 'Boston, MA'
53
+ })
54
+
55
+ === find events added/updated/deleted within the last day
56
+
57
+ events = Bandsintown::Event.daily
58
+
59
+ == Links
60
+
61
+ * RDoc[http://bandsintown.rubyforge.org/rdoc]
62
+ * {Bandsintown.com API Documentation}[http://www.bandsintown.com/api/requests]
63
+ * Github[http://github.com/bandsintown/bandsintown]
64
+
65
+ == LICENSE:
66
+
67
+ (The MIT License)
68
+
69
+ Copyright (c) 2009 Mike Costanza
70
+
71
+ Permission is hereby granted, free of charge, to any person obtaining
72
+ a copy of this software and associated documentation files (the
73
+ 'Software'), to deal in the Software without restriction, including
74
+ without limitation the rights to use, copy, modify, merge, publish,
75
+ distribute, sublicense, and/or sell copies of the Software, and to
76
+ permit persons to whom the Software is furnished to do so, subject to
77
+ the following conditions:
78
+
79
+ The above copyright notice and this permission notice shall be
80
+ included in all copies or substantial portions of the Software.
81
+
82
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
83
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
84
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
85
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
86
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
87
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
88
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/bandsintown'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('bandsintown', Bandsintown::VERSION) do |p|
7
+ p.developer('Mike Costanza', 'mike@bandsintown.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.rubyforge_name = p.name # TODO this is default value
10
+ p.extra_deps = [
11
+ ['activesupport','>= 2.0.2'],
12
+ ['json', '>= 1.1.3']
13
+ ]
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
@@ -0,0 +1,27 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ require 'open-uri'
6
+ require 'cgi'
7
+ require 'activesupport'
8
+ require 'json'
9
+
10
+ require 'bandsintown/base'
11
+ require 'bandsintown/connection'
12
+ require 'bandsintown/artist'
13
+ require 'bandsintown/event'
14
+ require 'bandsintown/venue'
15
+
16
+ module Bandsintown
17
+ VERSION = '0.1.1'
18
+ class APIError < StandardError; end
19
+ class << self
20
+ # All Bandsintown API requests require an app_id parameter for identification.
21
+ # See http://www.bandsintown.com/api/authentication for more information.
22
+ #
23
+ attr_accessor :app_id
24
+ end
25
+ end
26
+
27
+
@@ -0,0 +1,49 @@
1
+ module Bandsintown
2
+ class Artist < Base
3
+
4
+ attr_accessor :name, :events
5
+
6
+ def initialize(name, url = nil)
7
+ @name = name
8
+ @bandsintown_url = url || build_bandsintown_url
9
+ end
10
+
11
+ #Returns an array of Bandsintown::Event objects for each of the artist's upcoming events available through bandsintown.com.
12
+ #See http://www.bandsintown.com/api/requests#artists-events for more information.
13
+ #
14
+ #====example:
15
+ # artist = Bandsintown::Artist.new("Little Brother")
16
+ # upcoming_little_brother_events = artist.events
17
+ #
18
+ def events
19
+ return @events unless @events.blank?
20
+ @events = self.class.request_and_parse("#{api_name}/events").map { |event| Bandsintown::Event.build_from_json(event) }
21
+ end
22
+
23
+ # name used in api requests. / and ? must be double escaped.
24
+ #
25
+ def api_name
26
+ name = @name.dup
27
+ name.gsub!('/', CGI.escape('/'))
28
+ name.gsub!('?', CGI.escape('?'))
29
+ URI.escape(name)
30
+ end
31
+
32
+ def self.resource_path
33
+ "artists"
34
+ end
35
+
36
+ private
37
+
38
+ def build_bandsintown_url
39
+ name = @name.dup
40
+ name.gsub!('&', 'And')
41
+ name.gsub!('+', 'Plus')
42
+ name = name.split.map { |w| w.capitalize }.join if name =~ /\s/
43
+ name.gsub!('/', CGI.escape('/'))
44
+ name.gsub!('?', CGI.escape('?'))
45
+ "http://www.bandsintown.com/#{URI.escape(name)}"
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,31 @@
1
+ module Bandsintown
2
+ class Base
3
+
4
+ attr_accessor :bandsintown_url
5
+
6
+ def self.request(api_method, args={})
7
+ self.connection.request(self.resource_path, api_method, args)
8
+ end
9
+
10
+ def self.connection
11
+ @connection ||= Bandsintown::Connection.new("http://api.bandsintown.com")
12
+ end
13
+
14
+ def self.parse(response)
15
+ json = JSON.parse(response)
16
+ check_for_errors(json)
17
+ json
18
+ end
19
+
20
+ def self.check_for_errors(json)
21
+ if json.is_a?(Hash) && json.has_key?("errors")
22
+ raise Bandsintown::APIError.new(json["errors"].join(", "))
23
+ end
24
+ end
25
+
26
+ def self.request_and_parse(api_method, args={})
27
+ parse(request(api_method, args))
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ module Bandsintown
2
+ class Connection
3
+ attr_accessor :base_url
4
+
5
+ def initialize(base_url)
6
+ @base_url = base_url
7
+ end
8
+
9
+ def request(resource_path, method_path, args = {})
10
+ request_url = "#{@base_url}/#{resource_path}/#{method_path}?#{encode(args.symbolize_keys)}"
11
+ begin
12
+ open(request_url).read
13
+ rescue OpenURI::HTTPError => error_response
14
+ error_response.io.read
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def encode(args = {})
21
+ start_date = args.delete(:start_date)
22
+ end_date = args.delete(:end_date)
23
+ if start_date && end_date
24
+ start_date = start_date.strftime("%Y-%m-%d") unless start_date.is_a?(String)
25
+ end_date = end_date.strftime("%Y-%m-%d") unless end_date.is_a?(String)
26
+ args[:date] = "#{start_date},#{end_date}"
27
+ elsif args.has_key?(:date)
28
+ args[:date] = args[:date].strftime("%Y-%m-%d") unless args[:date].is_a?(String)
29
+ end
30
+ args[:format] = "json"
31
+ args[:app_id] = Bandsintown.app_id
32
+ args.to_param
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,102 @@
1
+ module Bandsintown
2
+ class Event < Base
3
+
4
+ attr_accessor :bandsintown_id, :datetime, :ticket_url, :artists, :venue, :status, :ticket_status, :on_sale_datetime
5
+
6
+ def tickets_available?
7
+ ticket_status == "available"
8
+ end
9
+
10
+ #Returns an array of Bandsintown::Event objects matching the options passed.
11
+ #See http://www.bandsintown.com/api/requests#events-search for more information.
12
+ #====options:
13
+ # :artists - an array of artist names or music brainz id's (formatted as 'mbid_<id>').
14
+ # :location - a string with one of the following formats:
15
+ # * 'city, state' for United States and Canada
16
+ # * 'city, country' for other countries
17
+ # * 'latitude,longitude'
18
+ # * ip address - will use the location of the passed ip address
19
+ # * 'use_geoip' - will use the location of the ip address that made the request
20
+ # :radius - a number in miles. API default is 25, maximum is 150.
21
+ # :date - use one of the following formats:
22
+ # * 'upcoming' - all upcoming dates, this is the API default.
23
+ # * single date
24
+ # * String formatted 'yyyy-mm-dd'
25
+ # * Time/Date/DateTime object (anything that responds to strftime)
26
+ # * date range
27
+ # * String formatted 'yyyy-mm-dd,yyyy-mm-dd'
28
+ # * alternatively use :start_date and :end_date with 'yyyy-mm-dd' Strings or Time/Date/DateTime objects.
29
+ # :per_page - number of results per response. API default is 50, maximum is 100.
30
+ # :page - offset for paginated results. API default is 1.
31
+ #
32
+ #====notes:
33
+ #:location or :artists is required for this request, all other arguments are optional.
34
+ #
35
+ #====examples:
36
+ #All concerts (first page w/ 50 results) in New York City for The Roots or Slum Village within the next 30 days (using Date objects):
37
+ # Bandsintown::Event.search(:location => "New York, NY", :artists => ["The Roots", "Slum Village"], :start_date => Date.today, :end_date => Date.today + 30)
38
+ #
39
+ #All concerts (first page w/ 50 results) on Dec 31 2009 (using formatted date string) within 100 miles of London:
40
+ # Bandsintown::Event.search(:location => "London, UK", :radius => 100, :date => "2009-12-31")
41
+ #
42
+ #Second page of all concerts near the request's ip address within in the next month, using Time objects and 100 results per page:
43
+ # Bandsintown::Event.search(:start_date => Time.now, :end_date => 1.month.from_now, :per_page => 100, :page => 2, :location => "use_geoip")
44
+ #
45
+ def self.search(options = {})
46
+ events = []
47
+ self.request_and_parse("search", options).each { |event| events << Bandsintown::Event.build_from_json(event) }
48
+ events
49
+ end
50
+
51
+ #Returns an array of Bandsintown::Event objects for all events added to Bandsintown within the last day (updated at 12:00 PM EST daily).
52
+ #See http://www.bandsintown.com/api/requests#events-daily for more information.
53
+ #
54
+ def self.daily
55
+ events = []
56
+ self.request_and_parse("daily").each { |event| events << Bandsintown::Event.build_from_json(event) }
57
+ events
58
+ end
59
+
60
+ #Returns an array of Bandsintown::Event objects matching the options passed.
61
+ #See http://www.bandsintown.com/api/requests#events-recommended for more information.
62
+ #====options:
63
+ #All options are the same as Bandsintown::Event.search with the following extra option:
64
+ # :only_recs - boolean for whether to include events with the artists from the :artists option. default is false.
65
+ #
66
+ #====notes:
67
+ #:location and :artists are required for this request, all other arguments are optional.
68
+ #
69
+ #====examples:
70
+ #All concerts (first page w/ 50 results) in Boston, MA recommended for fans of Metallica, including Metallica concerts
71
+ # Bandsintown::Event.recommended(:location => "Boston, MA", :artists => ["Metallica"])
72
+ #
73
+ #All concerts (first page w/ 50 results) on Dec 31 2009 within 100 miles of London recommended for fans of Usher and Lil Wayne, excluding Usher and Lil Wayne concerts
74
+ # Bandsintown::Event.recommended(:location => "London, UK", :radius => 100, :date => "2009-12-31", :artists => ["Usher", "Lil Wayne"], :only_recs => true)
75
+ #
76
+ def self.recommended(options = {})
77
+ events = []
78
+ self.request_and_parse("recommended", options).each { |event| events << Bandsintown::Event.build_from_json(event) }
79
+ events
80
+ end
81
+
82
+ def self.resource_path
83
+ "events"
84
+ end
85
+
86
+ def self.build_from_json(json_hash)
87
+ event = Bandsintown::Event.new()
88
+ event.bandsintown_id = json_hash["id"]
89
+ event.bandsintown_url = json_hash["url"]
90
+ event.datetime = Time.parse(json_hash["datetime"])
91
+ event.ticket_url = json_hash["ticket_url"]
92
+ event.status = json_hash["status"]
93
+ event.ticket_status = json_hash["ticket_status"]
94
+ event.on_sale_datetime = Time.parse(json_hash["on_sale_datetime"]) rescue nil
95
+ event.venue = Bandsintown::Venue.new(json_hash["venue"])
96
+ event.artists = []
97
+ json_hash["artists"].each { |artist| event.artists << Bandsintown::Artist.new(artist["name"], artist["url"]) }
98
+ event
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,18 @@
1
+ module Bandsintown
2
+ class Venue < Base
3
+
4
+ attr_accessor :name, :bandsintown_id, :region, :city, :country, :latitude, :longitude
5
+
6
+ def initialize(args={})
7
+ @name = args["name"]
8
+ @bandsintown_url = args["url"]
9
+ @bandsintown_id = args["id"]
10
+ @region = args["region"]
11
+ @city = args["city"]
12
+ @country = args["country"]
13
+ @latitude = args["latitude"]
14
+ @longitude = args["longitude"]
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/bandsintown.rb'}"
9
+ puts "Loading bandsintown gem"
10
+ exec "#{irb} #{libs} --simple-prompt"