digitalpardoe-rflickr 1.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,109 @@
1
+ # rFlickr: A Ruby based Flickr API implementation.
2
+ # Copyright (C) 2009, Alex Pardoe (digital:pardoe)
3
+ #
4
+ # Derrived from work by Trevor Schroeder, see here:
5
+ # http://rubyforge.org/projects/rflickr/.
6
+ #
7
+ # This program is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License
9
+ # as published by the Free Software Foundation; either version 2
10
+ # of the License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
+
21
+ require 'flickr/base'
22
+
23
+ class Flickr::Method
24
+ attr_reader :name,:authenticated,:description,:response,:explanation,
25
+ :arguments, :errors
26
+
27
+ def initialize(name,authenticated,description,response,explanation)
28
+ @name = name
29
+ @authenticated = authenticated
30
+ @description = description
31
+ @response = response
32
+ @explanation = explanation
33
+ @arguments = []
34
+ @errors = []
35
+ end
36
+ end
37
+
38
+ class Flickr::MethodArgument
39
+ attr_reader :name, :optional, :description
40
+
41
+ def initialize(name,optional,description)
42
+ @name = name
43
+ @optional = optional
44
+ @description = description
45
+ end
46
+ end
47
+
48
+ class Flickr::Reflection < Flickr::APIBase
49
+ # We don't bother with caching because it's not worth it for the
50
+ # reflection API.
51
+ def getMethodInfo(method_name)
52
+ res = @flickr.call_method('flickr.reflection.getMethodInfo',
53
+ 'method_name' => method_name)
54
+ els = res.elements
55
+ att = res.root.attributes
56
+ desc = els['/method/description'] ?
57
+ els['/method/description'].text : nil
58
+ resp = els['/method/response'] ?
59
+ els['/method/response'].text : nil
60
+ expl = els['/method/explanation'] ?
61
+ els['/method/explanation'].text : nil
62
+ meth = Flickr::Method.new(att['name'],att['needslogin'].to_i==1,
63
+ desc,resp,expl)
64
+ els['/method/arguments'].each_element do |el|
65
+ att = el.attributes
66
+ arg = Flickr::MethodArgument.new(att['name'],
67
+ att['optional'].to_i == 1,el.text)
68
+ meth.arguments << arg
69
+ end
70
+ els['/method/errors'].each_element do |el|
71
+ att = el.attributes
72
+ err = XMLRPC::FaultException.new(att['code'].to_i,
73
+ el.text)
74
+ meth.errors << err
75
+ end
76
+ return meth
77
+ end
78
+
79
+ def getMethods
80
+ res = @flickr.call_method('flickr.reflection.getMethods')
81
+ list = []
82
+ res.elements['/methods'].each_element do |el|
83
+ list << el.text
84
+ end
85
+ return list
86
+ end
87
+
88
+ def missing_methods
89
+ list = []
90
+ methods = self.getMethods
91
+ methods.each do |mname|
92
+ parts = mname.split('.')
93
+ parts.shift
94
+ call = parts.pop
95
+ obj = @flickr
96
+ parts.each do |part|
97
+ if obj.respond_to?(part)
98
+ obj = obj.method(part).call
99
+ else
100
+ obj = nil
101
+ list << mname
102
+ break
103
+ end
104
+ end
105
+ list << mname if (obj && !obj.respond_to?(call))
106
+ end
107
+ return list
108
+ end
109
+ end
@@ -0,0 +1,79 @@
1
+ # rFlickr: A Ruby based Flickr API implementation.
2
+ # Copyright (C) 2009, Alex Pardoe (digital:pardoe)
3
+ #
4
+ # Derrived from work by Trevor Schroeder, see here:
5
+ # http://rubyforge.org/projects/rflickr/.
6
+ #
7
+ # This program is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License
9
+ # as published by the Free Software Foundation; either version 2
10
+ # of the License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
+
21
+ require 'flickr/base'
22
+
23
+ class Flickr::Tags < Flickr::APIBase
24
+ def getListPhoto(photo)
25
+ photo = photo.id if photo.class == Flickr::Photo
26
+ res = @flickr.call_method('flickr.tags.getListPhoto',
27
+ 'photo_id'=>photo)
28
+ xml = res.root
29
+ phid = xml.attributes['id']
30
+ photo = (photo.class == Flickr::Photo) ? photo :
31
+ (@flickr.photo_cache_lookup(phid) ||
32
+ Flickr::Photo.new(@flickr,phid))
33
+ if xml.elements['tags']
34
+ tags = []
35
+ xml.elements['tags'].each_element do |el|
36
+ tags << Flickr::Tag.from_xml(el,photo)
37
+ end
38
+ end
39
+ photo.tags = tags
40
+ return tags
41
+ end
42
+
43
+ def getListUserPopular(user,count = nil)
44
+ user = user.nsid if user.class == Flickr::Person
45
+ args = { 'user_id' => user }
46
+ args['count'] = count if count
47
+
48
+ res = @flickr.call_method('flickr.tags.getListUserPopular',args)
49
+ tags = {}
50
+ res.elements['/who/tags'].each_element do |tag|
51
+ att = tag.attributes
52
+ tags[tag.text]=att['count'].to_i
53
+ end
54
+ return tags
55
+ end
56
+
57
+ def getListUser(user)
58
+ user = user.nsid if user.class == Flickr::Person
59
+ args = { 'user_id' => user }
60
+
61
+ res = @flickr.call_method('flickr.tags.getListUser',args)
62
+ tags = []
63
+ res.elements['/who/tags'].each_element do |tag|
64
+ tags << tag.text
65
+ end
66
+ return tags
67
+ end
68
+
69
+ def getRelated(tag)
70
+ args = { 'tag' => tag }
71
+
72
+ res = @flickr.call_method('flickr.tags.getRelated',args)
73
+ tags = []
74
+ res.elements['/tags'].each_element do |tag|
75
+ tags << tag.text
76
+ end
77
+ return tags
78
+ end
79
+ end
@@ -0,0 +1,29 @@
1
+ # rFlickr: A Ruby based Flickr API implementation.
2
+ # Copyright (C) 2009, Alex Pardoe (digital:pardoe)
3
+ #
4
+ # Derrived from work by Trevor Schroeder, see here:
5
+ # http://rubyforge.org/projects/rflickr/.
6
+ #
7
+ # This program is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License
9
+ # as published by the Free Software Foundation; either version 2
10
+ # of the License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
+
21
+ require 'flickr/base'
22
+
23
+ class Flickr::Transform < Flickr::APIBase
24
+ def rotate(photo,degrees)
25
+ photo = photo.id if photo.class == Flickr::Photo
26
+ @flickr.call_method('flickr.photos.transform.rotate',
27
+ 'photo_id' => photo, 'degrees' => degrees)
28
+ end
29
+ end
@@ -0,0 +1,225 @@
1
+ # rFlickr: A Ruby based Flickr API implementation.
2
+ # Copyright (C) 2009, Alex Pardoe (digital:pardoe)
3
+ #
4
+ # Derrived from work by Trevor Schroeder, see here:
5
+ # http://rubyforge.org/projects/rflickr/.
6
+ #
7
+ # This program is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License
9
+ # as published by the Free Software Foundation; either version 2
10
+ # of the License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
+
21
+ require 'flickr/base'
22
+ require 'mime/types'
23
+ require 'net/http'
24
+
25
+ class Flickr::Ticket
26
+ attr_reader :id
27
+ attr_accessor :complete, :invalid, :photoid
28
+
29
+ COMPLETE=[:incomplete,:completed,:failed]
30
+
31
+ def initialize(id,upload)
32
+ @id = id
33
+ @upload = upload
34
+ end
35
+
36
+ def check
37
+ t = @upload.checkTickets(self)[0]
38
+ self.complete = t.complete
39
+ self.invalid = t.invalid
40
+ self.photoid = t.photoid
41
+ return t
42
+ end
43
+ end
44
+
45
+ class Flickr::FormPart
46
+ attr_reader :data, :mime_type, :attributes
47
+
48
+ def initialize(name,data,mime_type=nil)
49
+ @attributes = {}
50
+ @attributes['name'] = name
51
+ @data = data
52
+ @mime_type = mime_type
53
+ end
54
+
55
+ def to_s
56
+ ([ "Content-Disposition: form-data" ] +
57
+ attributes.map{|k,v| "#{k}=\"#{v}\""}).
58
+ join('; ') + "\r\n"+
59
+ (@mime_type ? "Content-Type: #{@mime_type}\r\n" : '')+
60
+ "\r\n#{data}"
61
+ end
62
+ end
63
+
64
+ class Flickr::MultiPartForm
65
+ attr_accessor :boundary, :parts
66
+
67
+ def initialize(boundary=nil)
68
+ @boundary = boundary ||
69
+ "----------------------------Ruby#{rand(1000000000000)}"
70
+ @parts = []
71
+ end
72
+
73
+ def to_s
74
+ "--#@boundary\r\n"+
75
+ parts.map{|p| p.to_s}.join("\r\n--#@boundary\r\n")+
76
+ "\r\n--#@boundary--\r\n"
77
+ end
78
+ end
79
+
80
+ class Flickr::Upload < Flickr::APIBase
81
+
82
+ # TODO: It would probably be better if we wrapped the fault
83
+ # in something more meaningful. At the very least, a broad
84
+ # division of errors, such as retryable and fatal.
85
+ def error(el)
86
+ att = el.attributes
87
+ fe = XMLRPC::FaultException.new(att['code'].to_i,
88
+ att['msg'])
89
+ $stderr.puts "ERR: #{fe.faultString} (#{fe.faultCode})"
90
+ raise fe
91
+ end
92
+
93
+ def prepare_parts(data,mimetype,filename,title=nil,description=nil,
94
+ tags=nil, is_public=nil,is_friend=nil,is_family=nil,
95
+ sig=nil, async=nil)
96
+ parts = []
97
+ parts << Flickr::FormPart.new('title',title) if title
98
+ parts << Flickr::FormPart.new('description',description) if
99
+ description
100
+ parts << Flickr::FormPart.new('tags',tags.join(',')) if tags
101
+ parts << Flickr::FormPart.new('is_public',
102
+ is_public ? '1' : '0') if is_public != nil
103
+ parts << Flickr::FormPart.new('is_friend',
104
+ is_friend ? '1' : '0') if is_friend != nil
105
+ parts << Flickr::FormPart.new('is_family',
106
+ is_family ? '1' : '0') if is_family != nil
107
+ parts << Flickr::FormPart.new('async',
108
+ async ? '1' : '0') if async != nil
109
+
110
+ parts << Flickr::FormPart.new('api_key',@flickr.api_key)
111
+ parts << Flickr::FormPart.new('auth_token',
112
+ @flickr.auth.token.token)
113
+ parts << Flickr::FormPart.new('api_sig',sig)
114
+
115
+ parts << Flickr::FormPart.new('photo',data,mimetype)
116
+ parts.last.attributes['filename'] = filename
117
+ return parts
118
+ end
119
+
120
+ def make_signature(title=nil,description=nil, tags=nil,
121
+ is_public=nil,is_friend=nil,is_family=nil,async=nil)
122
+ args = {'api_key' => @flickr.api_key,
123
+ 'auth_token' => @flickr.auth.token.token}
124
+ args['title'] = title if title
125
+ args['description'] = description if description
126
+ args['tags'] = tags.join(',') if tags
127
+ args['is_public'] = (is_public ? '1' : '0') if is_public != nil
128
+ args['is_friend'] = (is_friend ? '1' : '0') if is_friend != nil
129
+ args['is_family'] = (is_family ? '1' : '0') if is_family != nil
130
+ args['async'] = (async ? '1' : '0') if async != nil
131
+ args['api_sig'] = @flickr.sign(args)
132
+ end
133
+
134
+ def send_form(form)
135
+ headers = {"Content-Type" =>
136
+ "multipart/form-data; boundary=" + form.boundary}
137
+
138
+ http = Net::HTTP.new('www.flickr.com', 80)
139
+ # http.read_timeout = 900 # 15 minutes max upload time
140
+ tries = 3
141
+ begin
142
+ res=http.post('/services/upload/',form.to_s,headers)
143
+ rescue Timeout::Error => err
144
+ tries -= 1
145
+ $stderr.puts "Timed out, will retry #{tries} more."
146
+ retry if tries > 0
147
+ raise err
148
+ end
149
+ return res
150
+ end
151
+
152
+ def upload_file_async(filename,title=nil,description=nil,tags=nil,
153
+ is_public=nil,is_friend=nil,is_family=nil)
154
+ mt = MIME::Types.of(filename)
155
+ f = File.open(filename,'rb')
156
+ data = f.read
157
+ f.close
158
+ return upload_image_async(data,mt,filename,title,description,
159
+ tags, is_public,is_friend,is_family)
160
+ end
161
+
162
+
163
+ def upload_file(filename,title=nil,description=nil,tags=nil,
164
+ is_public=nil,is_friend=nil,is_family=nil)
165
+ mt = MIME::Types.of(filename)
166
+ f = File.open(filename,'rb')
167
+ data = f.read
168
+ f.close
169
+ return upload_image(data,mt,filename,title,description,tags,
170
+ is_public,is_friend,is_family)
171
+ end
172
+
173
+ def upload_image_async(data,mimetype,filename,title=nil,description=nil,
174
+ tags=nil, is_public=nil,is_friend=nil,is_family=nil)
175
+ form = Flickr::MultiPartForm.new
176
+
177
+ sig = make_signature(title,description, tags, is_public,
178
+ is_friend, is_family, true)
179
+ form.parts += prepare_parts(data,mimetype,filename,title,
180
+ description, tags, is_public, is_friend,
181
+ is_family, sig, true)
182
+ res = REXML::Document.new(send_form(form).body)
183
+ error(res.elements['/rsp/err']) if res.elements['/rsp/err']
184
+ t = Flickr::Ticket.new(res.elements['/rsp/ticketid'].text, self)
185
+ @flickr.ticket_cache_store(t)
186
+ return t
187
+ end
188
+
189
+ def upload_image(data,mimetype,filename,title=nil,description=nil,
190
+ tags=nil, is_public=nil,is_friend=nil,is_family=nil)
191
+ form = Flickr::MultiPartForm.new
192
+
193
+ sig = make_signature(title,description, tags, is_public,
194
+ is_friend, is_family)
195
+ form.parts += prepare_parts(data,mimetype,filename,title,
196
+ description, tags, is_public, is_friend,
197
+ is_family, sig)
198
+ res = REXML::Document.new(send_form(form).body)
199
+ error(res.elements['/rsp/err']) if res.elements['/rsp/err']
200
+ val = res.elements['/rsp/photoid'].text
201
+ return val
202
+ end
203
+
204
+ def checkTickets(tickets)
205
+ tickets = [tickets] if tickets.class != Array
206
+ targ = tickets.map{|t|
207
+ t.id.to_s if t.class == Flickr::Ticket }.join(',')
208
+ res = @flickr.call_method('flickr.photos.upload.checkTickets',
209
+ 'tickets' => targ)
210
+ tickets = []
211
+ res.elements['/uploader'].each_element('ticket') do |tick|
212
+ att = tick.attributes
213
+ tid = att['id']
214
+ t = @flickr.ticket_cache_lookup(tid) ||
215
+ Flickr::Ticket.new(tid,self)
216
+ t.complete = Flickr::Ticket::COMPLETE[att['complete'].to_i]
217
+ t.photoid = att['photoid']
218
+ t.invalid = true if (att['invalid'] &&
219
+ (att['invalid'].to_i == 1))
220
+ @flickr.ticket_cache_store(t)
221
+ tickets << t
222
+ end
223
+ return tickets
224
+ end
225
+ end
@@ -0,0 +1,69 @@
1
+ # rFlickr: A Ruby based Flickr API implementation.
2
+ # Copyright (C) 2009, Alex Pardoe (digital:pardoe)
3
+ #
4
+ # Derrived from work by Trevor Schroeder, see here:
5
+ # http://rubyforge.org/projects/rflickr/.
6
+ #
7
+ # This program is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License
9
+ # as published by the Free Software Foundation; either version 2
10
+ # of the License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
+
21
+ require 'flickr/base'
22
+
23
+ class Flickr::Urls < Flickr::APIBase
24
+ def getGroup(group)
25
+ group = group.nsid if group.class == Flickr::Group
26
+ res = @flickr.call_method('flickr.urls.getGroup',
27
+ 'group_id' => group)
28
+ return res.elements['/group'].attributes['url']
29
+ end
30
+
31
+ def getUserPhotos(user)
32
+ user = user.nsid if user.respond_to?(:nsid)
33
+ args = {}
34
+ args['user_id'] = user if user
35
+ res = @flickr.call_method('flickr.urls.getUserPhotos',args)
36
+ return res.elements['/user'].attributes['url']
37
+ end
38
+
39
+ def getUserProfile(user)
40
+ user = user.nsid if user.respond_to?(:nsid)
41
+ args = {}
42
+ args['user_id'] = user if user
43
+ res = @flickr.call_method('flickr.urls.getUserProfile',args)
44
+ return res.elements['/user'].attributes['url']
45
+ end
46
+
47
+ def lookupGroup(url)
48
+ res = @flickr.call_method('flickr.urls.lookupGroup','url'=>url)
49
+ els = res.elements
50
+ nsid = els['/group'].attributes['id']
51
+
52
+ g = @flickr.group_cache_lookup(nsid) ||
53
+ Flickr::Group.new(@flickr,nsid,
54
+ els['/group/groupname'].text)
55
+ @flickr.group_cache_store(g)
56
+ return g
57
+ end
58
+
59
+ def lookupUser(url)
60
+ res = @flickr.call_method('flickr.urls.lookupUser','url'=>url)
61
+ els = res.elements
62
+ nsid = els['/user'].attributes['id']
63
+ p = @flickr.person_cache_lookup(nsid) ||
64
+ Flickr::Person.new(@flickr,nsid,
65
+ els['/user/username'].text)
66
+ @flickr.person_cache_store(p)
67
+ return p
68
+ end
69
+ end