jbgutierrez-delicious_api 1.0.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.
- data/README.textile +136 -0
- data/delicious_api.gemspec +31 -0
- data/lib/delicious_api.rb +54 -0
- data/lib/delicious_api/base.rb +67 -0
- data/lib/delicious_api/bookmark.rb +162 -0
- data/lib/delicious_api/bundle.rb +43 -0
- data/lib/delicious_api/extensions.rb +5 -0
- data/lib/delicious_api/extensions/hash.rb +6 -0
- data/lib/delicious_api/tag.rb +52 -0
- data/lib/delicious_api/wrapper.rb +307 -0
- data/spec/custom_macros.rb +23 -0
- data/spec/custom_matchers.rb +5 -0
- data/spec/delicious_api_spec.rb +7 -0
- data/spec/delicious_api_spec/base_spec.rb +9 -0
- data/spec/delicious_api_spec/bookmark_spec.rb +177 -0
- data/spec/delicious_api_spec/bundle_spec.rb +76 -0
- data/spec/delicious_api_spec/tag_spec.rb +78 -0
- data/spec/delicious_api_spec/wrapper_spec.rb +431 -0
- data/spec/spec_helper.rb +21 -0
- metadata +105 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
|
2
|
+
|
|
3
|
+
module DeliciousApi
|
|
4
|
+
class Bundle < Base
|
|
5
|
+
|
|
6
|
+
# Bundle name
|
|
7
|
+
attr_accessor :name
|
|
8
|
+
|
|
9
|
+
# Tags <tt>Array</tt>
|
|
10
|
+
attr_accessor :tags
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Bundle initialize method
|
|
14
|
+
# ==== Parameters
|
|
15
|
+
# * <tt>name</tt> - Bundle name
|
|
16
|
+
# * <tt>tags</tt> - An optional <tt>Array</tt> of tags
|
|
17
|
+
# ==== Result
|
|
18
|
+
# An new instance of the current class
|
|
19
|
+
def initialize(name, tags=[])
|
|
20
|
+
@name = name
|
|
21
|
+
@tags = tags
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Retrieves a list of tag bundles from Delicious
|
|
25
|
+
# ==== Parameters
|
|
26
|
+
# * <tt>limit</tt> - An integer determining the limit on the number of tag bundles that should be returned.
|
|
27
|
+
def self.all(limit = 10)
|
|
28
|
+
self.wrapper.get_all_bundles(limit)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Updates a tag bundle at Delicious
|
|
32
|
+
def save
|
|
33
|
+
validate_presence_of :name, :tags
|
|
34
|
+
wrapper.set_bundle(@name, @tags.join(' ')) || raise(OperationFailed)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Deletes a tag bundle from Delicious
|
|
38
|
+
def delete
|
|
39
|
+
validate_presence_of :name
|
|
40
|
+
wrapper.delete_bundle(@name) || raise(OperationFailed)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
|
2
|
+
|
|
3
|
+
module DeliciousApi
|
|
4
|
+
class Tag < Base
|
|
5
|
+
|
|
6
|
+
# Tag name
|
|
7
|
+
attr_accessor :name
|
|
8
|
+
|
|
9
|
+
# An alias for the tag name
|
|
10
|
+
alias :tag :name
|
|
11
|
+
|
|
12
|
+
# Number of times used
|
|
13
|
+
attr_reader :count
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Tag initialize method
|
|
17
|
+
# ==== Parameters
|
|
18
|
+
# * <tt>name</tt> - Tag name
|
|
19
|
+
# * <tt>params</tt> - An optional <tt>Hash</tt> containing any combination of the instance attributes
|
|
20
|
+
# ==== Result
|
|
21
|
+
# An new instance of the current class
|
|
22
|
+
def initialize(name, params = {})
|
|
23
|
+
params.symbolize_keys!.assert_valid_keys(:name, :tag, :count)
|
|
24
|
+
params.merge!(:name => name, :original_name => name)
|
|
25
|
+
assign params
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Retrieves a list of tags and number of times used from Delicious
|
|
29
|
+
def self.all
|
|
30
|
+
self.wrapper.get_all_tags
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Deletes a tag from Delicious
|
|
34
|
+
def delete
|
|
35
|
+
validate_presence_of :name
|
|
36
|
+
wrapper.delete_tag(@name) || raise(OperationFailed)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Updates a tag name at Delicious (if necessary)
|
|
40
|
+
def save
|
|
41
|
+
validate_presence_of :name
|
|
42
|
+
unless @original_name == @name
|
|
43
|
+
wrapper.rename_tag(@original_name, @name) || raise(OperationFailed)
|
|
44
|
+
@original_name = @name
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
protected
|
|
49
|
+
attr_accessor :original_name
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
require 'hpricot'
|
|
2
|
+
require 'net/http'
|
|
3
|
+
require 'net/https'
|
|
4
|
+
require 'uri'
|
|
5
|
+
|
|
6
|
+
module DeliciousApi
|
|
7
|
+
|
|
8
|
+
class HTTPError < DeliciousApiError; end
|
|
9
|
+
|
|
10
|
+
class Wrapper
|
|
11
|
+
|
|
12
|
+
# del.icio.us account username
|
|
13
|
+
attr_reader :user
|
|
14
|
+
|
|
15
|
+
# del.icio.us account password
|
|
16
|
+
attr_reader :password
|
|
17
|
+
|
|
18
|
+
# request user agent
|
|
19
|
+
attr_reader :user_agent
|
|
20
|
+
|
|
21
|
+
# requests time gap
|
|
22
|
+
attr_reader :waiting_time_gap
|
|
23
|
+
|
|
24
|
+
# http client
|
|
25
|
+
attr_reader :http_client
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Wrapper initialize method
|
|
29
|
+
# ==== Parameters
|
|
30
|
+
# * <tt>user</tt> - Delicious username
|
|
31
|
+
# * <tt>password</tt> - Delicious password
|
|
32
|
+
# * <tt>options</tt> - A <tt>Hash</tt> containing any of the following:
|
|
33
|
+
# - <tt>user_agent</tt> - User agent to sent to the server.
|
|
34
|
+
# - <tt>waiting_time_gap</tt> - Time gap between requests. By default is set to 1.
|
|
35
|
+
# ==== Result
|
|
36
|
+
# An new instance of the current class
|
|
37
|
+
def initialize(user, password, options = {})
|
|
38
|
+
raise ArgumentError if (user.nil? || password.nil?)
|
|
39
|
+
options.assert_valid_keys(:user_agent, :waiting_time_gap)
|
|
40
|
+
@user = user
|
|
41
|
+
@password = password
|
|
42
|
+
@user_agent = options[:user_agent] || default_user_agent
|
|
43
|
+
@waiting_time_gap = options[:waiting_time_gap] || 1
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# API URL to add a new bookmark
|
|
47
|
+
API_URL_ADD_BOOKMARK = '/v1/posts/add?'
|
|
48
|
+
# API URL to delete an existing bookmark
|
|
49
|
+
API_URL_DELETE_BOOKMARK = '/v1/posts/delete?'
|
|
50
|
+
# API URL to get a collection of bookmarks filtered by date
|
|
51
|
+
API_URL_GET_BOOKMARKS_BY_DATE = '/v1/posts/get?'
|
|
52
|
+
# API URL to get the most recent bookmarks
|
|
53
|
+
API_URL_RECENT_BOOKMARKS = '/v1/posts/recent?'
|
|
54
|
+
# API URL to get all the bookmarks
|
|
55
|
+
API_URL_ALL_BOOKMARKS = '/v1/posts/all?'
|
|
56
|
+
# API URL to get all the tag
|
|
57
|
+
API_URL_ALL_TAGS = '/v1/tags/get'
|
|
58
|
+
# API URL to rename an existing tag
|
|
59
|
+
API_URL_RENAME_TAG = '/v1/tags/rename?'
|
|
60
|
+
# API URL to delete an existing tag
|
|
61
|
+
API_URL_DELETE_TAG = '/v1/tags/delete?'
|
|
62
|
+
# API URL to get popular, recommended and network tags for a particular url
|
|
63
|
+
API_URL_SUGGEST_TAG = '/v1/posts/suggest?'
|
|
64
|
+
# API URL to get all of a user's bundles.
|
|
65
|
+
API_URL_ALL_BUNDLES = '/v1/tags/bundles/all?'
|
|
66
|
+
# API URL to set a tag bundle
|
|
67
|
+
API_URL_SET_BUNDLE = '/v1/tags/bundles/set?'
|
|
68
|
+
# API URL to delete an existing bundle
|
|
69
|
+
API_URL_DELETE_BUNDLE = '/v1/tags/bundles/delete?'
|
|
70
|
+
|
|
71
|
+
##
|
|
72
|
+
# Add a bookmark to Delicious
|
|
73
|
+
# ==== Parameters
|
|
74
|
+
# * <tt>url</tt> - the url of the item.
|
|
75
|
+
# * <tt>description</tt> - the description of the item.
|
|
76
|
+
# * <tt>options</tt> - A <tt>Hash</tt> containing any of the following:
|
|
77
|
+
# - <tt>extended</tt> - notes for the item.
|
|
78
|
+
# - <tt>tags</tt> - tags for the item (space delimited).
|
|
79
|
+
# - <tt>dt</tt> - datestamp of the item (format "CCYY-MM-DDThh:mm:ssZ"). Requires a LITERAL "T" and "Z" like in ISO8601 at http://www.cl.cam.ac.uk/~mgk25/iso-time.html for example: "1984-09-01T14:21:31Z"
|
|
80
|
+
# - <tt>replace=no</tt> - don't replace bookmark if given url has already been posted.
|
|
81
|
+
# - <tt>shared=no</tt> - make the item private
|
|
82
|
+
# ==== Result
|
|
83
|
+
# * <tt>true</tt> if the bookmark was successfully added
|
|
84
|
+
# * <tt>false</tt> if the addition failed
|
|
85
|
+
def add_bookmark(url, description, options = {})
|
|
86
|
+
options.assert_valid_keys(:extended, :tags, :dt, :replace, :shared)
|
|
87
|
+
options[:url], options[:description] = url, description
|
|
88
|
+
doc = process_request(API_URL_ADD_BOOKMARK + options.to_query)
|
|
89
|
+
doc.at('result')['code'] == 'done'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# Delete a bookmark from Delicious
|
|
94
|
+
# ==== Parameters
|
|
95
|
+
# * <tt>url</tt> - the url of the item.
|
|
96
|
+
# ==== Result
|
|
97
|
+
# * <tt>true</tt> if the bookmark was successfully deleted
|
|
98
|
+
# * <tt>false</tt> if the deletion failed
|
|
99
|
+
def delete_bookmark(url)
|
|
100
|
+
options = { :url => url }
|
|
101
|
+
doc = process_request(API_URL_DELETE_BOOKMARK + options.to_query)
|
|
102
|
+
doc.at('result')['code'] == 'done' || doc.at('result')['code'] == 'item not found'
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
##
|
|
106
|
+
# Returns one or more bookmarks on a single day matching the arguments. If no date or url is given, most recent date will be used.
|
|
107
|
+
# ==== Parameters
|
|
108
|
+
# * <tt>dt</tt> - Filter by this date, defaults to the most recent date on which bookmarks were saved.
|
|
109
|
+
# * <tt>options</tt> - A <tt>Hash</tt> containing any of the following:
|
|
110
|
+
# - <tt>tag</tt> - [TAG,TAG,...TAG] Filter by this tag.
|
|
111
|
+
# - <tt>url</tt> - Fetch a bookmark for this URL, regardless of date.
|
|
112
|
+
# - <tt>hashes</tt> - [MD5,MD5,...,MD5] Fetch multiple bookmarks by one or more URL MD5s regardless of date, separated by URL-encoded spaces (ie. '+').
|
|
113
|
+
# - <tt>meta=yes</tt> - Include change detection signatures on each item in a 'meta' attribute. Clients wishing to maintain a synchronized local store of bookmarks should retain the value of this attribute - its value will change when any significant field of the bookmark changes.
|
|
114
|
+
# ==== Result
|
|
115
|
+
# An <tt>Array</tt> of <tt>Bookmarks</tt> matching the criteria
|
|
116
|
+
def get_bookmarks_by_date(dt, options)
|
|
117
|
+
options = { :dt => dt } unless dt.nil?
|
|
118
|
+
options.assert_valid_keys(:tag, :dt, :url, :hashes, :meta)
|
|
119
|
+
doc = process_request(API_URL_GET_BOOKMARKS_BY_DATE + options.to_query)
|
|
120
|
+
(doc/'posts/post').collect{ |post| Bookmark.new(post['href'], post.attributes) }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
##
|
|
124
|
+
# Returns a <tt>Bookmark</tt> for the <tt>url</tt>
|
|
125
|
+
# ==== Parameters
|
|
126
|
+
# * <tt>url</tt> - Fetch a bookmark for this URL.
|
|
127
|
+
# ==== Result
|
|
128
|
+
# A <tt>Bookmark</tt> matching the criteria or nil
|
|
129
|
+
def get_bookmark_by_url(url)
|
|
130
|
+
get_bookmarks_by_date(nil, :url=> url).first
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
##
|
|
134
|
+
# Returns a list of the most recent bookmarks, filtered by argument. Maximum 100.
|
|
135
|
+
# ==== Parameters
|
|
136
|
+
# * <tt>tag</tt> - Filter by this tag.
|
|
137
|
+
# * <tt>count</tt> - Number of items to retrieve (Default:15, Maximum:100).
|
|
138
|
+
# ==== Result
|
|
139
|
+
# An <tt>Array</tt> of <tt>Bookmarks</tt> matching the criteria
|
|
140
|
+
def get_recent_bookmarks(options = {})
|
|
141
|
+
options.assert_valid_keys(:tag, :count)
|
|
142
|
+
doc = process_request(API_URL_RECENT_BOOKMARKS + options.to_query)
|
|
143
|
+
(doc/'posts/post').collect{ |post| Bookmark.new(post['href'], post.attributes) }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
##
|
|
147
|
+
# Returns a list with all the bookmarks, filtered by argument.
|
|
148
|
+
# ==== Parameters
|
|
149
|
+
# * <tt>options</tt> - A <tt>Hash</tt> containing any of the following:
|
|
150
|
+
# - <tt>tag</tt> - Filter by this tag.
|
|
151
|
+
# - <tt>start</tt> - Start returning bookmarks this many results into the set.
|
|
152
|
+
# - <tt>results</tt> - Return this many results
|
|
153
|
+
# - <tt>fromdt</tt> - Filter for posts on this date or later (format "CCYY-MM-DDThh:mm:ssZ"). Requires a LITERAL "T" and "Z" like in ISO8601 at http://www.cl.cam.ac.uk/~mgk25/iso-time.html for example: "1984-09-01T14:21:31Z"
|
|
154
|
+
# - <tt>todt</tt> - Return this many results (format "CCYY-MM-DDThh:mm:ssZ"). Requires a LITERAL "T" and "Z" like in ISO8601 at http://www.cl.cam.ac.uk/~mgk25/iso-time.html for example: "1984-09-01T14:21:31Z"
|
|
155
|
+
# - <tt>meta=yes</tt> - Include change detection signatures on each item in a 'meta' attribute. Clients wishing to maintain a synchronized local store of bookmarks should retain the value of this attribute - its value will change when any significant field of the bookmark changes.
|
|
156
|
+
# ==== Result
|
|
157
|
+
# An <tt>Array</tt> of <tt>Bookmarks</tt> matching the criteria
|
|
158
|
+
def get_all_bookmarks(options = {})
|
|
159
|
+
options.assert_valid_keys(:tag, :start, :results, :fromdt, :todt, :meta)
|
|
160
|
+
doc = process_request(API_URL_ALL_BOOKMARKS + options.to_query)
|
|
161
|
+
(doc/'posts/post').collect{ |post| Bookmark.new(post['href'], post.attributes) }
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
##
|
|
165
|
+
# Returns a list of tags and number of times used by a user.
|
|
166
|
+
# ==== Result
|
|
167
|
+
# An <tt>Array</tt> of <tt>Tags</tt>
|
|
168
|
+
def get_all_tags
|
|
169
|
+
doc = process_request(API_URL_ALL_TAGS)
|
|
170
|
+
(doc/'tags/tag').collect{ |tag| Tag.new(tag['tag'], tag.attributes) }
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
##
|
|
174
|
+
# Rename an existing tag with a new tag name.
|
|
175
|
+
# ==== Parameters
|
|
176
|
+
# * <tt>old_name</tt> - Original tag name.
|
|
177
|
+
# * <tt>new_name</tt> - New tag name.
|
|
178
|
+
# ==== Result
|
|
179
|
+
# * <tt>true</tt> if the tag was successfully renamed
|
|
180
|
+
# * <tt>false</tt> otherwise
|
|
181
|
+
def rename_tag(old_name, new_name)
|
|
182
|
+
options = { :old => old_name, :new => new_name }
|
|
183
|
+
doc = process_request(API_URL_RENAME_TAG + options.to_query)
|
|
184
|
+
doc.at('result')['code'] == 'done'
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Delete a tag from Delicious
|
|
188
|
+
# ==== Parameters
|
|
189
|
+
# * <tt>tag_to_delete</tt> - tag name to delete.
|
|
190
|
+
# ==== Result
|
|
191
|
+
# * <tt>true</tt> if the tag was successfully deleted
|
|
192
|
+
# * <tt>false</tt> if the deletion failed
|
|
193
|
+
def delete_tag(tag_to_delete)
|
|
194
|
+
options = { :tag => tag_to_delete }
|
|
195
|
+
doc = process_request(API_URL_DELETE_TAG + options.to_query)
|
|
196
|
+
doc.at('result')['code'] == 'done'
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
##
|
|
200
|
+
# Returns a list of popular tags, recommended tags and network tags for the given url.
|
|
201
|
+
# This method is intended to provide suggestions for tagging a particular url.
|
|
202
|
+
# ==== Parameters
|
|
203
|
+
# * <tt>url</tt> - URL for which you'd like suggestions.
|
|
204
|
+
# ==== Result
|
|
205
|
+
# A <tt>Hash</tt> containing three arrays of <tt>Tags</tt>: <tt>:popular</tt>, <tt>:recommended</tt> and <tt>:network</tt>
|
|
206
|
+
def get_suggested_tags_for_url(url)
|
|
207
|
+
options = { :url => url }
|
|
208
|
+
doc = process_request(API_URL_SUGGEST_TAG + options.to_query)
|
|
209
|
+
result = { }
|
|
210
|
+
result[:popular] = (doc/'suggest/popular').collect{ |tag| Tag.new(tag.inner_html) }
|
|
211
|
+
result[:recommended] = (doc/'suggest/recommended').collect{ |tag| Tag.new(tag.inner_html) }
|
|
212
|
+
result[:network] = (doc/'suggest/network').collect{ |tag| Tag.new(tag.inner_html) }
|
|
213
|
+
result
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
##
|
|
217
|
+
# Retrieve all of a user's bundles.
|
|
218
|
+
# ==== Parameters
|
|
219
|
+
# * <tt>options</tt> - A <tt>Hash</tt> containing any of the following:
|
|
220
|
+
# - <tt>bundle</tt> - Fetch just the named bundle.
|
|
221
|
+
# ==== Result
|
|
222
|
+
# An <tt>Array</tt> of <tt>Bundles</tt> matching the criteria
|
|
223
|
+
def get_all_bundles(options = {})
|
|
224
|
+
options.assert_valid_keys(:bundle)
|
|
225
|
+
doc = process_request(API_URL_ALL_BUNDLES + options.to_query)
|
|
226
|
+
(doc/'bundles/bundle').collect{ |bundle| Bundle.new(bundle['name'], bundle['tags'].split(' ')) }
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
##
|
|
230
|
+
# Returns the user <tt>Bundle</tt> with the given <tt>name</tt>
|
|
231
|
+
# ==== Parameters
|
|
232
|
+
# * <tt>name</tt> - User's bundle name.
|
|
233
|
+
# ==== Result
|
|
234
|
+
# A <tt>Bundle</tt> matching the criteria or nil
|
|
235
|
+
def get_bundle_by_name(name)
|
|
236
|
+
get_all_bundles(:bundle => name).first
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
##
|
|
240
|
+
# Assign a set of tags to a single bundle, wipes away previous settings for bundle.
|
|
241
|
+
# ==== Parameters
|
|
242
|
+
# * <tt>name</tt> - bundle's name.
|
|
243
|
+
# * <tt>tags</tt> - tags for the bundle (space delimited).
|
|
244
|
+
# ==== Result
|
|
245
|
+
# * <tt>true</tt> if the bundle was set
|
|
246
|
+
# * <tt>false</tt> if the bundle was not set
|
|
247
|
+
def set_bundle(name, tags)
|
|
248
|
+
options = { :bundle => name, :tags => tags }
|
|
249
|
+
doc = process_request(API_URL_SET_BUNDLE + options.to_query)
|
|
250
|
+
doc.at('result').inner_html == 'ok'
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
##
|
|
254
|
+
# Delete a bundle from Delicious
|
|
255
|
+
# ==== Parameters
|
|
256
|
+
# * <tt>name</tt> - name of the bundle
|
|
257
|
+
# ==== Result
|
|
258
|
+
# * <tt>true</tt> if the bundle was successfully deleted
|
|
259
|
+
# * <tt>false</tt> if the deletion failed
|
|
260
|
+
def delete_bundle(name)
|
|
261
|
+
options = { :bundle => name }
|
|
262
|
+
doc = process_request(API_URL_DELETE_BUNDLE + options.to_query)
|
|
263
|
+
doc.at('result')['code'] == 'done'
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
private
|
|
267
|
+
|
|
268
|
+
def process_request(url)
|
|
269
|
+
init_http_client if @http_client.nil?
|
|
270
|
+
response = make_web_request(url)
|
|
271
|
+
Hpricot.XML(response.body)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def init_http_client
|
|
275
|
+
@http_client = Net::HTTP.new('api.del.icio.us', 443)
|
|
276
|
+
@http_client.use_ssl = true
|
|
277
|
+
@http_client.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def make_web_request(url)
|
|
281
|
+
http_client.start do |http|
|
|
282
|
+
req = Net::HTTP::Get.new(url, {'User-Agent' => @user_agent} )
|
|
283
|
+
req.basic_auth(@user, @password)
|
|
284
|
+
current_time = Time.now
|
|
285
|
+
@@last_request ||= current_time - waiting_time_gap
|
|
286
|
+
current_window = [current_time - @@last_request, waiting_time_gap].max
|
|
287
|
+
sleep(current_window) if current_window <= waiting_time_gap
|
|
288
|
+
response = @http_client.request(req)
|
|
289
|
+
case response
|
|
290
|
+
when Net::HTTPSuccess
|
|
291
|
+
return response
|
|
292
|
+
when Net::HTTPUnauthorized # 401 - HTTPUnauthorized
|
|
293
|
+
raise HTTPError, 'Invalid username or password'
|
|
294
|
+
when Net::HTTPServiceUnavailable # 503 - HTTPServiceUnavailable
|
|
295
|
+
raise HTTPError, 'You have been throttled. Try increasing the time gap between requests.'
|
|
296
|
+
else
|
|
297
|
+
raise HTTPError, "HTTP #{response.code}: #{response.message}"
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def default_user_agent
|
|
303
|
+
return "#{NAME}/#{VERSION} (Ruby/#{RUBY_VERSION})"
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
end
|
|
307
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module CustomMacros
|
|
2
|
+
def self.included(base)
|
|
3
|
+
base.extend(ClassMethods)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
module ClassMethods
|
|
7
|
+
def configure_wrapper
|
|
8
|
+
before(:all) do
|
|
9
|
+
Tag.wrapper = mock("base.wrapper", :null_object => true)
|
|
10
|
+
end
|
|
11
|
+
after(:all) do
|
|
12
|
+
Tag.wrapper = nil
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def freeze_time
|
|
17
|
+
before(:each) do
|
|
18
|
+
time_now = Time.now.utc
|
|
19
|
+
Time.stub!(:now).and_return(time_now)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|