rflickr 2006.02.01

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,104 @@
1
+ require 'flickr/base'
2
+
3
+ class Flickr::PhotoSets < Flickr::APIBase
4
+ # photoset can be a PhotoSet or a a photoset id
5
+ # photo can be a Photo or a photo id
6
+ def addPhoto(photoset,photo)
7
+ photo = photo.id if photo.class == Flickr::Photo
8
+ photoset = photoset.id if photoset.class == Flickr::PhotoSet
9
+
10
+ @flickr.call_method('flickr.photosets.addPhoto',
11
+ 'photoset_id' => photoset, 'photo_id' => photo)
12
+ end
13
+
14
+ def create(title,primary_photo, description = nil)
15
+ primary_photo = primary_photo.id if
16
+ primary_photo.class == Flickr::Photo
17
+ args = { 'title' => title, 'primary_photo_id' =>
18
+ primary_photo}
19
+ args['description'] = description if description
20
+ res = @flickr.call_method('flickr.photosets.create',args)
21
+ id = res.elements['/photoset'].attributes['id']
22
+ url = res.elements['/photoset'].attributes['url']
23
+ set = Flickr::PhotoSet.new(id,@flickr)
24
+ set.title = title
25
+ set.url = url
26
+ @flickr.photoset_cache_store(set)
27
+ return set
28
+ end
29
+
30
+ def delete(photoset)
31
+ photoset = photoset.id if photoset.class == Flickr::PhotoSet
32
+ @flickr.call_method('flickr.photosets.delete',
33
+ 'photoset_id' => photoset)
34
+ end
35
+
36
+ def editMeta(photoset,title,description=nil)
37
+ photoset = photoset.id if photoset.class == Flickr::PhotoSet
38
+ args = {'photoset_id' => photoset,
39
+ 'title' => title}
40
+ args['description' ] = description if description
41
+ @flickr.call_method('flickr.photosets.editMeta',args)
42
+ end
43
+
44
+ def editPhotos(photoset,primary_photo,photos)
45
+ photoset = photoset.id if photoset.class == Flickr::PhotoSet
46
+ primary_photo = primary_photo.id if
47
+ primary_photo.class == Flickr::Photo
48
+ photos=photos.map{|p| p.id if p.class==Flickr::Photo}.join(',')
49
+ args = {'photoset_id' => photoset,
50
+ 'primary_photo_id' => primary_photo,
51
+ 'photo_ids' => photos }
52
+ @flickr.call_method('flickr.photosets.editPhotos',args)
53
+ end
54
+
55
+ def getContext(photo,photoset)
56
+ photoset = photoset.id if photoset.class == Flickr::PhotoSet
57
+ photo = photo.id if photo.class == Flickr::Photo
58
+ res = @flickr.call_method('flickr.photosets.getContext',
59
+ 'photo_id' => photo, 'photoset_id' => photoset)
60
+ return Flickr::Context.from_xml(res,@flickr)
61
+ end
62
+
63
+ def getList(user=nil)
64
+ user = user.nsid if user.respond_to?(:nsid)
65
+ args = {}
66
+ args['user_id'] = user if user
67
+ res = @flickr.call_method('flickr.photosets.getList',args)
68
+ list = []
69
+ res.elements['/photosets'].each_element do |el|
70
+ list << Flickr::PhotoSet.from_xml(el,@flickr)
71
+ end
72
+ return list
73
+ end
74
+
75
+ def removePhoto(photoset,photo)
76
+ photoset = photoset.id if photoset.class == Flickr::PhotoSet
77
+ photo = photo.id if photo.class == Flickr::Photo
78
+ @flickr.call_method('flickr.photosets.removePhoto',
79
+ 'photo_id' => photo, 'photoset_id' => photoset)
80
+ end
81
+
82
+ def getPhotos(photoset,extras=nil)
83
+ photoset = photoset.id if photoset.class == Flickr::PhotoSet
84
+ extras = extras.join(',') if extras.class == Array
85
+ args = { 'photoset_id' => photoset }
86
+ args['extras'] = extras if extras
87
+ res = @flickr.call_method('flickr.photosets.getPhotos',args)
88
+ return Flickr::PhotoSet.from_xml(res.root,@flickr)
89
+ end
90
+
91
+ def getInfo(photoset)
92
+ photoset = photoset.id if photoset.class == Flickr::PhotoSet
93
+ res = @flickr.call_method('flickr.photosets.getInfo',
94
+ 'photoset_id' => photoset)
95
+ return Flickr::PhotoSet.from_xml(res.root,@flickr)
96
+ end
97
+
98
+ def orderSets(photosets)
99
+ photosets=photosets.map { |ps|
100
+ (ps.class==Flickr::PhotoSet) ? ps.id : ps}.join(',')
101
+ @flickr.call_method('flickr.photosets.orderSets',
102
+ 'photoset_ids' => photosets)
103
+ end
104
+ end
@@ -0,0 +1,70 @@
1
+ require 'flickr/groups'
2
+
3
+ class Flickr::Pools < Flickr::APIBase
4
+ def initialize(flickr,groups)
5
+ super(flickr)
6
+ @groups = groups
7
+ end
8
+
9
+ # photo can be a Photo or photo_id
10
+ # group can be a Group or group_id
11
+ def add(photo,group)
12
+ group = group.nsid if group.class == Flickr::Group
13
+ photo = photo.id if photo.class == Flickr::Photo
14
+ @flickr.call_method('flickr.groups.pools.add',
15
+ 'group_id' => group, 'photo_id' => photo)
16
+ end
17
+
18
+ # photo can be a Photo or photo_id
19
+ # group can be a Group or group_id
20
+ def remove(photo,group)
21
+ group = group.nsid if group.class == Flickr::Group
22
+ photo = photo.id if photo.class == Flickr::Photo
23
+ @flickr.call_method('flickr.groups.pools.add',
24
+ 'group_id' => group, 'photo_id' => photo)
25
+ end
26
+
27
+ # photo can be a Photo or photo_id
28
+ # group can be a Group or group_id
29
+ def getContext(photo,group)
30
+ group = group.nsid if group.class == Flickr::Group
31
+ photo = photo.id if photo.class == Flickr::Photo
32
+ res = @flickr.call_method('flickr.groups.pools.getContex',
33
+ 'group_id' => group, 'photo_id' => photo)
34
+ return Flickr::Context.from_xml(res)
35
+ end
36
+
37
+ def getGroups
38
+ res = @flickr.call_method('flickr.groups.pools.getGroups')
39
+ list = []
40
+ res.elements['/groups'].each_element do |el|
41
+ att = el.attributes
42
+ nsid = att['nsid']
43
+ g = @flickr.group_cache_lookup(nsid) ||
44
+ Flickr::Group.new(@flickr,nsid,att['name'])
45
+ g.name = att['name']
46
+ g.admin = att['admin'].to_i == 1
47
+ g.privacy = Flickr::Group::PRIVACY[att['privacy'].to_i]
48
+ g.photo_count = att['photos'].to_i
49
+ g.iconserver = att['iconserver'].to_i
50
+
51
+ @flickr.group_cache_store(g)
52
+ list << g
53
+ end
54
+ return list
55
+ end
56
+
57
+ def getPhotos(group,tags=nil,extras=nil,per_page=nil,page=nil)
58
+ group = group.nsid if group.class == Flickr::Group
59
+ group = group.id.to_s if group.class == Flickr::PhotoPool
60
+ args = { 'group_id' => group }
61
+ args['tags'] = tags.map{|t| t.clean if t.class ==
62
+ Flick::Tag}.join(',') if tags
63
+ args['extras'] = extras.join(',') if extras.class == Array
64
+ args['per_page'] = per_page if per_page
65
+ args['page'] = page if page
66
+
67
+ res = @flickr.call_method('flickr.groups.pools.getPhotos', args)
68
+ return Flickr::PhotoList.from_xml(res,@flickr)
69
+ end
70
+ end
@@ -0,0 +1,89 @@
1
+ require 'flickr/base'
2
+
3
+ class Flickr::Method
4
+ attr_reader :name,:authenticated,:description,:response,:explanation,
5
+ :arguments, :errors
6
+
7
+ def initialize(name,authenticated,description,response,explanation)
8
+ @name = name
9
+ @authenticated = authenticated
10
+ @description = description
11
+ @response = response
12
+ @explanation = explanation
13
+ @arguments = []
14
+ @errors = []
15
+ end
16
+ end
17
+
18
+ class Flickr::MethodArgument
19
+ attr_reader :name, :optional, :description
20
+
21
+ def initialize(name,optional,description)
22
+ @name = name
23
+ @optional = optional
24
+ @description = description
25
+ end
26
+ end
27
+
28
+ class Flickr::Reflection < Flickr::APIBase
29
+ # We don't bother with caching because it's not worth it for the
30
+ # reflection API.
31
+ def getMethodInfo(method_name)
32
+ res = @flickr.call_method('flickr.reflection.getMethodInfo',
33
+ 'method_name' => method_name)
34
+ els = res.elements
35
+ att = res.root.attributes
36
+ desc = els['/method/description'] ?
37
+ els['/method/description'].text : nil
38
+ resp = els['/method/response'] ?
39
+ els['/method/response'].text : nil
40
+ expl = els['/method/explanation'] ?
41
+ els['/method/explanation'].text : nil
42
+ meth = Flickr::Method.new(att['name'],att['needslogin'].to_i==1,
43
+ desc,resp,expl)
44
+ els['/method/arguments'].each_element do |el|
45
+ att = el.attributes
46
+ arg = Flickr::MethodArgument.new(att['name'],
47
+ att['optional'].to_i == 1,el.text)
48
+ meth.arguments << arg
49
+ end
50
+ els['/method/errors'].each_element do |el|
51
+ att = el.attributes
52
+ err = XMLRPC::FaultException.new(att['code'].to_i,
53
+ el.text)
54
+ meth.errors << err
55
+ end
56
+ return meth
57
+ end
58
+
59
+ def getMethods
60
+ res = @flickr.call_method('flickr.reflection.getMethods')
61
+ list = []
62
+ res.elements['/methods'].each_element do |el|
63
+ list << el.text
64
+ end
65
+ return list
66
+ end
67
+
68
+ def missing_methods
69
+ list = []
70
+ methods = self.getMethods
71
+ methods.each do |mname|
72
+ parts = mname.split('.')
73
+ parts.shift
74
+ call = parts.pop
75
+ obj = @flickr
76
+ parts.each do |part|
77
+ if obj.respond_to?(part)
78
+ obj = obj.method(part).call
79
+ else
80
+ obj = nil
81
+ list << mname
82
+ break
83
+ end
84
+ end
85
+ list << mname if (obj && !obj.respond_to?(call))
86
+ end
87
+ return list
88
+ end
89
+ end
@@ -0,0 +1,59 @@
1
+ require 'flickr/base'
2
+
3
+ class Flickr::Tags < Flickr::APIBase
4
+ def getListPhoto(photo)
5
+ photo = photo.id if photo.class == Flickr::Photo
6
+ res = @flickr.call_method('flickr.tags.getListPhoto',
7
+ 'photo_id'=>photo)
8
+ xml = res.root
9
+ phid = xml.attributes['id']
10
+ photo = (photo.class == Flickr::Photo) ? photo :
11
+ (@flickr.photo_cache_lookup(phid) ||
12
+ Flickr::Photo.new(@flickr,phid))
13
+ if xml.elements['tags']
14
+ tags = []
15
+ xml.elements['tags'].each_element do |el|
16
+ tags << Flickr::Tag.from_xml(el,photo)
17
+ end
18
+ end
19
+ photo.tags = tags
20
+ return tags
21
+ end
22
+
23
+ def getListUserPopular(user,count = nil)
24
+ user = user.nsid if user.class == Flickr::Person
25
+ args = { 'user_id' => user }
26
+ args['count'] = count if count
27
+
28
+ res = @flickr.call_method('flickr.tags.getListUserPopular',args)
29
+ tags = {}
30
+ res.elements['/who/tags'].each_element do |tag|
31
+ att = tag.attributes
32
+ tags[tag.text]=att['count'].to_i
33
+ end
34
+ return tags
35
+ end
36
+
37
+ def getListUser(user)
38
+ user = user.nsid if user.class == Flickr::Person
39
+ args = { 'user_id' => user }
40
+
41
+ res = @flickr.call_method('flickr.tags.getListUser',args)
42
+ tags = []
43
+ res.elements['/who/tags'].each_element do |tag|
44
+ tags << tag.text
45
+ end
46
+ return tags
47
+ end
48
+
49
+ def getRelated(tag)
50
+ args = { 'tag' => tag }
51
+
52
+ res = @flickr.call_method('flickr.tags.getRelated',args)
53
+ tags = []
54
+ res.elements['/tags'].each_element do |tag|
55
+ tags << tag.text
56
+ end
57
+ return tags
58
+ end
59
+ end
@@ -0,0 +1,19 @@
1
+ require 'flickr/base'
2
+
3
+ class Flickr::Test < Flickr::APIBase
4
+ # This has to be a Hash
5
+ def echo(args)
6
+ return @flickr.call_method('flickr.test.echo',args)
7
+ end
8
+
9
+ def login
10
+ res = @flickr.call_method('flickr.test.login')
11
+ nsid = res.elements['/user'].attributes['id']
12
+ name = res.elements['/user/username'].text
13
+ p = @flickr.person_cache_lookup(nsid) ||
14
+ Flickr::Person.new(@flickr,nsid,name)
15
+ p.name = name
16
+ @flickr.person_cache_store(p)
17
+ return p
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ require 'flickr/base'
2
+
3
+ class Flickr::Transform < Flickr::APIBase
4
+ def rotate(photo,degrees)
5
+ photo = photo.id if photo.class == Flickr::Photo
6
+ @flickr.call_method('flickr.photos.transform.rotate',
7
+ 'photo_id' => photo, 'degrees' => degrees)
8
+ end
9
+ end
@@ -0,0 +1,205 @@
1
+ require 'flickr/base'
2
+ require 'mime/types'
3
+ require 'net/http'
4
+
5
+ class Flickr::Ticket
6
+ attr_reader :id
7
+ attr_accessor :complete, :invalid, :photoid
8
+
9
+ COMPLETE=[:incomplete,:completed,:failed]
10
+
11
+ def initialize(id,upload)
12
+ @id = id
13
+ @upload = upload
14
+ end
15
+
16
+ def check
17
+ t = @upload.checkTickets(self)[0]
18
+ self.complete = t.complete
19
+ self.invalid = t.invalid
20
+ self.photoid = t.photoid
21
+ return t
22
+ end
23
+ end
24
+
25
+ class Flickr::FormPart
26
+ attr_reader :data, :mime_type, :attributes
27
+
28
+ def initialize(name,data,mime_type=nil)
29
+ @attributes = {}
30
+ @attributes['name'] = name
31
+ @data = data
32
+ @mime_type = mime_type
33
+ end
34
+
35
+ def to_s
36
+ ([ "Content-Disposition: form-data" ] +
37
+ attributes.map{|k,v| "#{k}=\"#{v}\""}).
38
+ join('; ') + "\r\n"+
39
+ (@mime_type ? "Content-Type: #{@mime_type}\r\n" : '')+
40
+ "\r\n#{data}"
41
+ end
42
+ end
43
+
44
+ class Flickr::MultiPartForm
45
+ attr_accessor :boundary, :parts
46
+
47
+ def initialize(boundary=nil)
48
+ @boundary = boundary ||
49
+ "----------------------------Ruby#{rand(1000000000000)}"
50
+ @parts = []
51
+ end
52
+
53
+ def to_s
54
+ "--#@boundary\r\n"+
55
+ parts.map{|p| p.to_s}.join("\r\n--#@boundary\r\n")+
56
+ "\r\n--#@boundary--\r\n"
57
+ end
58
+ end
59
+
60
+ class Flickr::Upload < Flickr::APIBase
61
+
62
+ # TODO: It would probably be better if we wrapped the fault
63
+ # in something more meaningful. At the very least, a broad
64
+ # division of errors, such as retryable and fatal.
65
+ def error(el)
66
+ att = el.attributes
67
+ fe = XMLRPC::FaultException.new(att['code'].to_i,
68
+ att['msg'])
69
+ $stderr.puts "ERR: #{fe.faultString} (#{fe.faultCode})"
70
+ raise fe
71
+ end
72
+
73
+ def prepare_parts(data,mimetype,filename,title=nil,description=nil,
74
+ tags=nil, is_public=nil,is_friend=nil,is_family=nil,
75
+ sig=nil, async=nil)
76
+ parts = []
77
+ parts << Flickr::FormPart.new('title',title) if title
78
+ parts << Flickr::FormPart.new('description',description) if
79
+ description
80
+ parts << Flickr::FormPart.new('tags',tags.join(',')) if tags
81
+ parts << Flickr::FormPart.new('is_public',
82
+ is_public ? '1' : '0') if is_public != nil
83
+ parts << Flickr::FormPart.new('is_friend',
84
+ is_friend ? '1' : '0') if is_friend != nil
85
+ parts << Flickr::FormPart.new('is_family',
86
+ is_family ? '1' : '0') if is_family != nil
87
+ parts << Flickr::FormPart.new('async',
88
+ async ? '1' : '0') if async != nil
89
+
90
+ parts << Flickr::FormPart.new('api_key',@flickr.api_key)
91
+ parts << Flickr::FormPart.new('auth_token',
92
+ @flickr.auth.token.token)
93
+ parts << Flickr::FormPart.new('api_sig',sig)
94
+
95
+ parts << Flickr::FormPart.new('photo',data,mimetype)
96
+ parts.last.attributes['filename'] = filename
97
+ return parts
98
+ end
99
+
100
+ def make_signature(title=nil,description=nil, tags=nil,
101
+ is_public=nil,is_friend=nil,is_family=nil,async=nil)
102
+ args = {'api_key' => @flickr.api_key,
103
+ 'auth_token' => @flickr.auth.token.token}
104
+ args['title'] = title if title
105
+ args['description'] = description if description
106
+ args['tags'] = tags.join(',') if tags
107
+ args['is_public'] = (is_public ? '1' : '0') if is_public != nil
108
+ args['is_friend'] = (is_friend ? '1' : '0') if is_friend != nil
109
+ args['is_family'] = (is_family ? '1' : '0') if is_family != nil
110
+ args['async'] = (async ? '1' : '0') if async != nil
111
+ args['api_sig'] = @flickr.sign(args)
112
+ end
113
+
114
+ def send_form(form)
115
+ headers = {"Content-Type" =>
116
+ "multipart/form-data; boundary=" + form.boundary}
117
+
118
+ http = Net::HTTP.new('www.flickr.com', 80)
119
+ # http.read_timeout = 900 # 15 minutes max upload time
120
+ tries = 3
121
+ begin
122
+ res=http.post('/services/upload/',form.to_s,headers)
123
+ rescue Timeout::Error => err
124
+ tries -= 1
125
+ $stderr.puts "Timed out, will retry #{tries} more."
126
+ retry if tries > 0
127
+ raise err
128
+ end
129
+ return res
130
+ end
131
+
132
+ def upload_file_async(filename,title=nil,description=nil,tags=nil,
133
+ is_public=nil,is_friend=nil,is_family=nil)
134
+ mt = MIME::Types.of(filename)
135
+ f = File.open(filename,'rb')
136
+ data = f.read
137
+ f.close
138
+ return upload_image_async(data,mt,filename,title,description,
139
+ tags, is_public,is_friend,is_family)
140
+ end
141
+
142
+
143
+ def upload_file(filename,title=nil,description=nil,tags=nil,
144
+ is_public=nil,is_friend=nil,is_family=nil)
145
+ mt = MIME::Types.of(filename)
146
+ f = File.open(filename,'rb')
147
+ data = f.read
148
+ f.close
149
+ return upload_image(data,mt,filename,title,description,tags,
150
+ is_public,is_friend,is_family)
151
+ end
152
+
153
+ def upload_image_async(data,mimetype,filename,title=nil,description=nil,
154
+ tags=nil, is_public=nil,is_friend=nil,is_family=nil)
155
+ form = Flickr::MultiPartForm.new
156
+
157
+ sig = make_signature(title,description, tags, is_public,
158
+ is_friend, is_family, true)
159
+ form.parts += prepare_parts(data,mimetype,filename,title,
160
+ description, tags, is_public, is_friend,
161
+ is_family, sig, true)
162
+ res = REXML::Document.new(send_form(form).body)
163
+ error(res.elements['/rsp/err']) if res.elements['/rsp/err']
164
+ t = Flickr::Ticket.new(res.elements['/rsp/ticketid'].text, self)
165
+ @flickr.ticket_cache_store(t)
166
+ return t
167
+ end
168
+
169
+ def upload_image(data,mimetype,filename,title=nil,description=nil,
170
+ tags=nil, is_public=nil,is_friend=nil,is_family=nil)
171
+ form = Flickr::MultiPartForm.new
172
+
173
+ sig = make_signature(title,description, tags, is_public,
174
+ is_friend, is_family)
175
+ form.parts += prepare_parts(data,mimetype,filename,title,
176
+ description, tags, is_public, is_friend,
177
+ is_family, sig)
178
+ res = REXML::Document.new(send_form(form).body)
179
+ error(res.elements['/rsp/err']) if res.elements['/rsp/err']
180
+ val = res.elements['/rsp/photoid'].text
181
+ return val
182
+ end
183
+
184
+ def checkTickets(tickets)
185
+ tickets = [tickets] if tickets.class != Array
186
+ targ = tickets.map{|t|
187
+ t.id.to_s if t.class == Flickr::Ticket }.join(',')
188
+ res = @flickr.call_method('flickr.photos.upload.checkTickets',
189
+ 'tickets' => targ)
190
+ tickets = []
191
+ res.elements['/uploader'].each_element('ticket') do |tick|
192
+ att = tick.attributes
193
+ tid = att['id']
194
+ t = @flickr.ticket_cache_lookup(tid) ||
195
+ Flickr::Ticket.new(tid,self)
196
+ t.complete = Flickr::Ticket::COMPLETE[att['complete'].to_i]
197
+ t.photoid = att['photoid']
198
+ t.invalid = true if (att['invalid'] &&
199
+ (att['invalid'].to_i == 1))
200
+ @flickr.ticket_cache_store(t)
201
+ tickets << t
202
+ end
203
+ return tickets
204
+ end
205
+ end