eventfulapi 2.1.1 → 2.2.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.
Files changed (3) hide show
  1. data/README +2 -3
  2. data/lib/eventful/api.rb +178 -91
  3. metadata +4 -4
data/README CHANGED
@@ -5,6 +5,5 @@ calendars, and users.
5
5
  See http://api.eventful.com/ for general information about the API, and
6
6
  http://api.eventful.com/docs/libs/ruby/doc for documentation about the Ruby library.
7
7
 
8
- Copyright 2005-2007 EVDB, Inc. All rights reserved. This module is distributed
9
- under the same terms as Ruby itself (see
10
- http://www.ruby-lang.org/en/LICENSE.txt)
8
+ Copyright 2005-2007 EVDB, Inc. This module is distributed under the same terms
9
+ as Ruby itself (see http://www.ruby-lang.org/en/LICENSE.txt)
@@ -13,36 +13,89 @@
13
13
  # begin
14
14
  #
15
15
  # # Start an API session with a username and password
16
- # eventful = Eventful::API.new 'application_key',
17
- # 'user' => 'username',
18
- # 'password' => 'password'
16
+ # eventful = Eventful::API.new 'application_key',
17
+ # :user => 'username',
18
+ # :password => 'password'
19
19
  #
20
20
  # # Lookup an event by its unique id
21
21
  # event = eventful.call 'events/get',
22
- # 'id' => 'E0-001-001042544-7'
22
+ # :id => 'E0-001-001042544-7'
23
23
  #
24
24
  # puts "Event Title: #{event['title']}"
25
- #
25
+ #
26
26
  # # Get information about that event's venue
27
- # venue = eventful.call 'venues/get',
28
- # 'id' => event['venue_id']
27
+ # venue = eventful.call 'venues/get',
28
+ # :id => event['venue_id']
29
29
  #
30
30
  # puts "Venue: #{venue['name']}"
31
31
  #
32
32
  # rescue Eventful::APIError => e
33
- # puts "There was an error fetching the event: #{e}"
33
+ # puts "There was a problem with the API: #{e}"
34
+ # end
35
+ #
36
+ #
37
+ # == Another Example
38
+ #
39
+ # require 'rubygems'
40
+ # require 'eventful/api'
41
+ #
42
+ # # First, create our Eventful::API object
43
+ # eventful = Eventful::API.new 'application_key'
44
+ #
45
+ # loop do
46
+ # # Ask the user what and where to search
47
+ # puts "Search where? (Ex: San Diego)"
48
+ # print "? "
49
+ # location = gets.chomp
50
+ # puts "Search for what (Ex: music)"
51
+ # print "? "
52
+ # query = gets.chomp
53
+ #
54
+ # # This is the cool part!
55
+ # results = eventful.call 'events/search',
56
+ # :keywords => query,
57
+ # :location => location,
58
+ # :page_size => 5
59
+ #
60
+ # # If we couldn't find anything, ask the user again
61
+ # if results['events'].nil? then
62
+ # puts
63
+ # puts "Hmm. I couldn't find anything. Sorry."
64
+ # puts
65
+ # next
66
+ # end
67
+ #
68
+ # # Output the results
69
+ # results['events']['event'].each do |event|
70
+ # puts
71
+ # puts "http://eventful.com/events/" + event['id']
72
+ # puts event['title']
73
+ # puts " at " + event['venue_name']
74
+ # puts " on " + Time.parse(event['start_time']).strftime("%a, %b %d, %I:%M %p") if event['start_time']
75
+ # end
76
+ # puts
34
77
  # end
35
78
  #
36
79
  #
37
80
  # == API Key
38
81
  #
39
- # Use of the Eventful API requires an application key
82
+ # Use of the Eventful API requires an application key
40
83
  # (see http://api.eventful.com/keys for more information).
41
84
  #
42
85
  # == Change Notes
43
86
  #
44
87
  # === Eventful API
45
88
  #
89
+ # ==== Version 2.2.0
90
+ #
91
+ # - The authentication bug has been fixed, so I'm rolling back the workaround.
92
+ # - Documented the parameters for specifying alternative API servers when calling
93
+ # Eventful.new
94
+ # - The names of these keys have been changed to be a bit friendlier. The old
95
+ # keys will still work fine.
96
+ # - Hash keys to methods can now be Symbols, in addition to strings
97
+ # - A fun new example, just because
98
+ #
46
99
  # ==== Version 2.1.1
47
100
  #
48
101
  # - Includes a workaround fix for an authentication bug. This fix may be rolled
@@ -50,10 +103,10 @@
50
103
  #
51
104
  # ==== Version 2.1
52
105
  #
53
- # - As EVDB Inc. has been renamed Eventful Inc., the EVDB module has been
54
- # renamed Eventful, and the gem is now named eventfulapi. Support for the
106
+ # - As EVDB Inc. has been renamed Eventful Inc., the EVDB module has been
107
+ # renamed Eventful, and the gem is now named eventfulapi. Support for the
55
108
  # evdbapi gem is being discontinued; please use the eventfulapi gem from now on.
56
- # - Much better at throwing an error when a network or server problem happens,
109
+ # - Much better at throwing an error when a network or server problem happens,
57
110
  # rather than failing silently and mysteriously
58
111
  # - Documentation improvements
59
112
  #
@@ -63,7 +116,7 @@
63
116
  #
64
117
  # - Fixed a minor documentation error
65
118
  #
66
- # ==== Version 2.0
119
+ # ==== Version 2.0
67
120
  #
68
121
  # Version 2.0 of this library includes some significant changes which may not
69
122
  # be backwards compatible. Specifically:
@@ -78,9 +131,9 @@
78
131
  # == Information
79
132
  #
80
133
  # Status:: Stable
81
- # Version:: 2.1.1
134
+ # Version:: 2.2.0
82
135
  # Date:: 2007-03-24
83
- # Current Author:: Paul Knight (mailto:pknight@eventful.com)
136
+ # Current Author:: Paul Knight (mailto:paul@eventful.com)
84
137
  # Previous Authors:: Joe Auricchio
85
138
  # Copyright:: Copyright (C) 2005-2007 Eventful Inc.
86
139
  # License:: This code is distributed under the same terms as Ruby itself (see http://www.ruby-lang.org/en/LICENSE.txt)
@@ -104,8 +157,7 @@ require 'cgi'
104
157
  require 'net/http'
105
158
  require 'base64'
106
159
  require 'digest/md5'
107
- require 'open-uri'
108
- require 'rexml/document'
160
+
109
161
 
110
162
 
111
163
 
@@ -113,97 +165,140 @@ require 'rexml/document'
113
165
  module Eventful
114
166
 
115
167
 
116
-
168
+
117
169
  # Version descriptor of this library
118
- VERSION = '2.1'
119
-
170
+ VERSION = '2.2.0'
171
+
120
172
  # Default API server to connect to
121
- DEFAULT_API_SERVER = 'api.eventful.com' #:nodoc:
173
+ DEFAULT_SERVER = 'api.eventful.com' #:nodoc:
122
174
  # Default server port
123
- DEFAULT_API_PORT = 80 #:nodoc:
175
+ DEFAULT_PORT = 80 #:nodoc:
124
176
  # Default server path
125
- DEFAULT_API_ROOT = '/yaml/' #:nodoc:
126
-
177
+ DEFAULT_ROOT = '/yaml/' #:nodoc:
178
+
127
179
  # Our POST data boundary
128
180
  BOUNDARY = '1E666D29B5E749F6A145BE8A576049E6' #:nodoc:
129
181
  BOUNDARY_MARKER = "--#{BOUNDARY}" #:nodoc:
130
182
  BOUNDARY_END_MARKER = "--#{BOUNDARY}--" #:nodoc:
131
-
132
-
133
-
183
+
184
+
185
+
134
186
  # Parent Error used for all Eventful exceptions
135
187
  class Error < StandardError ; end
136
-
188
+
137
189
  # An error that may also include the YAML response from the server
138
190
  class APIError < Error
139
191
  attr_reader :response
140
-
192
+
141
193
  # Creates a new exception.
142
194
  def initialize(response)
143
195
  super
144
196
  @response = response
145
197
  end
146
-
198
+
147
199
  # The error string returned by the API call.
148
200
  def to_s
149
201
  "#{@response['string']}: #{@response['description']}"
150
202
  end
151
203
  end
152
-
153
-
154
-
204
+
205
+
206
+
155
207
  # A class for working with the Eventful API.
156
208
  class API
157
-
158
-
159
-
209
+
210
+
211
+
160
212
  # Create an object for working with the Eventful API. Working with the API
161
213
  # requires an application key, which can be obtained at http://api.eventful.com/keys/
162
214
  #
163
215
  # Options may be:
164
216
  #
165
- # <tt>'user'</tt>:: Authenticate as this user, required for some API methods. A password must also be specified.
166
- # <tt>'password'</tt>:: Password for user authentication.
217
+ # <tt>:user</tt>:: Authenticate as this user, required for some API methods. A password must also be specified.
218
+ # <tt>:password</tt>:: Password for user authentication.
219
+ #
220
+ # If both <tt>user</tt> and <tt>password</tt> are specified, then digest
221
+ # authenticatino will be used. Otherise, basic authentication will be used.
222
+ # Please note that basic authentication sends passwords in the clear.
223
+ # For more information, please see http://api.eventful.com/docs/auth
224
+ #
225
+ # ==== Testing Against Another Server
226
+ #
227
+ # For testing, you may use the following options for specifying a
228
+ # different API server:
229
+ #
230
+ # <tt>:server</tt>:: Hostname of the API server, default <tt>api.eventful.com</tt>
231
+ # <tt>:root</tt>:: Path to the root of all method calls, default <tt>/yaml/</tt>
232
+ # <tt>:port</tt>:: Server port, default <tt>80</tt>
233
+ #
234
+ # If the server is behind HTTP authentication, you can use:
235
+ #
236
+ # <tt>:http_user</tt>:: Username for HTTP authentication
237
+ # <tt>:http_password</tt>:: Password for HTTP authenciation
238
+ #
239
+ # Please note that none of these five options are needed for using the Eventful API.
240
+ #
241
+ # ==== Example
167
242
  #
168
- # Example:
169
- #
170
243
  # eventful = Eventful::API.new 'app_key',
171
- # 'user' => 'username',
172
- # 'password' => 'password'
244
+ # :user => 'username',
245
+ # :password => 'password'
173
246
  #
174
247
  def initialize(app_key, options = {})
175
- @api_server = options['api_server'] || DEFAULT_API_SERVER
176
- @api_root = options['api_root'] || DEFAULT_API_ROOT
177
- @api_port = options['api_port'] || DEFAULT_API_PORT
178
-
179
- @auth_user = options['auth_user']
180
- @auth_password = options['auth_password']
181
-
182
- @authentication = nil
183
-
248
+ # Grab our arguments
249
+
250
+ @server = find_option [:server, :api_server], options, DEFAULT_SERVER
251
+ @root = find_option [:root, :api_root], options, DEFAULT_ROOT
252
+ @port = find_option [:port, :api_port], options, DEFAULT_PORT
253
+
254
+ @http_user = find_option [:http_user, :auth_user], options
255
+ @http_password = find_option [:http_password, :auth_password], options
256
+
257
+ user = find_option [:user], options
258
+ password = find_option [:password], options
259
+
184
260
  # User authentication
185
- if (options['user'] && options['password'])
186
- nonce = get_nonce app_key
187
-
261
+ if user and password
262
+ # Get a nonce; we expect an error response here, so rescue the exception and continue
263
+ begin
264
+ response = call 'users/login',
265
+ :app_key => app_key
266
+ rescue APIError => error
267
+ raise unless error.response['nonce']
268
+ nonce = error.response['nonce']
269
+ end
270
+
188
271
  # Login with a hash of the nonce and our password
189
- login_hash = Digest::MD5.hexdigest("#{nonce}:#{Digest::MD5.hexdigest(options['password'])}")
190
- response = call 'users/login',
191
- 'app_key' => app_key,
192
- 'user' => options['user'],
193
- 'nonce' => nonce,
194
- 'response' => login_hash
195
-
272
+ login_hash = Digest::MD5.hexdigest "#{nonce}:#{Digest::MD5.hexdigest(password)}"
273
+ response = call 'users/login',
274
+ :app_key => app_key,
275
+ :user => user,
276
+ :nonce => nonce,
277
+ :response => login_hash
278
+
196
279
  # Store authentication information and use it for all future calls
197
- @authentication = { 'app_key' => app_key,
198
- 'user' => options['user'],
199
- 'user_key' => response['user_key'] }
280
+ @authentication = { :app_key => app_key,
281
+ :user => user,
282
+ :user_key => response['user_key'] }
200
283
  else
201
- @authentication = { 'app_key' => app_key }
284
+ @authentication = { :app_key => app_key }
285
+ end
286
+ end
287
+
288
+
289
+
290
+ # Search through a method argument Hash for specified named parameters
291
+ def find_option(names, arguments, default = nil) #:nodoc:
292
+ result = default
293
+ names.each do |name|
294
+ result = arguments[name] || arguments[name.to_s] || result
202
295
  end
296
+ return result
203
297
  end
204
298
 
205
299
 
206
-
300
+
301
+
207
302
  # Prepares the body of the POST request
208
303
  def prepare_post(params) #:nodoc:
209
304
  content = ""
@@ -215,7 +310,7 @@ module Eventful
215
310
  content += "Content-Transfer-Encoding: binary\r\n\r\n"
216
311
  content += open(value) { |f| f.read } + "\r\n"
217
312
  else
218
- content += "Content-Disposition: form-data; name=\"#{CGI::escape(key.to_s)}\";\r\n\r\n#{value}\r\n"
313
+ content += "Content-Disposition: form-data; name=\"#{CGI::escape(key.to_s)}\";\r\n\r\n#{value}\r\n"
219
314
  end
220
315
  end
221
316
  content += BOUNDARY_END_MARKER
@@ -228,50 +323,42 @@ module Eventful
228
323
  # a hash. Please see the Eventful API documentation (http://api.eventful.com/docs)
229
324
  # for information about methods and their parameters.
230
325
  #
231
- # Example:
326
+ # ==== Example
232
327
  #
233
328
  # event = eventful.call 'events/get',
234
- # 'id' => 'E0-001-001042544-7'
329
+ # :id => 'E0-001-001042544-7'
235
330
  #
236
331
  def call(method, params = {})
237
332
  # Use available auth tokens
238
333
  params.merge! @authentication if @authentication
239
334
 
240
- response = Net::HTTP.start(@api_server, @api_port) do |connection|
241
- if @auth_user && @auth_password then
335
+ response = Net::HTTP.start(@server, @port) do |connection|
336
+ if @http_user and @http_password then
242
337
  connection.post(
243
- "#{@api_root}#{method}",
244
- prepare_post(params),
245
- "Content-type" => "multipart/form-data; boundary=#{BOUNDARY} ",
246
- "Authorization" => Base64.encode64("#{@auth_user}:#{@auth_password}"))
338
+ "#{@root}#{method}",
339
+ prepare_post(params),
340
+ "Content-type" => "multipart/form-data; boundary=#{BOUNDARY} ",
341
+ "Authorization" => Base64.encode64("#{@http_user}:#{@http_password}"))
247
342
  else
248
343
  connection.post(
249
- "#{@api_root}#{method}",
250
- prepare_post(params),
344
+ "#{@root}#{method}",
345
+ prepare_post(params),
251
346
  "Content-type" => "multipart/form-data; boundary=#{BOUNDARY} ")
252
347
  end
253
348
  end
254
-
349
+
255
350
  # Raise an exception if we didn't get a 2xx response code
256
351
  response.value
257
-
352
+
258
353
  yaml = YAML::load response.body
259
-
354
+
260
355
  # Raise an error if we got an API error
261
356
  raise APIError.new(yaml['error']) if yaml['error']
262
357
 
263
358
  return yaml
264
359
  end
265
-
266
- # Only intended for the first users/login authentication call
267
- def get_nonce(app_key) # :nodoc:
268
- open "http://#{@api_server}/rest/users/login?app_key=#{CGI::escape app_key}" do |f|
269
- (REXML::Document.new f.read).elements["error/nonce"].text
270
- end
271
- end
272
-
273
-
274
-
360
+
361
+
362
+
275
363
  end # class API
276
364
  end # module Eventful
277
-
metadata CHANGED
@@ -3,13 +3,13 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: eventfulapi
5
5
  version: !ruby/object:Gem::Version
6
- version: 2.1.1
7
- date: 2007-04-24 00:00:00 -07:00
6
+ version: 2.2.0
7
+ date: 2007-05-14 00:00:00 -07:00
8
8
  summary: Interface to the Eventful API. http://eventful.com
9
9
  require_paths:
10
10
  - lib
11
- email: pknight@eventful.com
12
- homepage: http://api.evdb.com
11
+ email: paul@eventful.com
12
+ homepage: http://api.eventful.com
13
13
  rubyforge_project:
14
14
  description:
15
15
  autorequire: eventful/api