#!/usr/bin/env python """This module is used to parse the Google Picasa Web API feeds""" import urllib2 import datetime import stat import xml.dom.minidom as minidom import errno from fuse import Fuse class Object: title = '' summary = '' last_updated = '' def get_title (self, xml_node): title = xml_node.getElementsByTagName('title') if title and title[0].childNodes: return title[0].childNodes[0].nodeValue # raise exception here return '' def get_summary (self, xml_node): summary = xml_node.getElementsByTagName('summary') if summary and summary[0].childNodes: return summary[0].childNodes[0].nodeValue return '' def get_last_updated (self, xml_node): updated = xml_node.getElementsByTagName('updated')[0].childNodes[0].nodeValue date = updated[:10].split('-') time = updated[11:19].split(':') return datetime.datetime (*map(int, (date[0], date[1], date[2], time[0], time[1], time[2]))) def set_values (self, xml_node): self.last_updated = self.get_last_updated(xml_node) self.title = self.get_title(xml_node) self.summary = self.get_summary(xml_node) def get_value(self, xml_node, value): val = xml_node.getElementsByTagName(value) if val and val[0].childNodes: return val[0].childNodes[0].nodeValue return None class Photo(Object): def __init__ (self, xml_node): self.image = None self.set_values(xml_node) self.width = self.get_width(xml_node) self.height = self.get_height(xml_node) self.size = self.get_size(xml_node) self.url = self.get_url(xml_node) def get_width(self, xml_node): width = self.get_value(xml_node, 'width') if width: return width return 0 def get_height(self, xml_node): height = self.get_value(xml_node, 'height') if height: return height return 0 def get_size(self, xml_node): size = self.get_value(xml_node, 'size') if size: return size return 0 def get_url(self, xml_node): content = xml_node.getElementsByTagName('content')[0] return content.getAttribute('src') def get_image(self): if image == '': self.download_image() return image def download_image(self): http_handler = urllib2.HTTPHandler() req = urllib2.Request(self.url) self.image = http_handler.http_open(req).read() class Album(Object): url = 'http://picasaweb.google.com/data/feed/api/user/' def __init__ (self, xml_node, username): self.keywords = [] self.list_of_photos = [] self.set_values(xml_node) self.rights = self.get_rights(xml_node) self.numphotos = self.get_numphotos(xml_node) self.owner = username self.http_handler = urllib2.HTTPHandler() def get_rights(self, xml_node): rights = self.get_value(xml_node, 'rights') if rights: return rights return 'public' def get_numphotos(self, xml_node): num = self.get_value(xml_node, 'numphotos') if num: return num return 0 def get_photos(self): """Only add/remove files. Do not update files which have been downloaded. TO BE IMPLEMENTED""" if not self.list_of_photos: self.populate_album() print 'List of Photos: ', self.list_of_photos return [photo.title for photo in self.list_of_photos] def populate_album(self): """Populate the album with photos""" url = self.url + self.owner + '/album/' + self.title + '?kind=photo' req = urllib2.Request (url) res = self.http_handler.http_open(req).read() xml_file = minidom.parseString(res) for entry in xml_file.getElementsByTagName('entry'): self.list_of_photos.append(Photo(entry)) class Users(Object): url = 'http://picasaweb.google.com/data/feed/api/user/' def __init__(self, username=''): self.subtitle = '' self.total_results = 0 self.itemsPerPage = 0 self.http_handler = urllib2.HTTPHandler() self.albums = [] self.title = username def login(self, username, password): """do login stuff here""" # Check the page at http://code.google.com/apis/accounts/Authentication.html pass def destroy_values(self): for album in self.albums: del album self.albums = [] def get_albums(self): self.destroy_values() self.populate_user() return [album.title for album in self.albums] def find_album(self, albumname): for album in self.albums: if album.title == albumname: return album def populate_user(self): url = self.url + self.title + '?kind=album' req = urllib2.Request(url) response = self.http_handler.http_open(req).read() xml_file = minidom.parseString(response) self.set_values(xml_file) for entry in xml_file.getElementsByTagName('entry'): self.albums.append(Album(entry, self.title)) class PicasaWeb(Fuse): def __init__(self, *args, **kw): Fuse.__init__(self, *args, **kw) self.list_of_users = [] # self.get_user('prashmohan') def dir_from_list(self, list): """ Return a properly formatted list of items suitable to a directory listing. ['a', 'b', 'c'] => [('a', 0), ('b', 0), ('c', 0)] """ return [(str(x), 0) for x in list] def get_depth(self, path): if path == '/': return 0 else: return path.count ('/') def get_parts(self, path): if path == '/': return ['/'] else: return path.split('/') def get_user(self, user): self.list_of_users.append(Users(user)) def find_user(self, username): for user in self.list_of_users: if user.title == username: return user def getdir(self, path): print path depth = self.get_depth(path) if depth == 0: users = [user.title for user in self.list_of_users] print users, self.list_of_users if self.list_of_users: print self.list_of_users[0].title return self.dir_from_list(users) elif depth == 1: parts = self.get_parts(path) user = self.find_user(parts[-1]) if not user: self.get_user(parts[-1]) user = self.find_user(parts[-1]) if not user: return -errno.ENOSYS albums = user.get_albums() print albums return self.dir_from_list(albums) elif depth == 2: parts = self.get_parts(path) user = self.find_user(parts[-2]) album = user.find_album(parts[-1]) photos = album.get_photos() return self.dir_from_list(photos) def getattr(self, path): """ - st_mode (protection bits) - st_ino (inode number) - st_dev (device) - st_nlink (number of hard links) - st_uid (user ID of owner) - st_gid (group ID of owner) - st_size (size of file, in bytes) - st_atime (time of most recent access) - st_mtime (time of most recent content modification) - st_ctime (platform dependent; time of most recent metadata change on Unix, or the time of creation on Windows). """ print '*** getattr', path depth = self.get_depth(path) if depth > 2: mode = stat.S_IFREG else: mode = stat.S_IFDIR return (mode, 0, 0, 0, 0, 0, 0, 0, 0, 0) if __name__ == '__main__': fs = PicasaWeb() fs.flags = 0 fs.multithreaded = 0 fs.main()