flickrie 1.5.0 → 1.5.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/README.md +1 -1
- data/lib/flickrie.rb +18 -92
- data/lib/flickrie/api_methods.rb +759 -11
- data/lib/flickrie/base58.rb +15 -0
- data/lib/flickrie/callable.rb +78 -0
- data/lib/flickrie/client.rb +25 -17
- data/lib/flickrie/instance.rb +10 -15
- data/lib/flickrie/middleware.rb +4 -21
- data/lib/flickrie/middleware/fix_flickr_data.rb +215 -0
- data/lib/flickrie/middleware/retry.rb +23 -0
- data/lib/flickrie/{license.rb → objects/license.rb} +0 -0
- data/lib/flickrie/{location.rb → objects/location.rb} +13 -13
- data/lib/flickrie/{media.rb → objects/media.rb} +30 -25
- data/lib/flickrie/{media → objects/media}/exif.rb +0 -0
- data/lib/flickrie/{media → objects/media}/note.rb +11 -12
- data/lib/flickrie/{media → objects/media}/tag.rb +10 -9
- data/lib/flickrie/objects/media/visibility.rb +28 -0
- data/lib/flickrie/objects/media_context.rb +17 -0
- data/lib/flickrie/objects/media_count.rb +46 -0
- data/lib/flickrie/{photo.rb → objects/photo.rb} +2 -3
- data/lib/flickrie/{set.rb → objects/set.rb} +9 -30
- data/lib/flickrie/{ticket.rb → objects/ticket.rb} +0 -0
- data/lib/flickrie/{user.rb → objects/user.rb} +10 -50
- data/lib/flickrie/{user → objects/user}/upload_status.rb +0 -0
- data/lib/flickrie/{video.rb → objects/video.rb} +3 -4
- data/lib/flickrie/version.rb +1 -1
- metadata +38 -37
- data/lib/flickrie/api_methods/media.rb +0 -698
- data/lib/flickrie/api_methods/set.rb +0 -23
- data/lib/flickrie/api_methods/user.rb +0 -45
- data/lib/flickrie/media/class_methods.rb +0 -217
- data/lib/flickrie/media/visibility.rb +0 -29
- data/lib/flickrie/media_count.rb +0 -54
@@ -0,0 +1,15 @@
|
|
1
|
+
module Flickrie
|
2
|
+
module Base58
|
3
|
+
ALPHABET = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'.chars.to_a.freeze
|
4
|
+
|
5
|
+
def to_base58(value)
|
6
|
+
value = Integer(value)
|
7
|
+
begin
|
8
|
+
value, remainder = value.divmod(58)
|
9
|
+
result = ALPHABET[remainder] + (result || '')
|
10
|
+
end while value > 0
|
11
|
+
|
12
|
+
result
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'flickrie/client'
|
2
|
+
require 'flickrie/upload_client'
|
3
|
+
require 'flickrie/middleware'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
|
6
|
+
module Flickrie
|
7
|
+
module Callable
|
8
|
+
# This is for manual use (for example, if I haven't covered something yet, and you really need it).
|
9
|
+
# Here's an example:
|
10
|
+
#
|
11
|
+
# response = Flickrie.client.get "flickr.photos.getInfo", :photo_id => 8423943
|
12
|
+
# response.body['photo']['id'] # => 8423943
|
13
|
+
# response.body['photo']['description'] # => "..."
|
14
|
+
#
|
15
|
+
# Flickrie.client.post "flickr.photos.licenses.setLicense", :photo_id => 1241497, :license_id => 2
|
16
|
+
#
|
17
|
+
# For the full list of available API methods, see [this page](http://www.flickr.com/services/api/).
|
18
|
+
#
|
19
|
+
# @return [HTTP response] A Faraday HTTP response
|
20
|
+
def client
|
21
|
+
params = {
|
22
|
+
:url => 'http://api.flickr.com/services/rest',
|
23
|
+
:params => {
|
24
|
+
:format => 'json',
|
25
|
+
:nojsoncallback => '1',
|
26
|
+
:api_key => api_key
|
27
|
+
},
|
28
|
+
:request => {
|
29
|
+
:open_timeout => open_timeout || DEFAULTS[:open_timeout],
|
30
|
+
:timeout => timeout || DEFAULTS[:timeout]
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
@client ||=
|
35
|
+
Client.new(params) do |b|
|
36
|
+
b.use Middleware::Retry
|
37
|
+
b.use FaradayMiddleware::OAuth,
|
38
|
+
:consumer_key => api_key,
|
39
|
+
:consumer_secret => shared_secret,
|
40
|
+
:token => access_token,
|
41
|
+
:token_secret => access_secret
|
42
|
+
|
43
|
+
b.use Middleware::FixFlickrData
|
44
|
+
b.use Middleware::StatusCheck
|
45
|
+
b.use FaradayMiddleware::ParseJson
|
46
|
+
b.use Middleware::OAuthCheck
|
47
|
+
|
48
|
+
b.adapter :net_http
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def upload_client
|
53
|
+
params = {
|
54
|
+
:url => 'http://api.flickr.com/services',
|
55
|
+
:request => {
|
56
|
+
:open_timeout => open_timeout || DEFAULTS[:open_timeout]
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
@upload_client ||=
|
61
|
+
UploadClient.new(params) do |b|
|
62
|
+
b.use Middleware::Retry
|
63
|
+
b.use FaradayMiddleware::OAuth,
|
64
|
+
:consumer_key => api_key,
|
65
|
+
:consumer_secret => shared_secret,
|
66
|
+
:token => access_token,
|
67
|
+
:token_secret => access_secret
|
68
|
+
b.request :multipart
|
69
|
+
|
70
|
+
b.use Middleware::UploadStatusCheck
|
71
|
+
b.use FaradayMiddleware::ParseXml
|
72
|
+
b.use Middleware::OAuthCheck
|
73
|
+
|
74
|
+
b.adapter :net_http
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/flickrie/client.rb
CHANGED
@@ -2,22 +2,20 @@ require 'faraday'
|
|
2
2
|
|
3
3
|
module Flickrie
|
4
4
|
class Client < Faraday::Connection
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
req.params[:method] = method
|
20
|
-
req.params.update(params)
|
5
|
+
# @!method get(method, params = {})
|
6
|
+
# @!method post(method, params = {})
|
7
|
+
[:get, :post].each do |http_method|
|
8
|
+
define_method(http_method) do |flickr_method, params = {}|
|
9
|
+
# (:include_sizes => true) --> (:extras => "url_sq,url_q,url_s,...")
|
10
|
+
if params.delete(:include_sizes)
|
11
|
+
urls = Photo::FLICKR_SIZES.values.map { |s| "url_#{s}" }.join(',')
|
12
|
+
params[:extras] = [params[:extras], urls].compact.join(',')
|
13
|
+
end
|
14
|
+
|
15
|
+
super() do |req|
|
16
|
+
req.params[:method] = flickr_method
|
17
|
+
req.params.update(params)
|
18
|
+
end
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
@@ -82,7 +80,7 @@ module Flickrie
|
|
82
80
|
end
|
83
81
|
|
84
82
|
def get_media_counts(params = {})
|
85
|
-
get 'flickr.photos.getCounts', params
|
83
|
+
get 'flickr.photos.getCounts', ensure_utc(params)
|
86
84
|
end
|
87
85
|
|
88
86
|
def get_media_exif(media_id, params = {})
|
@@ -223,5 +221,15 @@ module Flickrie
|
|
223
221
|
dup_params[:extras] = [dup_params[:extras], 'media'].compact.join(',')
|
224
222
|
end
|
225
223
|
end
|
224
|
+
|
225
|
+
def ensure_utc(params)
|
226
|
+
params.dup.tap do |hash|
|
227
|
+
if hash[:taken_dates].is_a?(String)
|
228
|
+
hash[:taken_dates] = hash[:taken_dates].split(',').
|
229
|
+
map { |date| DateTime.parse(date) }.
|
230
|
+
map(&:to_time).map(&:getutc).join(',')
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
226
234
|
end
|
227
235
|
end
|
data/lib/flickrie/instance.rb
CHANGED
@@ -2,6 +2,15 @@ module Flickrie
|
|
2
2
|
class Instance
|
3
3
|
attr_reader :access_token, :access_secret
|
4
4
|
|
5
|
+
def self.delegate(*attributes)
|
6
|
+
attributes.each do |attribute|
|
7
|
+
define_method(attribute) do
|
8
|
+
Flickrie.send(attribute)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
delegate :api_key, :shared_secret, :open_timeout, :timeout, :pagination
|
13
|
+
|
5
14
|
# Initializes a new authenticated instance. Example:
|
6
15
|
#
|
7
16
|
# flickrie = Flickrie::Instance.new("ACCESS_TOKEN", "ACCESS_SECRET")
|
@@ -10,21 +19,7 @@ module Flickrie
|
|
10
19
|
@access_token, @access_secret = access_token, access_secret
|
11
20
|
end
|
12
21
|
|
13
|
-
|
14
|
-
def client
|
15
|
-
@client ||= Flickrie.new_client(access_token_hash)
|
16
|
-
end
|
17
|
-
|
22
|
+
include Callable
|
18
23
|
include ApiMethods
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def upload_client
|
23
|
-
@upload_client ||= Flickrie.new_upload_client(access_token_hash)
|
24
|
-
end
|
25
|
-
|
26
|
-
def access_token_hash
|
27
|
-
{:token => access_token, :secret => access_secret}
|
28
|
-
end
|
29
24
|
end
|
30
25
|
end
|
data/lib/flickrie/middleware.rb
CHANGED
@@ -12,7 +12,7 @@ module Flickrie
|
|
12
12
|
end
|
13
13
|
|
14
14
|
# Internal
|
15
|
-
module Middleware
|
15
|
+
module Middleware
|
16
16
|
class StatusCheck < Faraday::Response::Middleware
|
17
17
|
def on_complete(env)
|
18
18
|
if env[:body]['stat'] != 'ok'
|
@@ -40,26 +40,6 @@ module Flickrie
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
class Retry < Faraday::Middleware
|
44
|
-
def initialize(app, retries = 2)
|
45
|
-
@retries = retries
|
46
|
-
super(app)
|
47
|
-
end
|
48
|
-
|
49
|
-
def call(env)
|
50
|
-
retries = @retries
|
51
|
-
begin
|
52
|
-
@app.call(env)
|
53
|
-
rescue Faraday::Error::TimeoutError
|
54
|
-
if retries > 0
|
55
|
-
retries -= 1
|
56
|
-
retry
|
57
|
-
end
|
58
|
-
raise
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
43
|
class ParseOAuthParams < FaradayMiddleware::ResponseMiddleware
|
64
44
|
define_parser do |body|
|
65
45
|
CGI.parse(body).inject({}) do |hash, (key, value)|
|
@@ -69,3 +49,6 @@ module Flickrie
|
|
69
49
|
end
|
70
50
|
end
|
71
51
|
end
|
52
|
+
|
53
|
+
require 'flickrie/middleware/retry'
|
54
|
+
require 'flickrie/middleware/fix_flickr_data'
|
@@ -0,0 +1,215 @@
|
|
1
|
+
module Flickrie
|
2
|
+
module Middleware
|
3
|
+
class FixFlickrData < Faraday::Response::Middleware
|
4
|
+
def call(env)
|
5
|
+
response = @app.call(env)
|
6
|
+
fix_flickr_data!(response)
|
7
|
+
response
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# Ugly, just normalizing the data
|
13
|
+
def fix_flickr_data!(response)
|
14
|
+
data = response.env[:body]
|
15
|
+
query = CGI.parse(response.env[:url].query)
|
16
|
+
flickr_method = query['method'].first
|
17
|
+
|
18
|
+
case flickr_method
|
19
|
+
# people
|
20
|
+
when 'flickr.people.findByUsername'
|
21
|
+
data['user']['username'] = data['user']['username']['_content']
|
22
|
+
when 'flickr.people.findByEmail'
|
23
|
+
data['user']['username'] = data['user']['username']['_content']
|
24
|
+
when 'flickr.people.getInfo'
|
25
|
+
%w[username realname location description profileurl mobileurl photosurl].each do |attribute|
|
26
|
+
data['person'][attribute] = data['person'][attribute]['_content']
|
27
|
+
end
|
28
|
+
%w[count firstdatetaken firstdate].each do |photo_attribute|
|
29
|
+
data['person']['photos'][photo_attribute] = data['person']['photos'][photo_attribute]['_content']
|
30
|
+
end
|
31
|
+
when 'flickr.test.login'
|
32
|
+
data['user']['username'] = data['user']['username']['_content']
|
33
|
+
when 'flickr.people.getUploadStatus'
|
34
|
+
data['user']['username'] = data['user']['username']['_content']
|
35
|
+
data['user']['upload_status'] = {
|
36
|
+
'bandwidth' => data['user'].delete('bandwidth'),
|
37
|
+
'filesize' => data['user'].delete('filesize'),
|
38
|
+
'sets' => data['user'].delete('sets'),
|
39
|
+
'videosize' => data['user'].delete('videosize'),
|
40
|
+
'videos' => data['user'].delete('videos')
|
41
|
+
}
|
42
|
+
|
43
|
+
# photos
|
44
|
+
when 'flickr.people.getPhotos'
|
45
|
+
fix_common!(data)
|
46
|
+
when 'flickr.people.getPublicPhotos'
|
47
|
+
fix_common!(data)
|
48
|
+
when 'flickr.photos.getInfo'
|
49
|
+
data['photo']['title'] = data['photo']['title']['_content']
|
50
|
+
data['photo']['description'] = data['photo']['description']['_content']
|
51
|
+
data['photo']['comments_count'] = data['photo'].delete('comments')['_content']
|
52
|
+
data['photo']['dates']['uploaded'] = data['photo'].delete('dateuploaded')
|
53
|
+
data['photo']['tags'] = data['photo']['tags']['tag']
|
54
|
+
when 'flickr.photosets.getPhotos'
|
55
|
+
data['photoset']['photo'].map! do |media_hash|
|
56
|
+
media_hash['owner'] = {
|
57
|
+
'id' => data['photoset']['owner'],
|
58
|
+
'nsid' => data['photoset']['owner'],
|
59
|
+
'username' => data['photoset']['ownername'],
|
60
|
+
}
|
61
|
+
fix_extras!(media_hash)
|
62
|
+
media_hash
|
63
|
+
end
|
64
|
+
when 'flickr.photos.getSizes'
|
65
|
+
data['sizes']['usage'] = {
|
66
|
+
'canblog' => data['sizes']['canblog'],
|
67
|
+
'canprint' => data['sizes']['canprint'],
|
68
|
+
'candownload' => data['sizes']['candownload']
|
69
|
+
}
|
70
|
+
data['sizes']['id'] = query['photo_id'].first
|
71
|
+
if data['sizes']['size'].find { |hash| hash['label'] == 'Video Player' }
|
72
|
+
# Video
|
73
|
+
data['sizes']['video'] ||= {}
|
74
|
+
data['sizes']['size'].each do |info|
|
75
|
+
case info['label']
|
76
|
+
when 'Video Player' then data['sizes']['video']['source_url'] = info['source']
|
77
|
+
when 'Site MP4' then data['sizes']['video']['download_url'] = info['source']
|
78
|
+
when 'Mobile MP4' then data['sizes']['video']['mobile_download_url'] = info['source']
|
79
|
+
end
|
80
|
+
end
|
81
|
+
else
|
82
|
+
flickr_sizes = {
|
83
|
+
'Square' => Photo::FLICKR_SIZES['Square 75'],
|
84
|
+
'Large Square' => Photo::FLICKR_SIZES['Square 150'],
|
85
|
+
'Thumbnail' => Photo::FLICKR_SIZES['Thumbnail'],
|
86
|
+
'Small' => Photo::FLICKR_SIZES['Small 240'],
|
87
|
+
'Small 320' => Photo::FLICKR_SIZES['Small 320'],
|
88
|
+
'Medium' => Photo::FLICKR_SIZES['Medium 500'],
|
89
|
+
'Medium 640' => Photo::FLICKR_SIZES['Medium 640'],
|
90
|
+
'Medium 800' => Photo::FLICKR_SIZES['Medium 800'],
|
91
|
+
'Large' => Photo::FLICKR_SIZES['Large 1024'],
|
92
|
+
'Large 1600' => Photo::FLICKR_SIZES['Large 1600'],
|
93
|
+
'Large 2048' => Photo::FLICKR_SIZES['Large 2048'],
|
94
|
+
'Original' => Photo::FLICKR_SIZES['Original']
|
95
|
+
}
|
96
|
+
data['sizes']['size'].each do |size_info|
|
97
|
+
size_abbr = flickr_sizes[size_info['label']]
|
98
|
+
data['sizes']["width_#{size_abbr}"] = size_info['width']
|
99
|
+
data['sizes']["height_#{size_abbr}"] = size_info['height']
|
100
|
+
data['sizes']["url_#{size_abbr}"] = size_info['source']
|
101
|
+
end
|
102
|
+
end
|
103
|
+
when 'flickr.photos.search'
|
104
|
+
fix_common!(data)
|
105
|
+
when 'flickr.photos.getContactsPhotos'
|
106
|
+
data['photos']['photo'].each do |media_hash|
|
107
|
+
media_hash['ownername'] = media_hash.delete('username')
|
108
|
+
end
|
109
|
+
fix_common!(data)
|
110
|
+
when 'flickr.photos.getContactsPublicPhotos'
|
111
|
+
data['photos']['photo'].each do |media_hash|
|
112
|
+
media_hash['ownername'] = media_hash.delete('username')
|
113
|
+
end
|
114
|
+
fix_common!(data)
|
115
|
+
when 'flickr.photos.getNotInSet'
|
116
|
+
fix_common!(data)
|
117
|
+
when 'flickr.people.getPhotosOf'
|
118
|
+
fix_common!(data)
|
119
|
+
when 'flickr.photos.getPerms'
|
120
|
+
fix_visibility!(data['perms'])
|
121
|
+
data['perms']['permissions'] = {
|
122
|
+
'permcomment' => data['perms'].delete('permcomment'),
|
123
|
+
'permaddmeta' => data['perms'].delete('permaddmeta')
|
124
|
+
}
|
125
|
+
when 'flickr.photos.getRecent'
|
126
|
+
fix_common!(data)
|
127
|
+
when 'flickr.photos.getUntagged'
|
128
|
+
fix_common!(data)
|
129
|
+
when 'flickr.photos.getWithGeoData'
|
130
|
+
fix_common!(data)
|
131
|
+
when 'flickr.photos.getWithoutGeoData'
|
132
|
+
fix_common!(data)
|
133
|
+
when 'flickr.photos.recentlyUpdated'
|
134
|
+
fix_common!(data)
|
135
|
+
|
136
|
+
# photosets
|
137
|
+
when 'flickr.photosets.getInfo'
|
138
|
+
data['photoset']['title'] = data['photoset']['title']['_content']
|
139
|
+
data['photoset']['description'] = data['photoset']['description']['_content']
|
140
|
+
when 'flickr.photosets.getList'
|
141
|
+
data['photosets']['photoset'].map! do |set_hash|
|
142
|
+
set_hash['count_photos'] = set_hash.delete('photos')
|
143
|
+
set_hash['count_videos'] = set_hash.delete('videos')
|
144
|
+
set_hash['title'] = set_hash['title']['_content']
|
145
|
+
set_hash['description'] = set_hash['description']['_content']
|
146
|
+
set_hash['owner'] = query['user_id'].first
|
147
|
+
set_hash
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def fix_extras!(hash)
|
153
|
+
if hash['iconserver'] or hash['iconfarm']
|
154
|
+
hash['owner'] ||= {}
|
155
|
+
hash['owner'].update \
|
156
|
+
'iconserver' => hash.delete('iconserver'),
|
157
|
+
'iconfarm' => hash.delete('iconfarm')
|
158
|
+
end
|
159
|
+
|
160
|
+
if hash['place_id']
|
161
|
+
geo_info = %w[latitude longitude accuracy context place_id woeid]
|
162
|
+
hash['location'] = geo_info.inject({}) do |location, geo|
|
163
|
+
location.update(geo => hash.delete(geo))
|
164
|
+
end
|
165
|
+
hash['geoperms'] = {
|
166
|
+
'isfamily' => hash['geo_is_family'],
|
167
|
+
'isfriend' => hash['geo_is_friend'],
|
168
|
+
'iscontact' => hash['geo_is_contact'],
|
169
|
+
'ispublic' => hash['geo_is_public']
|
170
|
+
}
|
171
|
+
end
|
172
|
+
|
173
|
+
if hash['tags']
|
174
|
+
hash['tags'] = hash['tags'].split(' ').map do |tag_content|
|
175
|
+
{'_content' => tag_content, 'machine_tag' => 0}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
if hash['machine_tags']
|
179
|
+
hash['tags'] ||= []
|
180
|
+
hash['tags'] += hash.delete('machine_tags').split(' ').map do |tag_content|
|
181
|
+
{'_content' => tag_content, 'machine_tag' => 1}
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
hash['dates'] = {
|
186
|
+
'uploaded' => hash.delete('dateupload'),
|
187
|
+
'lastupdate' => hash.delete('lastupdate'),
|
188
|
+
'taken' => hash.delete('datetaken'),
|
189
|
+
'takengranularity' => hash.delete('datetakengranularity'),
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
def fix_visibility!(hash)
|
194
|
+
hash['visibility'] = {
|
195
|
+
'ispublic' => hash.delete('ispublic'),
|
196
|
+
'isfriend' => hash.delete('isfriend'),
|
197
|
+
'isfamily' => hash.delete('isfamily')
|
198
|
+
}
|
199
|
+
end
|
200
|
+
|
201
|
+
def fix_common!(hash)
|
202
|
+
hash['photos']['photo'].map! do |media_hash|
|
203
|
+
media_hash['owner'] = {
|
204
|
+
'id' => media_hash['owner'],
|
205
|
+
'nsid' => media_hash.delete('owner'),
|
206
|
+
'username' => media_hash.delete('ownername')
|
207
|
+
}
|
208
|
+
fix_extras!(media_hash)
|
209
|
+
fix_visibility!(media_hash)
|
210
|
+
media_hash
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|