rflickr 2006.02.01

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.
@@ -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