hjw3001-flickrx 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +5 -0
- data/README.rdoc +38 -0
- data/Rakefile +14 -0
- data/flickrx.gemspec +29 -0
- data/init.rb +1 -0
- data/lib/flickrx.rb +878 -0
- metadata +64 -0
data/Manifest
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
= Uniquify
|
2
|
+
|
3
|
+
Ruby gem implementation of Flickr API.
|
4
|
+
|
5
|
+
http://www.flickr.com/services/api/.
|
6
|
+
|
7
|
+
|
8
|
+
== Install
|
9
|
+
|
10
|
+
gem install hjw3001-flickrx --source http://gems.github.com
|
11
|
+
|
12
|
+
|
13
|
+
== Usage
|
14
|
+
|
15
|
+
TBD
|
16
|
+
|
17
|
+
== License
|
18
|
+
|
19
|
+
Copyright (c) 2009 Henry Wagner
|
20
|
+
|
21
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
22
|
+
a copy of this software and associated documentation files (the
|
23
|
+
"Software"), to deal in the Software without restriction, including
|
24
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
25
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
26
|
+
permit persons to whom the Software is furnished to do so, subject to
|
27
|
+
the following conditions:
|
28
|
+
|
29
|
+
The above copyright notice and this permission notice shall be
|
30
|
+
included in all copies or substantial portions of the Software.
|
31
|
+
|
32
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
33
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
34
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
35
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
36
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
37
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
38
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('flickrx', '0.1.0') do |p|
|
6
|
+
p.description = "Ruby implementation of Flickr API."
|
7
|
+
p.url = "http://github.com/hjw3001/flickrx"
|
8
|
+
p.author = "Henry Wagner"
|
9
|
+
p.email = "hjw3001@gmail.com"
|
10
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
11
|
+
p.development_dependencies = []
|
12
|
+
end
|
13
|
+
|
14
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/flickrx.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{flickrx}
|
3
|
+
s.version = "0.1.0"
|
4
|
+
|
5
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
6
|
+
s.authors = ["Henry Wagner"]
|
7
|
+
s.date = %q{2009-02-12}
|
8
|
+
s.description = %q{Ruby implementation of Flickr API.}
|
9
|
+
s.email = %q{hjw3001@gmail.com}
|
10
|
+
s.extra_rdoc_files = ["lib/flickrx.rb", "README.rdoc"]
|
11
|
+
s.files = ["init.rb", "lib/flickrx.rb", "Rakefile", "README.rdoc", "Manifest", "flickrx.gemspec"]
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.homepage = %q{http://github.com/hjw3001/flickrx}
|
14
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Flickrx", "--main", "README.rdoc"]
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.rubyforge_project = %q{flickrx}
|
17
|
+
s.rubygems_version = %q{1.2.0}
|
18
|
+
s.summary = %q{Ruby implementation of Flickr API.}
|
19
|
+
|
20
|
+
if s.respond_to? :specification_version then
|
21
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
22
|
+
s.specification_version = 2
|
23
|
+
|
24
|
+
if current_version >= 3 then
|
25
|
+
else
|
26
|
+
end
|
27
|
+
else
|
28
|
+
end
|
29
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'flickrx'
|
data/lib/flickrx.rb
ADDED
@@ -0,0 +1,878 @@
|
|
1
|
+
##
|
2
|
+
# Ruby API for Flickr (See http://www.flickr.com/services/api/)
|
3
|
+
# (C) 2008 Henry Wagner
|
4
|
+
# http://www.henrywagner.org/
|
5
|
+
|
6
|
+
__AUTHOR__ = "Henry Wagner"
|
7
|
+
__VERSION__ = "0.1"
|
8
|
+
__DATE__ = "2008-05-02 21:55"
|
9
|
+
|
10
|
+
require 'cgi'
|
11
|
+
require 'md5'
|
12
|
+
require 'optparse'
|
13
|
+
require 'net/http'
|
14
|
+
require 'rexml/document'
|
15
|
+
require 'yaml'
|
16
|
+
include REXML
|
17
|
+
|
18
|
+
module Flickrx
|
19
|
+
|
20
|
+
class Utils
|
21
|
+
def cleanString(source)
|
22
|
+
if source == nil
|
23
|
+
return
|
24
|
+
elsif source == "N/A" then
|
25
|
+
source = nil
|
26
|
+
elsif source.count("\"") > 0 then
|
27
|
+
list = source.split(/\"/)
|
28
|
+
source = list[1]
|
29
|
+
elsif source.count("/thumb") > 0 then
|
30
|
+
list = source.split(/thumb/)
|
31
|
+
source = list[0]
|
32
|
+
end
|
33
|
+
if (source != nil)
|
34
|
+
source = CGI::unescapeHTML(source)
|
35
|
+
end
|
36
|
+
source
|
37
|
+
end
|
38
|
+
|
39
|
+
def fixFilename(source)
|
40
|
+
if source.index('jpg') == nil then
|
41
|
+
source = source + '.jpg'
|
42
|
+
end
|
43
|
+
source
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Flickr
|
48
|
+
|
49
|
+
@@template = <<EOF
|
50
|
+
# .flickrx
|
51
|
+
#
|
52
|
+
# Please fill in fields like this:
|
53
|
+
#
|
54
|
+
# email: bla@bla.com
|
55
|
+
# password: secret
|
56
|
+
#
|
57
|
+
api_key:
|
58
|
+
secret:
|
59
|
+
EOF
|
60
|
+
|
61
|
+
attr_reader :config, :nsid, :username, :fullname
|
62
|
+
|
63
|
+
def initialize
|
64
|
+
@config = create_or_find_config
|
65
|
+
@interface = 'http://www.flickr.com/services/rest/'
|
66
|
+
@auth_url = 'http://flickr.com/services/auth/'
|
67
|
+
@nsid = ''
|
68
|
+
@username = ''
|
69
|
+
@fullname = ''
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_frob
|
73
|
+
method = 'flickr.auth.getFrob'
|
74
|
+
api_sig = _get_api_sig({'method' => method})
|
75
|
+
data = _do_get(method, {
|
76
|
+
'api_sig' => api_sig
|
77
|
+
}
|
78
|
+
)
|
79
|
+
doc = Document.new(data)
|
80
|
+
doc.elements.each('rsp/frob') { |frob|
|
81
|
+
return frob.text
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# perms:
|
87
|
+
# 'read', 'write', 'delete'
|
88
|
+
##
|
89
|
+
def get_login_url(frob, perms='read')
|
90
|
+
api_sig = _get_api_sig({'frob' => frob, 'perms' => perms});
|
91
|
+
return "#{@auth_url}?api_key=#{@config['api_key']}&perms=#{perms}&frob=#{frob}&api_sig=#{api_sig}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_token(frob)
|
95
|
+
method = 'flickr.auth.getToken'
|
96
|
+
api_sig = _get_api_sig({'frob' => frob, 'method' => method})
|
97
|
+
data = _do_get(method, {
|
98
|
+
'api_sig' => api_sig,
|
99
|
+
'frob' => frob
|
100
|
+
}
|
101
|
+
)
|
102
|
+
doc = Document.new(data)
|
103
|
+
doc.elements.each('rsp/auth') { |auth|
|
104
|
+
token = auth.elements['token'].text
|
105
|
+
user = auth.elements['user']
|
106
|
+
@nsid = user.attributes['nsid']
|
107
|
+
@username = user.attributes['username']
|
108
|
+
@fullname = user.attributes['fullname']
|
109
|
+
return token
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def _do_get(method, *params)
|
114
|
+
params.each { |x, y|
|
115
|
+
if y.class == Array then params[x] = y.join(y) end
|
116
|
+
}
|
117
|
+
url = "#{@interface}?api_key=#{@config['api_key']}&method=#{method}#{_urlencode(params)}"
|
118
|
+
resp = Net::HTTP.get_response(URI.parse(url))
|
119
|
+
doc = Document.new(resp.body.to_s)
|
120
|
+
if doc.elements['rsp'].attributes['stat'] != 'ok'
|
121
|
+
error_code = doc.elements['rsp'].elements['err'].attributes['code']
|
122
|
+
error_msg = doc.elements['rsp'].elements['err'].attributes['msg']
|
123
|
+
msg = "ERROR[#{error_code}]: #{error_msg}"
|
124
|
+
p msg
|
125
|
+
exit
|
126
|
+
end
|
127
|
+
resp.body.to_s
|
128
|
+
end
|
129
|
+
|
130
|
+
def _urlencode(params)
|
131
|
+
ret = ''
|
132
|
+
params.each { |param|
|
133
|
+
param.each { |x, y|
|
134
|
+
ret += "&#{x}=#{y}" unless "#{y}" == nil
|
135
|
+
}
|
136
|
+
}
|
137
|
+
ret
|
138
|
+
end
|
139
|
+
|
140
|
+
def _get_api_sig(params)
|
141
|
+
ret = ''
|
142
|
+
params.sort.each { |x, y|
|
143
|
+
ret += "#{x}#{y}" unless "#{y}" == nil
|
144
|
+
}
|
145
|
+
MD5.md5("#{@config['secret']}api_key#{@config['api_key']}#{ret}")
|
146
|
+
end
|
147
|
+
|
148
|
+
protected
|
149
|
+
|
150
|
+
# Checks for the config, creates it if not found
|
151
|
+
def create_or_find_config
|
152
|
+
home = ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']
|
153
|
+
begin
|
154
|
+
config = YAML::load open(home + "/.flickrx")
|
155
|
+
rescue
|
156
|
+
open(home + '/.flickrx','w').write(@@template)
|
157
|
+
config = YAML::load open(home + "/.flickrx")
|
158
|
+
end
|
159
|
+
|
160
|
+
if config['api_key'] == nil or config['secret'] == nil
|
161
|
+
puts "Please edit ~/.flickrx to include your flickr api_key and secret\nTextmate users: mate ~/.flickrx"
|
162
|
+
exit(0)
|
163
|
+
end
|
164
|
+
|
165
|
+
config
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
class Contacts < Flickr
|
171
|
+
|
172
|
+
##
|
173
|
+
# filter:
|
174
|
+
# 'friends', 'family', 'both', 'neither'
|
175
|
+
##
|
176
|
+
def get_list(auth_token, filter='')
|
177
|
+
method = 'flickr.contacts.getList'
|
178
|
+
api_sig = _get_api_sig(
|
179
|
+
{
|
180
|
+
'method' => method,
|
181
|
+
'auth_token' => config['token'],
|
182
|
+
'filter' => filter
|
183
|
+
}
|
184
|
+
)
|
185
|
+
data = _do_get(method,
|
186
|
+
{
|
187
|
+
'api_sig' => api_sig,
|
188
|
+
'auth_token' => config['token'],
|
189
|
+
'filter' => filter
|
190
|
+
}
|
191
|
+
)
|
192
|
+
doc = Document.new(data)
|
193
|
+
contacts = []
|
194
|
+
doc.elements.each('rsp/contacts/contact') { |contact|
|
195
|
+
contacts << {
|
196
|
+
'nsid' => contact.attributes['nsid'],
|
197
|
+
'username' => contact.attributes['username'],
|
198
|
+
'realname' => contact.attributes['realname'],
|
199
|
+
'friend' => contact.attributes['friend'],
|
200
|
+
'family' => contact.attributes['family'],
|
201
|
+
'ignored' => contact.attributes['ignored']
|
202
|
+
}
|
203
|
+
}
|
204
|
+
return contacts
|
205
|
+
end
|
206
|
+
|
207
|
+
def get_public_list(nsid)
|
208
|
+
method = 'flickr.contacts.getPublicList'
|
209
|
+
data = _do_get(method,
|
210
|
+
{
|
211
|
+
'api_key' => config['api_key'],
|
212
|
+
'user_id' => nsid
|
213
|
+
}
|
214
|
+
)
|
215
|
+
doc = Document.new(data)
|
216
|
+
contacts = []
|
217
|
+
doc.elements.each('rsp/contacts/contact') { |contact|
|
218
|
+
contacts << {
|
219
|
+
'nsid' => contact.attributes['nsid'],
|
220
|
+
'username' => contact.attributes['username'],
|
221
|
+
'ignored' => contact.attributes['ignored']
|
222
|
+
}
|
223
|
+
}
|
224
|
+
return contacts
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
class Favorites < Flickr
|
229
|
+
|
230
|
+
def add(auth_token, photo_id)
|
231
|
+
method = 'flickr.favorites.add'
|
232
|
+
api_sig = _get_api_sig(
|
233
|
+
{
|
234
|
+
'method' => method,
|
235
|
+
'auth_token' => config['token'],
|
236
|
+
'photo_id' => photo_id
|
237
|
+
}
|
238
|
+
)
|
239
|
+
data = _do_get(method, {
|
240
|
+
'api_sig' => api_sig,
|
241
|
+
'auth_token' => config['token'],
|
242
|
+
'photo_id' => photo_id
|
243
|
+
}
|
244
|
+
)
|
245
|
+
if data
|
246
|
+
return true
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
##
|
251
|
+
# extras: array that consists one or more of
|
252
|
+
# license, date_upload, date_taken, owner_name, icon_server
|
253
|
+
##
|
254
|
+
def get_list(auth_token, nsid='', extras=[], per_page=100, page=1)
|
255
|
+
method = 'flickr.favorites.getList'
|
256
|
+
api_sig = _get_api_sig(
|
257
|
+
{
|
258
|
+
'method' => method,
|
259
|
+
'auth_token' => config['token'],
|
260
|
+
'user_id' => nsid,
|
261
|
+
'extras' => extras.join(','),
|
262
|
+
'per_page' => per_page,
|
263
|
+
'page' => page
|
264
|
+
}
|
265
|
+
)
|
266
|
+
data = _do_get(method,
|
267
|
+
{
|
268
|
+
'api_sig' => api_sig,
|
269
|
+
'auth_token' => config['token'],
|
270
|
+
'user_id' => nsid,
|
271
|
+
'extras' => extras.join(','),
|
272
|
+
'per_page' => per_page,
|
273
|
+
'page' => page
|
274
|
+
}
|
275
|
+
)
|
276
|
+
doc = Document.new(data)
|
277
|
+
photos = []
|
278
|
+
doc.elements.each('rsp/photos/photo') { |photo|
|
279
|
+
photos << {
|
280
|
+
'id' => photo.attributes['id'],
|
281
|
+
'owner' => photo.attributes['owner'],
|
282
|
+
'ispublic' => photo.attributes['ispublic'],
|
283
|
+
'isfamily' => photo.attributes['isfamily'],
|
284
|
+
'isfriend' => photo.attributes['isfriend'],
|
285
|
+
'title' => photo.attributes['title'],
|
286
|
+
'license' => photo.attributes['license'],
|
287
|
+
'owner_name' => photo.attributes['ownername'],
|
288
|
+
'date_taken' => photo.attributes['datetaken'],
|
289
|
+
'date_upload' => photo.attributes['dateupload']
|
290
|
+
}
|
291
|
+
}
|
292
|
+
return photos
|
293
|
+
end
|
294
|
+
|
295
|
+
##
|
296
|
+
# extras: array that consists one or more of
|
297
|
+
# license, date_upload, date_taken, owner_name, icon_server
|
298
|
+
##
|
299
|
+
def get_public_list(nsid, extras=[], per_page=100, page=1)
|
300
|
+
method = 'flickr.favorites.getPublicList'
|
301
|
+
data = _do_get(method,
|
302
|
+
{
|
303
|
+
'api_key' => @config['api_key'],
|
304
|
+
'user_id' => nsid,
|
305
|
+
'extras' => extras.join(','),
|
306
|
+
'per_page' => per_page,
|
307
|
+
'page' => page
|
308
|
+
}
|
309
|
+
)
|
310
|
+
doc = Document.new(data)
|
311
|
+
photos = []
|
312
|
+
doc.elements.each('rsp/photos/photo') { |photo|
|
313
|
+
photos << {
|
314
|
+
'id' => photo.attributes['id'],
|
315
|
+
'owner' => photo.attributes['owner'],
|
316
|
+
'ispublic' => photo.attributes['ispublic'],
|
317
|
+
'isfamily' => photo.attributes['isfamily'],
|
318
|
+
'isfriend' => photo.attributes['isfriend'],
|
319
|
+
'title' => photo.attributes['title'],
|
320
|
+
'license' => photo.attributes['license'],
|
321
|
+
'owner_name' => photo.attributes['ownername'],
|
322
|
+
'date_taken' => photo.attributes['datetaken'],
|
323
|
+
'date_upload' => photo.attributes['dateupload']
|
324
|
+
}
|
325
|
+
}
|
326
|
+
return photos
|
327
|
+
end
|
328
|
+
|
329
|
+
def remove(auth_token, photo_id)
|
330
|
+
method = 'flickr.favorites.remove'
|
331
|
+
api_sig = _get_api_sig(
|
332
|
+
{
|
333
|
+
'method' => method,
|
334
|
+
'auth_token' => config['token'],
|
335
|
+
'photo_id' => photo_id
|
336
|
+
}
|
337
|
+
)
|
338
|
+
data = _do_get(method, {
|
339
|
+
'api_sig' => api_sig,
|
340
|
+
'auth_token' => config['token'],
|
341
|
+
'photo_id' => photo_id
|
342
|
+
}
|
343
|
+
)
|
344
|
+
if data
|
345
|
+
return true
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
class Group < Flickr
|
351
|
+
def poolAdd(photo_id, group_id)
|
352
|
+
puts "Adding #{photo_id} to #{group_id}"
|
353
|
+
method = 'flickr.groups.pools.add'
|
354
|
+
api_sig = _get_api_sig(
|
355
|
+
{
|
356
|
+
'method' => method,
|
357
|
+
'auth_token' => config['token'],
|
358
|
+
'photo_id' => photo_id,
|
359
|
+
'group_id' => group_id
|
360
|
+
}
|
361
|
+
)
|
362
|
+
data = _do_get(method, {
|
363
|
+
'api_sig' => api_sig,
|
364
|
+
'auth_token' => config['token'],
|
365
|
+
'photo_id' => photo_id,
|
366
|
+
'group_id' => group_id
|
367
|
+
}
|
368
|
+
)
|
369
|
+
if data
|
370
|
+
return true
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
class PhotoSets < Flickr
|
376
|
+
|
377
|
+
def addPhoto(photoset_id, photo_id)
|
378
|
+
method = 'flickr.photosets.addPhoto'
|
379
|
+
api_sig = _get_api_sig(
|
380
|
+
{
|
381
|
+
'method' => method,
|
382
|
+
'auth_token' => config['token'],
|
383
|
+
'photo_id' => photo_id,
|
384
|
+
'photoset_id' => photoset_id
|
385
|
+
}
|
386
|
+
)
|
387
|
+
data = _do_get(method, {
|
388
|
+
'api_sig' => api_sig,
|
389
|
+
'auth_token' => config['token'],
|
390
|
+
'photo_id' => photo_id,
|
391
|
+
'photoset_id' => photoset_id
|
392
|
+
}
|
393
|
+
)
|
394
|
+
if data
|
395
|
+
return true
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def create(title, description, primary_photo_id)
|
400
|
+
method = 'flickr.photosets.create'
|
401
|
+
if (description != nil)
|
402
|
+
api_sig = _get_api_sig(
|
403
|
+
{
|
404
|
+
'method' => method,
|
405
|
+
'auth_token' => config['token'],
|
406
|
+
'primary_photo_id' => primary_photo_id,
|
407
|
+
'title' => title,
|
408
|
+
'description' => description
|
409
|
+
}
|
410
|
+
)
|
411
|
+
data = _do_get(method, {
|
412
|
+
'api_sig' => api_sig,
|
413
|
+
'auth_token' => config['token'],
|
414
|
+
'primary_photo_id' => primary_photo_id,
|
415
|
+
'title' => CGI::escape(title),
|
416
|
+
'description' => CGI::escape(description)
|
417
|
+
}
|
418
|
+
)
|
419
|
+
else
|
420
|
+
api_sig = _get_api_sig(
|
421
|
+
{
|
422
|
+
'method' => method,
|
423
|
+
'auth_token' => config['token'],
|
424
|
+
'primary_photo_id' => primary_photo_id,
|
425
|
+
'title' => title
|
426
|
+
}
|
427
|
+
)
|
428
|
+
data = _do_get(method, {
|
429
|
+
'api_sig' => api_sig,
|
430
|
+
'auth_token' => config['token'],
|
431
|
+
'primary_photo_id' => primary_photo_id,
|
432
|
+
'title' => CGI::escape(title)
|
433
|
+
}
|
434
|
+
)
|
435
|
+
end
|
436
|
+
doc = Document.new(data)
|
437
|
+
photosets = []
|
438
|
+
doc.elements.each('rsp/photoset') { |photoset|
|
439
|
+
photosets << {
|
440
|
+
'id' => photoset.attributes['id']
|
441
|
+
}
|
442
|
+
}
|
443
|
+
return photosets
|
444
|
+
end
|
445
|
+
|
446
|
+
def delete(auth_token, photoset_id)
|
447
|
+
method = 'flickr.photosets.delete'
|
448
|
+
api_sig = _get_api_sig(
|
449
|
+
{
|
450
|
+
'method' => method,
|
451
|
+
'auth_token' => auth_token,
|
452
|
+
'photoset_id' => photoset_id
|
453
|
+
}
|
454
|
+
)
|
455
|
+
data = _do_get(method, {
|
456
|
+
'api_sig' => api_sig,
|
457
|
+
'auth_token' => auth_token,
|
458
|
+
'photoset_id' => photoset_id
|
459
|
+
}
|
460
|
+
)
|
461
|
+
if data
|
462
|
+
return true
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
def getList(user_id = nil)
|
467
|
+
method = 'flickr.photosets.getList'
|
468
|
+
api_sig = _get_api_sig(
|
469
|
+
{
|
470
|
+
'method' => method,
|
471
|
+
'auth_token' => config['token'],
|
472
|
+
'user_id' => user_id
|
473
|
+
}
|
474
|
+
)
|
475
|
+
data = _do_get(method, {
|
476
|
+
'api_sig' => api_sig,
|
477
|
+
'auth_token' => config['token'],
|
478
|
+
'user_id' => user_id
|
479
|
+
}
|
480
|
+
)
|
481
|
+
|
482
|
+
doc = Document.new(data)
|
483
|
+
photosets = Hash.new
|
484
|
+
doc.elements.each('rsp/photosets/photoset') { |photoset|
|
485
|
+
photosets[photoset.elements['title'].text] = {
|
486
|
+
'id' => photoset.attributes['id']
|
487
|
+
}
|
488
|
+
# photoset.attributes['id'] => photoset.elements['title'].text
|
489
|
+
}
|
490
|
+
return photosets
|
491
|
+
end
|
492
|
+
|
493
|
+
def orderSets(photosets)
|
494
|
+
method = 'flickr.photosets.orderSets'
|
495
|
+
api_sig = _get_api_sig(
|
496
|
+
{
|
497
|
+
'method' => method,
|
498
|
+
'auth_token' => config['token'],
|
499
|
+
'photoset_ids' => photosets
|
500
|
+
}
|
501
|
+
)
|
502
|
+
data = _do_get(method, {
|
503
|
+
'api_sig' => api_sig,
|
504
|
+
'auth_token' => config['token'],
|
505
|
+
'photoset_ids' => photosets
|
506
|
+
}
|
507
|
+
)
|
508
|
+
if data
|
509
|
+
return true
|
510
|
+
end
|
511
|
+
end
|
512
|
+
|
513
|
+
end
|
514
|
+
|
515
|
+
class Photos < Flickr
|
516
|
+
|
517
|
+
def add_tags(auth_token, photo_id, tags)
|
518
|
+
method = 'flickr.photos.addTags'
|
519
|
+
api_sig = _get_api_sig(
|
520
|
+
{
|
521
|
+
'method' => method,
|
522
|
+
'auth_token' => auth_token,
|
523
|
+
'photo_id' => photo_id,
|
524
|
+
'tags' => tags.join(' ')
|
525
|
+
}
|
526
|
+
)
|
527
|
+
data = _do_get(method, {
|
528
|
+
'api_sig' => api_sig,
|
529
|
+
'auth_token' => auth_token,
|
530
|
+
'photo_id' => photo_id,
|
531
|
+
'tags' => tags.join(' ')
|
532
|
+
}
|
533
|
+
)
|
534
|
+
doc = Document.new(data)
|
535
|
+
photos = []
|
536
|
+
doc.elements.each('rsp/photos/photo') { |photo|
|
537
|
+
photos << {
|
538
|
+
'id' => photo.attributes['id'],
|
539
|
+
'owner' => photo.attributes['owner'],
|
540
|
+
'username' => photo.attributes['username'],
|
541
|
+
'title' => photo.attributes['title']
|
542
|
+
}
|
543
|
+
}
|
544
|
+
return photos
|
545
|
+
end
|
546
|
+
|
547
|
+
##
|
548
|
+
# max(count) = 50
|
549
|
+
##
|
550
|
+
def get_contacts_photos(auth_token, count=10, just_friends=0, single_photo=0, include_self=0)
|
551
|
+
method = 'flickr.photos.getContactsPhotos'
|
552
|
+
api_sig = _get_api_sig(
|
553
|
+
{
|
554
|
+
'method' => method,
|
555
|
+
'auth_token' => auth_token,
|
556
|
+
'count' => count,
|
557
|
+
'just_friends' => just_friends,
|
558
|
+
'single_photo' => single_photo,
|
559
|
+
'include_self' => include_self
|
560
|
+
}
|
561
|
+
)
|
562
|
+
data = _do_get(method, {
|
563
|
+
'api_sig' => api_sig,
|
564
|
+
'auth_token' => auth_token,
|
565
|
+
'count' => count,
|
566
|
+
'just_friends' => just_friends,
|
567
|
+
'single_photo' => single_photo,
|
568
|
+
'include_self' => include_self
|
569
|
+
}
|
570
|
+
)
|
571
|
+
doc = Document.new(data)
|
572
|
+
photos = []
|
573
|
+
doc.elements.each('rsp/photos/photo') { |photo|
|
574
|
+
photos << {
|
575
|
+
'id' => photo.attributes['id'],
|
576
|
+
'owner' => photo.attributes['owner'],
|
577
|
+
'username' => photo.attributes['username'],
|
578
|
+
'title' => photo.attributes['title']
|
579
|
+
}
|
580
|
+
}
|
581
|
+
return photos
|
582
|
+
end
|
583
|
+
|
584
|
+
##
|
585
|
+
# max(count) = 50
|
586
|
+
##
|
587
|
+
def get_contacts_public_photos(nsid, count=10, just_friends=0, single_photo=0, include_self=0)
|
588
|
+
method = 'flickr.photos.getContactsPublicPhotos'
|
589
|
+
data = _do_get(method, {
|
590
|
+
'api_key' => @config['api_key'],
|
591
|
+
'user_id' => nsid,
|
592
|
+
'count' => count,
|
593
|
+
'just_friends' => just_friends,
|
594
|
+
'single_photo' => single_photo,
|
595
|
+
'include_self' => include_self
|
596
|
+
}
|
597
|
+
)
|
598
|
+
doc = Document.new(data)
|
599
|
+
photos = []
|
600
|
+
doc.elements.each('rsp/photos/photo') { |photo|
|
601
|
+
photos << {
|
602
|
+
'id' => photo.attributes['id'],
|
603
|
+
'owner' => photo.attributes['owner'],
|
604
|
+
'username' => photo.attributes['username'],
|
605
|
+
'title' => photo.attributes['title']
|
606
|
+
}
|
607
|
+
}
|
608
|
+
return photos
|
609
|
+
end
|
610
|
+
|
611
|
+
def get_favorites(photo_id)
|
612
|
+
method = 'flickr.photos.getFavorites'
|
613
|
+
data = _do_get(method, {
|
614
|
+
'api_key' => @config['api_key'],
|
615
|
+
'photo_id' => photo_id
|
616
|
+
}
|
617
|
+
)
|
618
|
+
doc = Document.new(data)
|
619
|
+
doc.elements.each('rsp/photo') { |photo|
|
620
|
+
return {
|
621
|
+
'id' => photo.attributes['id'],
|
622
|
+
'secret' => photo.attributes['secret'],
|
623
|
+
'server' => photo.attributes['server'],
|
624
|
+
'farm' => photo.attributes['farm'],
|
625
|
+
'page' => photo.attributes['page'],
|
626
|
+
'pages' => photo.attributes['pages'],
|
627
|
+
'perpage' => photo.attributes['perpage'],
|
628
|
+
'total' => photo.attributes['total']
|
629
|
+
}
|
630
|
+
}
|
631
|
+
end
|
632
|
+
|
633
|
+
def get_info(photo_id)
|
634
|
+
method = 'flickr.photos.getInfo'
|
635
|
+
api_sig = _get_api_sig(
|
636
|
+
{
|
637
|
+
'method' => method,
|
638
|
+
'auth_token' => config['token'],
|
639
|
+
'photo_id' => photo_id
|
640
|
+
}
|
641
|
+
)
|
642
|
+
data = _do_get(method, {
|
643
|
+
'api_sig' => api_sig,
|
644
|
+
'auth_token' => config['token'],
|
645
|
+
'photo_id' => photo_id
|
646
|
+
}
|
647
|
+
)
|
648
|
+
doc = Document.new(data)
|
649
|
+
doc.elements.each('rsp/photo') { |photo|
|
650
|
+
owner = photo.elements['owner']
|
651
|
+
date = photo.elements['dates']
|
652
|
+
tags = photo.elements['tags']
|
653
|
+
tags_arr = []
|
654
|
+
photo.elements.each('tags/tag') { |tag|
|
655
|
+
tags_arr << {
|
656
|
+
'id' => tag.attributes['id'],
|
657
|
+
'text' => tag.text
|
658
|
+
}
|
659
|
+
}
|
660
|
+
urls = photo.elements['urls']
|
661
|
+
urls_arr = []
|
662
|
+
photo.elements.each('urls/url') { |url|
|
663
|
+
urls_arr << url.text
|
664
|
+
}
|
665
|
+
return {
|
666
|
+
'id' => photo.attributes['id'],
|
667
|
+
'isfavorite' => photo.attributes['isfavorite'],
|
668
|
+
'license' => photo.attributes['license'],
|
669
|
+
'views' => photo.attributes['views'],
|
670
|
+
'media' => photo.attributes['media'],
|
671
|
+
'title' => photo.elements['title'].text,
|
672
|
+
'owner_nsid' => owner.attributes['nsid'],
|
673
|
+
'owner_username'=> owner.attributes['username'],
|
674
|
+
'owner_realname'=> owner.attributes['realname'],
|
675
|
+
'owner_location'=> owner.attributes['location'],
|
676
|
+
'date_posted' => date.attributes['posted'],
|
677
|
+
'date_taken' => date.attributes['taken'],
|
678
|
+
'tags' => tags_arr,
|
679
|
+
'urls' => urls_arr
|
680
|
+
}
|
681
|
+
}
|
682
|
+
end
|
683
|
+
|
684
|
+
def search(user_id, tags, tag_mode, page = 0, per_page = 500)
|
685
|
+
method = 'flickr.photos.search'
|
686
|
+
data = _do_get(method, {
|
687
|
+
'api_key' => @config['api_key'],
|
688
|
+
'user_id' => user_id,
|
689
|
+
'tags' => tags,
|
690
|
+
'tag_mode' => tag_mode,
|
691
|
+
'page' => page,
|
692
|
+
'per_page' => per_page
|
693
|
+
|
694
|
+
}
|
695
|
+
)
|
696
|
+
doc = Document.new(data)
|
697
|
+
photos = []
|
698
|
+
doc.elements.each('rsp/photos/photo') { |photo|
|
699
|
+
photos << {
|
700
|
+
'id' => photo.attributes['id'],
|
701
|
+
'owner' => photo.attributes['owner']
|
702
|
+
}
|
703
|
+
}
|
704
|
+
return photos
|
705
|
+
end
|
706
|
+
|
707
|
+
def removeTag(auth_token, tag_id)
|
708
|
+
method = 'flickr.photos.removeTag'
|
709
|
+
api_sig = _get_api_sig(
|
710
|
+
{
|
711
|
+
'method' => method,
|
712
|
+
'auth_token' => config['token'],
|
713
|
+
'tag_id' => tag_id
|
714
|
+
}
|
715
|
+
)
|
716
|
+
data = _do_get(method, {
|
717
|
+
'api_sig' => api_sig,
|
718
|
+
'auth_token' => config['token'],
|
719
|
+
'tag_id' => tag_id
|
720
|
+
}
|
721
|
+
)
|
722
|
+
if data
|
723
|
+
return true
|
724
|
+
end
|
725
|
+
end
|
726
|
+
|
727
|
+
end
|
728
|
+
|
729
|
+
class People < Flickr
|
730
|
+
|
731
|
+
def getPublicPhotos(user_id)
|
732
|
+
method = 'flickr.people.getPublicPhotos'
|
733
|
+
photos = []
|
734
|
+
page = 1
|
735
|
+
pages = 0
|
736
|
+
|
737
|
+
# Find all the photos on all the pages
|
738
|
+
begin
|
739
|
+
data = _do_get(method, {
|
740
|
+
'api_key' => @config['api_key'],
|
741
|
+
'user_id' => user_id,
|
742
|
+
'page' => page
|
743
|
+
|
744
|
+
}
|
745
|
+
)
|
746
|
+
doc = Document.new(data)
|
747
|
+
doc.elements.each('rsp/photos') { |object|
|
748
|
+
pages = object.attributes['pages']
|
749
|
+
puts 'page ' + object.attributes['page'] + ' of ' + pages
|
750
|
+
}
|
751
|
+
doc.elements.each('rsp/photos/photo') { |photo|
|
752
|
+
photos << {
|
753
|
+
'id' => photo.attributes['id'],
|
754
|
+
'owner' => photo.attributes['owner'],
|
755
|
+
'secret' => photo.attributes['secret'],
|
756
|
+
'server' => photo.attributes['server'],
|
757
|
+
'farm' => photo.attributes['farm'],
|
758
|
+
'title' => photo.attributes['title'],
|
759
|
+
'ispublic' => photo.attributes['ispublic'],
|
760
|
+
'isfriend' => photo.attributes['isfriend'],
|
761
|
+
'isfamily' => photo.attributes['isfamily']
|
762
|
+
}
|
763
|
+
}
|
764
|
+
page = page + 1
|
765
|
+
end while page <= pages.to_i
|
766
|
+
|
767
|
+
return photos
|
768
|
+
end
|
769
|
+
|
770
|
+
end
|
771
|
+
|
772
|
+
class Upload < Flickr
|
773
|
+
|
774
|
+
def _to_multipart(name, value)
|
775
|
+
return "Content-Disposition: form-data; name=\"#{CGI::escape(name)}\"\r\n\r\n#{value}\r\n"
|
776
|
+
end
|
777
|
+
|
778
|
+
def _file_to_multipart(name, file, content)
|
779
|
+
return "Content-Disposition: form-data; name=\"#{CGI::escape(name)}\"; filename=\"#{file}\"\r\n" +
|
780
|
+
"Content-Transfer-Encoding: binary\r\n" +
|
781
|
+
"Content-Type: image/jpeg\r\n\r\n" + content + "\r\n"
|
782
|
+
end
|
783
|
+
|
784
|
+
def _prepare_query(params)
|
785
|
+
query = params.collect { |k, v|
|
786
|
+
if v.respond_to?(:read)
|
787
|
+
q = _file_to_multipart(k, v.path, v.read)
|
788
|
+
else
|
789
|
+
q = _to_multipart(k, v)
|
790
|
+
end
|
791
|
+
"--" + @boundary + "\r\n" + q
|
792
|
+
}.join("") + "--" + @boundary + "--"
|
793
|
+
header = {"Content-type" => "multipart/form-data, boundary=" + @boundary + " "}
|
794
|
+
return query, header
|
795
|
+
end
|
796
|
+
|
797
|
+
def upload(photo, title='', description='', tags='', is_public=1, is_friend=0, is_family=0)
|
798
|
+
@flickr_host = 'www.flickr.com'
|
799
|
+
@upload_action = '/services/upload/'
|
800
|
+
@boundary = MD5.md5(photo).to_s
|
801
|
+
file = File.new(photo, 'rb')
|
802
|
+
api_sig = _get_api_sig(
|
803
|
+
{
|
804
|
+
'auth_token' => config['token'],
|
805
|
+
'title' => title,
|
806
|
+
'description' => description,
|
807
|
+
'tags' => tags,
|
808
|
+
'is_public' => is_public,
|
809
|
+
'is_family' => is_family,
|
810
|
+
'is_friend' => is_friend
|
811
|
+
}
|
812
|
+
)
|
813
|
+
params = {
|
814
|
+
'api_key' => config['api_key'],
|
815
|
+
'api_sig' => api_sig,
|
816
|
+
'auth_token' => config['token'],
|
817
|
+
'photo' => file,
|
818
|
+
'title' => title,
|
819
|
+
'description' => description,
|
820
|
+
'tags' => tags,
|
821
|
+
'is_public' => is_public,
|
822
|
+
'is_family' => is_family,
|
823
|
+
'is_friend' => is_friend
|
824
|
+
}
|
825
|
+
query, header = _prepare_query(params)
|
826
|
+
file.close
|
827
|
+
Net::HTTP.start(@flickr_host, 80) { |http|
|
828
|
+
http.read_timeout = 10000
|
829
|
+
http.open_timeout = 10000
|
830
|
+
response = http.post(@upload_action, query, header)
|
831
|
+
doc = Document.new(response.body)
|
832
|
+
status = doc.elements['rsp'].attributes['stat']
|
833
|
+
if status == "ok"
|
834
|
+
photoid = doc.elements['rsp/photoid'].text
|
835
|
+
return photoid
|
836
|
+
else
|
837
|
+
return false
|
838
|
+
end
|
839
|
+
}
|
840
|
+
end
|
841
|
+
|
842
|
+
def replace(photo, photo_id)
|
843
|
+
@flickr_host = 'www.flickr.com'
|
844
|
+
@upload_action = '/services/replace/'
|
845
|
+
@boundary = MD5.md5(photo).to_s
|
846
|
+
file = File.new(photo, 'rb')
|
847
|
+
api_sig = _get_api_sig(
|
848
|
+
{
|
849
|
+
'auth_token' => config['token'],
|
850
|
+
'photo_id' => photo_id
|
851
|
+
}
|
852
|
+
)
|
853
|
+
params = {
|
854
|
+
'api_key' => config['api_key'],
|
855
|
+
'api_sig' => api_sig,
|
856
|
+
'auth_token' => config['token'],
|
857
|
+
'photo' => file,
|
858
|
+
'photo_id' => photo_id
|
859
|
+
}
|
860
|
+
query, header = _prepare_query(params)
|
861
|
+
file.close
|
862
|
+
Net::HTTP.start(@flickr_host, 80) { |http|
|
863
|
+
http.read_timeout = 10000
|
864
|
+
http.open_timeout = 10000
|
865
|
+
response = http.post(@upload_action, query, header)
|
866
|
+
doc = Document.new(response.body)
|
867
|
+
status = doc.elements['rsp'].attributes['stat']
|
868
|
+
if status == "ok"
|
869
|
+
photoid = doc.elements['rsp/photoid'].text
|
870
|
+
return photoid
|
871
|
+
else
|
872
|
+
return false
|
873
|
+
end
|
874
|
+
}
|
875
|
+
end
|
876
|
+
|
877
|
+
end
|
878
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hjw3001-flickrx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Henry Wagner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-12 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Ruby implementation of Flickr API.
|
17
|
+
email: hjw3001@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- lib/flickrx.rb
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- init.rb
|
27
|
+
- lib/flickrx.rb
|
28
|
+
- Rakefile
|
29
|
+
- README.rdoc
|
30
|
+
- Manifest
|
31
|
+
- flickrx.gemspec
|
32
|
+
has_rdoc: true
|
33
|
+
homepage: http://github.com/hjw3001/flickrx
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options:
|
36
|
+
- --line-numbers
|
37
|
+
- --inline-source
|
38
|
+
- --title
|
39
|
+
- Flickrx
|
40
|
+
- --main
|
41
|
+
- README.rdoc
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "1.2"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project: flickrx
|
59
|
+
rubygems_version: 1.2.0
|
60
|
+
signing_key:
|
61
|
+
specification_version: 2
|
62
|
+
summary: Ruby implementation of Flickr API.
|
63
|
+
test_files: []
|
64
|
+
|