Package elisa :: Package plugins :: Package ugly :: Package flickr :: Module flickr_media
[hide private]
[frames] | no frames]

Source Code for Module elisa.plugins.ugly.flickr.flickr_media

  1  # -*- coding: utf-8 -*- 
  2  # Elisa - Home multimedia server 
  3  # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Elisa with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Elisa is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Elisa" in the root directory of this distribution package 
 15  # for details on that license. 
 16   
 17   
 18  __maintainer__ = 'Benjamin Kampmann <benjamin@fluendo.com>' 
 19   
 20  from elisa.base_components.media_provider import MediaProvider 
 21  from elisa.core.media_uri import MediaUri 
 22  from elisa.core import common, component 
 23  from elisa.core.bus import bus_message 
 24  import os 
 25  from twisted.internet import defer, threads 
 26   
 27  from elisa.extern.flickrest import Flickr, FlickrError 
 28  from twill import commands as twill 
 29   
 30   
 31  from elisa.extern.translation import gettexter, N_ 
 32  T_ = gettexter('elisa-flickr') 
 33   
34 -class FlickrMedia(MediaProvider):
35 """ 36 DOCME 37 """ 38 secret = '14693e87a1349c20' 39 key = '4bb9b930c2f01fab6b3fd20e02d165fb' 40 41 config_doc = {'per_page' : 'show so many entries should be' \ 42 'shown per page?', 43 'login': 'Your Flickr username (optional)', 44 'password': 'Your Flickr password (optional)', 45 'locations': 'A list of tags or flickr:// URIs' 46 } 47 48 49 default_config = {'per_page': '30', 50 'login': '', 51 'password': '', 52 'locations': [] 53 } 54 55
56 - def initialize(self):
57 MediaProvider.initialize(self) 58 self._cache = {} 59 self._login = self.config.get('login','') 60 self._password = self.config.get('password','') 61 self._per_page = int(self.config.get('per_page', '30')) 62 self._locations = self.config.get('locations', []) 63 64 self._show_pages = False # Hardcoded, but I'll be a config-option 65 # when it is usable 66 self._connected = False 67 self._perm = "read" 68 69 if self._login and self._password: 70 self._perm = "write" 71 72 try: 73 self._flickr = Flickr(self.key, self.secret, self._perm) 74 if self._perm == "write": 75 threads.deferToThread(self._connect_flickr) 76 else: 77 self._connected_cb(None) 78 except FlickrError, e: 79 raise component.InitializeFailure(self.name, e.get('msg'))
80 81
82 - def _connected_cb(self, auth):
83 self.debug("Connected, %r", auth) 84 self._connected = True 85 86 uri = "flickr:///" 87 action_type = bus_message.MediaLocation.ActionType.LOCATION_ADDED 88 msg = bus_message.InternetLocation(action_type, "flickr", 'flickr', uri, 89 media_types=['image',], 90 theme_icon='flickr') 91 common.application.bus.send_message(msg)
92
93 - def _error_cb(self, failure):
94 self.warning('Failed to connect to flickr. Maybe the API-Key or the' 95 ' Secret is wrong. Error message :%s', 96 failure.getErrorMessage())
97
98 - def _connect_flickr(self):
99 100 def auth_open_url(state): 101 if state is None: 102 self._connected_cb(state) 103 else: 104 twill.go(state['url']) 105 twill.formvalue(1, 'login', self._login) 106 twill.formvalue(1, 'passwd', self._password) 107 twill.submit() 108 twill.config('readonly_controls_writeable', 'True') 109 try: 110 twill.formvalue(3, 'done_auth', '1') 111 twill.submit() 112 except: 113 # already granted 114 pass 115 dfr = self._flickr.authenticate_2(state) 116 dfr.addCallbacks(self._connected_cb, self._error_cb) 117 return dfr
118 119 self.debug("Authenticating") 120 self._flickr.authenticate_1().addCallbacks(auth_open_url, 121 self._error_cb)
122
123 - def scannable_uri_schemes__get(self):
124 return []
125
126 - def supported_uri_schemes__get(self):
127 return {'flickr' : 0}
128
129 - def get_real_uri(self, uri):
130 if self._blocking_is_directory(uri): 131 return uri 132 133 server = uri.get_param('server') 134 secret = uri.get_param('secret') 135 # remove the starting '/' 136 id = uri.path[1:] 137 # build the real URL for the Image 138 return MediaUri(self._build_uri(id, server, secret, 'medium'))
139
140 - def _build_uri(self, id, server, secret, size):
141 size_suffixes = {'square': '_s', 142 'thumbnail': '_t', 143 'small': '_m', 144 'medium': '', 145 'large': '_b', 146 'original': '_o', 147 } 148 uri = "http://static.flickr.com/%s/%s_%s%s.jpg" % (server, id, secret, 149 size_suffixes[size]) 150 return uri
151
152 - def get_media_type(self, uri):
153 return defer.succeed(self._blocking_get_media_type(uri))
154
155 - def _blocking_get_media_type(self, uri):
156 if self._blocking_is_directory(uri): 157 return {'file_type' : 'directory', 'mime_type' : ''} 158 else: 159 return {'file_type' : 'image', 'mime_type' : 'image/jpeg'}
160 161
162 - def is_directory(self, uri):
163 return defer.succeed(self._blocking_is_directory(uri))
164
165 - def _blocking_is_directory(self, uri):
166 return uri.host != "photo"
167
168 - def has_children_with_types(self, uri, media_types):
169 df = threads.deferToThread(self._blocking_has_children_with_types, uri, 170 media_types) 171 return df
172
173 - def _blocking_has_children_with_types(self, uri, media_types):
174 has_children = False 175 media_type_ok = len(set(['image', 176 'directory']).intersection(media_types)) > 0 177 if uri.host != 'photo' and media_type_ok: 178 has_children = True 179 return has_children
180 181
182 - def get_direct_children(self, uri, children_with_info):
183 if not self._connected: 184 dfr = defer.Deferred() 185 dfr.callback(children_with_info) 186 187 elif uri.host == '': 188 dfr = threads.deferToThread(self._build_main_menu, children_with_info) 189 else: 190 dfr = self._dispatch(uri, children_with_info) 191 192 return dfr
193 194
195 - def next_location(self, from_uri, root=None):
196 next_uri = None 197 198 def got_children(children): 199 self._cache[from_uri] = [ str(i[0]) for i in children ] 200 return MediaUri(self._cache[from_uri][0])
201 202 if self._blocking_is_directory(from_uri): 203 dfr = self.get_direct_children(from_uri,[]) 204 dfr.addCallback(got_children) 205 else: 206 for dir_uri, items in self._cache.iteritems(): 207 try: 208 index = items.index(str(from_uri)) 209 except: 210 pass 211 else: 212 try: 213 next_uri = MediaUri(items[index+1]) 214 except: 215 pass 216 else: 217 break 218 if next_uri: 219 if self._blocking_is_directory(next_uri): 220 dfr = self.next_location(next_uri, root) 221 else: 222 dfr = defer.succeed(next_uri) 223 else: 224 dfr = defer.succeed(None) 225 return dfr 226 227
228 - def _dispatch(self, uri, children_with_info):
229 page = int(uri.get_param('page', '0')) 230 231 if uri.host == 'mine': 232 if uri.path[1:] == 'latest': 233 dfr = self._flickr.photos_search(user_id='me', page=page, 234 per_page=self._per_page) 235 dfr.addCallback(self._got_images, children_with_info, str(uri)) 236 237 elif uri.path[1:] == 'photosets': 238 dfr = self._flickr.photosets_getList(per_page=self._per_page) 239 dfr.addCallback(self._got_photosets, children_with_info) 240 241 elif uri.path[1:] == "tags": 242 dfr = self._flickr.tags_getListUser(per_page=self._per_page) 243 dfr.addCallback(self._got_whotags, children_with_info) 244 245 elif uri.path[1:] == 'favorites': 246 dfr = self._flickr.favorites_getList(page=page) 247 dfr.addCallback(self._got_images, children_with_info,str(uri)) 248 249 else: 250 dfr = threads.deferToThread(self._build_mine_menu,children_with_info) 251 252 elif uri.host == 'photo': 253 dfr = defer.Deferred() 254 dfr.callback(children_with_info) 255 256 elif uri.host == 'photoset': 257 dfr = self._flickr.photosets_getPhotos(photoset_id=uri.path[1:], 258 page=page, 259 per_page=self._per_page) 260 dfr.addCallback(self._got_images_in_photoset, children_with_info, 261 str(uri)) 262 263 elif uri.host == 'interesting': 264 dfr = self._flickr.interestingness_getList(page=page, 265 per_page=self._per_page) 266 dfr.addCallback(self._got_images, children_with_info, str(uri)) 267 268 elif uri.host == "hottags": 269 dfr = self._flickr.tags_getHotList() 270 dfr.addCallback(self._got_hottags, children_with_info) 271 272 elif uri.host == "tag": 273 who = uri.get_param('who') 274 dfr = self._flickr.photos_search(tags=uri.path[1:], 275 user_id=who, 276 page=page, 277 per_page=self._per_page) 278 dfr.addCallback(self._got_images, children_with_info, str(uri)) 279 280 elif uri.host == "custom": 281 282 for location in self._locations: 283 children_with_info.append((MediaUri(location), {})) 284 dfr = defer.succeed(children_with_info) 285 else: 286 dfr = defer.succeed(children_with_info) 287 return dfr
288
289 - def _build_mine_menu(self, list_of_children):
290 291 mine_menu = {"flickr://mine/favorites" : T_(N_("my Favorites")), 292 "flickr://mine/latest" : T_(N_("latest")), 293 "flickr://mine/photosets" : T_(N_("in photosets")), 294 "flickr://mine/tags" : T_(N_("by tag"))} 295 296 return self._from_list(list_of_children, mine_menu)
297 298
299 - def _build_main_menu(self, list_of_children):
300 301 302 main_menu = {"flickr://interesting/": T_(N_("Interesting")), 303 "flickr://hottags/": T_(N_("Hot Tags")), 304 } 305 if self._perm == 'write': 306 main_menu["flickr://mine/latest"] = T_(N_("My Photos")) 307 if self._locations: 308 main_menu["flickr://custom/"] = T_(N_("Custom locations")) 309 310 return self._from_list(list_of_children, main_menu)
311
312 - def _from_list(self, list_of_children, menu):
313 314 for entry, label in menu.items(): 315 list_of_children.append((self._make_uri(entry, label), {})) 316 317 318 return list_of_children
319
320 - def _make_uri(self, uri, label=None):
321 m = MediaUri(uri) 322 if label != None: 323 m.label = label 324 return m
325
326 - def _got_images(self, ret, list_of_children, url=""):
327 photos = ret.find('photos') 328 pages = int(photos.get('pages')) 329 page = int(photos.get('page')) 330 331 for nu in ret.findall("photos/photo"): 332 self._add_photo(nu, list_of_children) 333 334 # We don't support more pages yet 335 if (pages > 1 and page == 1 and self._show_pages): 336 i = 1 337 while (i < pages): 338 i = i + 1 339 m = MediaUri(url) 340 m.set_param('page', i) 341 m.label = T_(N_('page %s'), i) 342 list_of_children.append((m,{})) 343 return list_of_children
344
345 - def _got_images_in_photoset(self, ret, list_of_children, url=''):
346 photos = ret.find('photoset') 347 pages = int(photos.get('pages')) 348 page = int(photos.get('page')) 349 350 for nu in ret.findall("photoset/photo"): 351 self._add_photo(nu, list_of_children) 352 353 # We don't support more pages before the GUADEC 07 354 if (pages > 1 and page == 1 and self._show_pages): 355 i = 1 356 while (i < pages): 357 i = i + 1 358 m = MediaUri(url) 359 m.set_param('page', i) 360 m.label = T_(N_('page %s'), i) 361 list_of_children.append((m,{})) 362 return list_of_children
363
364 - def _add_photo(self, nu, list_of_children):
365 id = nu.get('id') 366 title = nu.get('title') 367 server = nu.get('server') 368 secret = nu.get('secret') 369 370 uri = self._make_uri("flickr://photo/%s?server=%s&secret=%s" % 371 (id, server, secret), title) 372 list_of_children.append((uri, { 373 'title' : title, 374 'server' : server, 375 'secret' : secret, 376 'owner' : nu.get('owner'), 377 'ispublic' : nu.get('ispublic'), 378 'isfriend' : nu.get('isfriend'), 379 'isfamily' : nu.get('isfamily'), 380 'default_image': MediaUri(self._build_uri(id, server, secret, 381 'small') 382 ) 383 } 384 ) 385 ) 386 return list_of_children
387
388 - def _got_hottags(self, ret, list_of_children):
389 for nu in ret.findall("hottags/tag"): 390 name = nu.text 391 score = nu.get('score') 392 uri = MediaUri("flickr://tag/%s" % name) 393 list_of_children.append(( uri, {"name" : name, score: "score"})) 394 return list_of_children
395
396 - def _got_whotags(self, ret, list_of_children):
397 who = ret.find("who").get('id') 398 for nu in ret.findall("who/tags/tag"): 399 name = nu.text 400 score = nu.get('score') 401 uri = MediaUri("flickr://tag/%s?who=%s" % (name, who)) 402 list_of_children.append(( uri, {"name" : name, score: "score"})) 403 return list_of_children
404
405 - def _got_photosets(self, ret, list_of_children):
406 for nu in ret.findall("photosets/photoset"): 407 id = nu.get('id') 408 name = nu.find('title').text 409 server = nu.get('server') 410 photos = nu.get('photos') 411 secret = nu.get('secret') 412 primary = nu.get('primary') 413 uri = self._make_uri("flickr://photoset/%s" % id, name) 414 list_of_children.append((uri, { 'name' : name, 415 'id' : id, 416 'server' : server, 417 'photos' : photos, 418 'secret' : secret, 419 'primary' : primary} 420 ) 421 ) 422 return list_of_children
423