net-flickr 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/LICENSE +25 -0
- data/lib/net/flickr.rb +218 -0
- data/lib/net/flickr/auth.rb +139 -0
- data/lib/net/flickr/errors.rb +35 -0
- data/lib/net/flickr/list.rb +135 -0
- data/lib/net/flickr/people.rb +65 -0
- data/lib/net/flickr/person.rb +251 -0
- data/lib/net/flickr/photo.rb +335 -0
- data/lib/net/flickr/photolist.rb +53 -0
- data/lib/net/flickr/photos.rb +189 -0
- data/lib/net/flickr/tag.rb +55 -0
- metadata +77 -0
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2007-2008 Ryan Grove <ryan@wonko.com>
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice,
|
8
|
+
this list of conditions and the following disclaimer.
|
9
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
* Neither the name of this project nor the names of its contributors may be
|
13
|
+
used to endorse or promote products derived from this software without
|
14
|
+
specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
20
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
21
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
22
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
23
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/lib/net/flickr.rb
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2007-2008 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
# Append this file's directory to the include path if it's not there already.
|
30
|
+
$:.unshift(File.dirname(__FILE__))
|
31
|
+
$:.uniq!
|
32
|
+
|
33
|
+
# stdlib includes
|
34
|
+
require 'digest/md5'
|
35
|
+
require 'net/http'
|
36
|
+
require 'uri'
|
37
|
+
|
38
|
+
# RubyGems includes
|
39
|
+
require 'rubygems'
|
40
|
+
require 'hpricot'
|
41
|
+
|
42
|
+
# Net::Flickr includes
|
43
|
+
require 'flickr/auth'
|
44
|
+
require 'flickr/errors'
|
45
|
+
require 'flickr/list'
|
46
|
+
require 'flickr/people'
|
47
|
+
require 'flickr/person'
|
48
|
+
require 'flickr/photo'
|
49
|
+
require 'flickr/photolist'
|
50
|
+
require 'flickr/photos'
|
51
|
+
require 'flickr/tag'
|
52
|
+
|
53
|
+
module Net
|
54
|
+
|
55
|
+
# = Net::Flickr
|
56
|
+
#
|
57
|
+
# This library implements Flickr's REST API. Its usage should be pretty
|
58
|
+
# straightforward. See below for examples.
|
59
|
+
#
|
60
|
+
# Author:: Ryan Grove (mailto:ryan@wonko.com)
|
61
|
+
# Version:: 0.0.1
|
62
|
+
# Copyright:: Copyright (c) 2007-2008 Ryan Grove. All rights reserved.
|
63
|
+
# License:: New BSD License (http://opensource.org/licenses/bsd-license.php)
|
64
|
+
# Website:: http://code.google.com/p/net-flickr/
|
65
|
+
#
|
66
|
+
# == APIs not yet implemented
|
67
|
+
#
|
68
|
+
# * activity
|
69
|
+
# * blogs
|
70
|
+
# * contacts
|
71
|
+
# * favorites
|
72
|
+
# * groups
|
73
|
+
# * groups.pools
|
74
|
+
# * interestingness
|
75
|
+
# * photos.comments
|
76
|
+
# * photos.geo
|
77
|
+
# * photos.licenses
|
78
|
+
# * photos.notes
|
79
|
+
# * photos.transform
|
80
|
+
# * photos.upload
|
81
|
+
# * photosets
|
82
|
+
# * photosets.comments
|
83
|
+
# * reflection
|
84
|
+
# * tags
|
85
|
+
# * test
|
86
|
+
# * urls
|
87
|
+
#
|
88
|
+
class Flickr
|
89
|
+
AUTH_URL = 'http://flickr.com/services/auth/'.freeze
|
90
|
+
REST_ENDPOINT = 'http://api.flickr.com/services/rest/'.freeze
|
91
|
+
VERSION = '0.0.1'.freeze
|
92
|
+
|
93
|
+
attr_accessor :timeout
|
94
|
+
attr_reader :api_key, :api_secret
|
95
|
+
|
96
|
+
# Creates a new Net::Flickr object that will use the specified _api_key_ and
|
97
|
+
# _api_secret_ to connect to Flickr. If you don't already have a Flickr API
|
98
|
+
# key, you can get one at http://flickr.com/services/api/keys.
|
99
|
+
#
|
100
|
+
# If you don't provide an _api_secret_, you won't be able to make API calls
|
101
|
+
# requiring authentication.
|
102
|
+
def initialize(api_key, api_secret = nil)
|
103
|
+
@api_key = api_key
|
104
|
+
@api_secret = api_secret
|
105
|
+
|
106
|
+
# Initialize dependent classes.
|
107
|
+
@auth = Auth.new(self)
|
108
|
+
@people = People.new(self)
|
109
|
+
@photos = Photos.new(self)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns a Net::Flickr::Auth instance.
|
113
|
+
def auth
|
114
|
+
@auth
|
115
|
+
end
|
116
|
+
|
117
|
+
# Parses the specified Flickr REST response. If the response indicates a
|
118
|
+
# successful request, the response block will be returned as an Hpricot
|
119
|
+
# element. Otherwise, an error will be raised.
|
120
|
+
def parse_response(response_xml)
|
121
|
+
begin
|
122
|
+
xml = Hpricot::XML(response_xml)
|
123
|
+
rescue => e
|
124
|
+
raise InvalidResponse, 'Invalid Flickr API response'
|
125
|
+
end
|
126
|
+
|
127
|
+
unless rsp = xml.at('/rsp')
|
128
|
+
raise InvalidResponse, 'Invalid Flickr API response'
|
129
|
+
end
|
130
|
+
|
131
|
+
if rsp['stat'] == 'ok'
|
132
|
+
return rsp
|
133
|
+
elsif rsp['stat'] == 'fail'
|
134
|
+
raise APIError, rsp.at('/err')['msg']
|
135
|
+
else
|
136
|
+
raise InvalidResponse, 'Invalid Flickr API response'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns a Net::Flickr::People instance.
|
141
|
+
def people
|
142
|
+
@people
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns a Net::Flickr::Photos instance.
|
146
|
+
def photos
|
147
|
+
@photos
|
148
|
+
end
|
149
|
+
|
150
|
+
# Calls the specified Flickr REST API _method_ with the supplied arguments
|
151
|
+
# and returns a Flickr REST response in XML format. If an API secret is set,
|
152
|
+
# the request will be properly signed.
|
153
|
+
def request(method, args = {})
|
154
|
+
params = args.merge({'method' => method, 'api_key' => @api_key})
|
155
|
+
url = URI.parse(REST_ENDPOINT)
|
156
|
+
http = Net::HTTP.new(url.host, url.port)
|
157
|
+
request = sign_request(Net::HTTP::Post.new(url.path), params)
|
158
|
+
|
159
|
+
http.start do |http|
|
160
|
+
if block_given?
|
161
|
+
http.request(request) {|response| yield response }
|
162
|
+
else
|
163
|
+
response = http.request(request)
|
164
|
+
|
165
|
+
# Raise a Net::HTTP error if the HTTP request failed.
|
166
|
+
unless response.is_a?(Net::HTTPSuccess) ||
|
167
|
+
response.is_a?(Net::HTTPRedirection)
|
168
|
+
response.error!
|
169
|
+
end
|
170
|
+
|
171
|
+
# Return the parsed response.
|
172
|
+
return parse_response(response.body)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# Signs a Flickr API request with the API secret if set.
|
178
|
+
def sign_request(request, params)
|
179
|
+
# If the secret isn't set, we can't sign anything.
|
180
|
+
if @api_secret.nil?
|
181
|
+
request.set_form_data(params)
|
182
|
+
return request
|
183
|
+
end
|
184
|
+
|
185
|
+
# Add auth_token to the param list if we're already authenticated.
|
186
|
+
params['auth_token'] = @auth.token unless @auth.token.nil?
|
187
|
+
|
188
|
+
# Build a sorted, concatenated parameter list as described at
|
189
|
+
# http://flickr.com/services/api/auth.spec.html
|
190
|
+
paramlist = ''
|
191
|
+
params.keys.sort.each {|key| paramlist << key <<
|
192
|
+
URI.escape(params[key].to_s) }
|
193
|
+
|
194
|
+
# Sign the request with a hash of the secret key and the concatenated
|
195
|
+
# parameter list.
|
196
|
+
params['api_sig'] = Digest::MD5.hexdigest(@api_secret + paramlist)
|
197
|
+
request.set_form_data(params)
|
198
|
+
|
199
|
+
return request
|
200
|
+
end
|
201
|
+
|
202
|
+
# Signs a Flickr URL with the API secret if set.
|
203
|
+
def sign_url(url)
|
204
|
+
return url if @api_secret.nil?
|
205
|
+
|
206
|
+
uri = URI.parse(url)
|
207
|
+
|
208
|
+
params = uri.query.split('&')
|
209
|
+
params << 'api_sig=' + Digest::MD5.hexdigest(@api_secret +
|
210
|
+
params.sort.join('').gsub('=', ''))
|
211
|
+
|
212
|
+
uri.query = params.join('&')
|
213
|
+
|
214
|
+
return uri.to_s
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2007-2008 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Net; class Flickr
|
30
|
+
|
31
|
+
# Implements the Flickr authentication API. Please see
|
32
|
+
# http://flickr.com/services/api/auth.spec.html for details on how to use this
|
33
|
+
# API in your application.
|
34
|
+
#
|
35
|
+
# Don't instantiate this class yourself. Instead, create an instance of the
|
36
|
+
# +Flickr+ class and then user <tt>Flickr.auth</tt> to access this class,
|
37
|
+
# like so:
|
38
|
+
#
|
39
|
+
# require 'net/flickr'
|
40
|
+
#
|
41
|
+
# flickr = Net::Flickr.new('524266cbd9d3c2xa2679fee8b337fip2',
|
42
|
+
# '835hae5d6j0sd47a')
|
43
|
+
#
|
44
|
+
# puts flickr.auth.url_desktop
|
45
|
+
#
|
46
|
+
class Auth
|
47
|
+
PERM_NONE = :none
|
48
|
+
PERM_READ = :read
|
49
|
+
PERM_WRITE = :write
|
50
|
+
PERM_DELETE = :delete
|
51
|
+
|
52
|
+
attr_reader :frob, :perms, :token, :user_id, :user_name, :user_fullname
|
53
|
+
|
54
|
+
def initialize(flickr)
|
55
|
+
@flickr = flickr
|
56
|
+
|
57
|
+
@frob = nil
|
58
|
+
@perms = PERM_NONE
|
59
|
+
@token = nil
|
60
|
+
@user_id = nil
|
61
|
+
@user_name = nil
|
62
|
+
@user_fullname = nil
|
63
|
+
end
|
64
|
+
|
65
|
+
#--
|
66
|
+
# Public Instance Methods
|
67
|
+
#++
|
68
|
+
|
69
|
+
# Updates this Auth object with the credentials attached to the specified
|
70
|
+
# authentication _token_. If the _token_ is not valid, an APIError will be
|
71
|
+
# raised.
|
72
|
+
def check_token(token = @token)
|
73
|
+
update_auth(@flickr.request('flickr.auth.checkToken',
|
74
|
+
'auth_token' => token))
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
|
78
|
+
# Gets the full authentication token for the specified _mini_token_.
|
79
|
+
def full_token(mini_token)
|
80
|
+
update_auth(@flickr.request('flickr.auth.getFullToken',
|
81
|
+
'mini_token' => mini_token))
|
82
|
+
return @token
|
83
|
+
end
|
84
|
+
|
85
|
+
# Gets a frob to be used during authentication.
|
86
|
+
def get_frob
|
87
|
+
response = @flickr.request('flickr.auth.getFrob').at('frob')
|
88
|
+
return @frob = response.inner_text
|
89
|
+
end
|
90
|
+
|
91
|
+
# Updates this Auth object with the credentials for the specified _frob_ and
|
92
|
+
# returns an auth token. If the _frob_ is not valid, an APIError will be
|
93
|
+
# raised.
|
94
|
+
def get_token(frob = @frob)
|
95
|
+
update_auth(@flickr.request('flickr.auth.getToken', 'frob' => frob))
|
96
|
+
return @token
|
97
|
+
end
|
98
|
+
|
99
|
+
# Gets a signed URL that can by used by a desktop application to show the
|
100
|
+
# user a Flickr authentication screen. Once the user has visited this URL
|
101
|
+
# and authorized your application, you can call get_token to authenticate.
|
102
|
+
def url_desktop(perms)
|
103
|
+
get_frob if @frob.nil?
|
104
|
+
url = Flickr::AUTH_URL +
|
105
|
+
"?api_key=#{@flickr.api_key}&perms=#{perms}&frob=#{@frob}"
|
106
|
+
|
107
|
+
return @flickr.sign_url(url)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Gets a signed URL that can be used by a web application to show the user a
|
111
|
+
# Flickr authentication screen. Once the user has visited this URL and
|
112
|
+
# authorized your application, you can call get_token with the frob provided
|
113
|
+
# by Flickr to authenticate.
|
114
|
+
def url_webapp(perms)
|
115
|
+
return @flickr.sign_url(Flickr::AUTH_URL +
|
116
|
+
"?api_key=#{@flickr.api_key}&perms=#{perms}")
|
117
|
+
end
|
118
|
+
|
119
|
+
#--
|
120
|
+
# Private Instance Methods
|
121
|
+
#++
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# Updates this Auth object with the credentials in the specified XML
|
126
|
+
# _response_.
|
127
|
+
def update_auth(response)
|
128
|
+
auth = response.at('auth')
|
129
|
+
user = auth.at('user')
|
130
|
+
|
131
|
+
@perms = auth.at('perms').inner_text.to_sym
|
132
|
+
@token = auth.at('token').inner_text
|
133
|
+
@user_id = user['nsid']
|
134
|
+
@user_name = user['username']
|
135
|
+
@user_fullname = user['fullname']
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end; end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2007-2008 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Net; class Flickr
|
30
|
+
|
31
|
+
class APIError < StandardError; end
|
32
|
+
class InvalidResponse < StandardError; end
|
33
|
+
class ListError < StandardError; end
|
34
|
+
|
35
|
+
end; end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2007-2008 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Net; class Flickr
|
30
|
+
|
31
|
+
# Base class for paginated lists.
|
32
|
+
#
|
33
|
+
# Don't instantiate this class yourself. It's a base class extended by
|
34
|
+
# +PhotoList+ and others.
|
35
|
+
class List
|
36
|
+
include Enumerable
|
37
|
+
|
38
|
+
attr_reader :page, :pages, :per_page, :total
|
39
|
+
|
40
|
+
def initialize(flickr, load_method, load_args)
|
41
|
+
@flickr = flickr
|
42
|
+
@load_method = load_method
|
43
|
+
@load_args = load_args
|
44
|
+
|
45
|
+
update_list
|
46
|
+
end
|
47
|
+
|
48
|
+
#--
|
49
|
+
# Public Instance Methods
|
50
|
+
#++
|
51
|
+
|
52
|
+
def [](index)
|
53
|
+
return @items[index]
|
54
|
+
end
|
55
|
+
|
56
|
+
def each
|
57
|
+
@items.each {|item| yield item }
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns +true+ if the current page is the first page of the list, +false+
|
61
|
+
# otherwise.
|
62
|
+
def first_page?
|
63
|
+
return @page == 1
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns +true+ if the current page is the last page of the list, +false+
|
67
|
+
# otherwise.
|
68
|
+
def last_page?
|
69
|
+
return @page == @pages
|
70
|
+
end
|
71
|
+
|
72
|
+
# Loads the next page in the list.
|
73
|
+
def next
|
74
|
+
if last_page?
|
75
|
+
raise ListError, 'Already on the last page of the list'
|
76
|
+
end
|
77
|
+
|
78
|
+
@load_args['page'] = @page + 1
|
79
|
+
update_list
|
80
|
+
end
|
81
|
+
|
82
|
+
# Loads the specified page in the list.
|
83
|
+
def page=(page)
|
84
|
+
if page < 1 || page > @pages
|
85
|
+
raise ArgumentError, 'Page number out of bounds'
|
86
|
+
end
|
87
|
+
|
88
|
+
@load_args['page'] = page
|
89
|
+
update_list
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sets the number of items loaded per page. Must be between 1 and 500
|
93
|
+
# inclusive.
|
94
|
+
def per_page=(per_page)
|
95
|
+
if per_page < 1 || per_page > 500
|
96
|
+
raise ArgumentError, 'per_page must be between 1 and 500 inclusive'
|
97
|
+
end
|
98
|
+
|
99
|
+
@per_page = per_page
|
100
|
+
@load_args['per_page'] = @per_page
|
101
|
+
end
|
102
|
+
|
103
|
+
# Loads the previous page in the list.
|
104
|
+
def previous
|
105
|
+
if first_page?
|
106
|
+
raise ListError, 'Already on the first page of the list'
|
107
|
+
end
|
108
|
+
|
109
|
+
@load_args['page'] = @page - 1
|
110
|
+
update_list
|
111
|
+
end
|
112
|
+
|
113
|
+
alias prev previous
|
114
|
+
|
115
|
+
#--
|
116
|
+
# Private Instance Methods
|
117
|
+
#++
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def update_list
|
122
|
+
@items = []
|
123
|
+
|
124
|
+
@response = @flickr.request(@load_method, @load_args).
|
125
|
+
at('/*[@page]:first')
|
126
|
+
|
127
|
+
@per_page = @response['perpage'].to_i
|
128
|
+
@page = @response['page'].to_i
|
129
|
+
@pages = @response['pages'].to_i
|
130
|
+
@total = @response['total'].to_i
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end; end
|