Announcement

Collapse
No announcement yet.

Python kwallet

Collapse
This topic is closed.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Python kwallet

    I am scripting a picasa web album sync using python and gdata. At the moment it currently requires me to either enter my login credentials every time or store them in plain text . I'd like to move over to doing this using kwallet to safely store these, as what I'm ultimately aiming to do is use my script in conjunction with the slideshow screensaver.

    I can't seem to find any examples or info on this, so can anyone help?
    Using a Novatech X16 NV Pro

    #2
    Re: Python kwallet

    This is what it currently looks like
    Code:
    '''
    Created on 27 Mar 2011
    
    @author: garethd
    
    Modded FROM: [url]http://talk.maemo.org/archive/index.php/t-27504.html[/url]
    
    FIXME: Security improvements
    find system way of SAFE storing / retrieving credentials
    mangle the username using md5 / sha / whatever when creating the top folder
    
    TODO: Script improvements
    
    Limit downloads by:
    * Only get images with highest rating
    * Start with the latest uploads and work backwards
    * Be able to pick which albums to sync
    ** devise some kind of scheme to do this!!!
    
    Limit cache dir to certain size
    * by limiting downloads (see above)
    * Use Max screen width / height as a hint for resizing
    * Deleting oldest files (off disk, not picasaweb!)
    
    TODO: DB indexing
    * Use SQLite to 
    * index what's been downloaded and help skip re-doing it
    * store comments to display on the saver
    
    TODO: Other feeds
    * People you follow, friends etc
    How to resize the featured feed?
    
    '''
    
    
    import os
    import socket
    import sys
    import urllib2
    
    # Try importing python gdata bindings from the system and then libs subdirectory
    try:
      import gdata.photos.service
      import gdata.media
      import gdata.geo
    except ImportError:
      sys.path.append('libs')
      import gdata.photos.service
      import gdata.media
      import gdata.geo
    
    
    gd_client = gdata.photos.service.PhotosService()
    
    
    # FIXME: find system way of storing / retrieving credentials and replace this <nonsense>!
    class Logins:
      username = 'my.username'
      email = username + '@gmail.com'
      password = 'XXX-WhatIWantToStoreSafely-XXX'
    
    
    def GetFeatured(imgmax=None, limit=100):
      # TODO: resizing this lot
      # Delete old ones!
      uri = '[url]https://picasaweb.google.com/data/feed/base/featured'[/url]
      album_dir = GetCacheDir('featured')
      current_dir = InitSyncDir(album_dir)
    
      photos = gd_client.GetFeed(uri)
    
      new_files = DownloadPhotos(photos, album_dir, limit=limit)
      RemoveFiles(current_dir - set(new_files), album_dir)
    
    
    def InitSyncDir(album_dir):
      """ensure the dir exists
      create if not
      return the contents list"""
      if not os.path.exists(album_dir):
        os.makedirs(album_dir)
      return set(os.listdir(album_dir))
    
    
    def FormatFileName(file_name):
      fn, ext = os.path.splitext(file_name)
      if len(fn) < 2: return ''
      replace = [' ', ';', ':', '"', "'", '!', '?', ',', '.',
            '#', '%', '$', r'/', '\\',
            'http', 'www', 'com']
      for r in replace: fn = fn.replace(r, '')
      if len(fn) > 36: fn = fn[:36]
      return fn + ext
    
    
    def DoClientLogin():
      """The parameters here will determine what gets downloaded
      if password is not given then only public albums will get downloaded
      """
      gd_client.email = Logins.email
      gd_client.password = Logins.password
      gd_client.source = 'gsaver'
      gd_client.ProgrammaticLogin()
    
    
    def sync(username, prefix, limit=None, imgmax=None, exclusions=['Fireworks', 'Blog']):
      #FIXME: replace the excusions hack with a proper album selection method
      try:
        album_list = gd_client.GetUserFeed(user=username, limit=limit)
        for album in reversed(album_list.entry):
          include = True
          for exclusion in exclusions:
            if exclusion in album.title.text: include = False
          if include:
            sync_album(album, prefix, imgmax)
      except socket.error:
        print 'interwebs is currently down, go make a panad'
    
    
    def GetAlbumDir(album, prefix):
      if not os.path.isdir(prefix):
        print "Creating directory %s" % (prefix)
        os.makedirs(prefix)
      album_dir = os.path.join(prefix, "%d" % (album.timestamp.datetime().year),
                   "%d-%02d-%02d %s" % (album.timestamp.datetime().year,
                             album.timestamp.datetime().month,
                             album.timestamp.datetime().day,
                             album.title.text))
      return album_dir.replace(' ', '_')
    
    
    def sync_album(album, prefix, imgmax):
      """
      download the album photos to the dir under prefix
      @param album: the gdata album object
      @param prefix: the root folder where the albums will exist
      @param imgmax: used to resize photos before downloading
      """
      album_dir = GetAlbumDir(album, prefix)
      InitSyncDir(album_dir)
    
      if not imgmax:
        photos = gd_client.GetFeed(album.GetPhotosUri())
      else:
        photos = gd_client.GetFeed("%s&imgmax=%s" % (album.GetPhotosUri(), imgmax))
    
      DownloadPhotos(photos, album_dir)
    
    
    def RemoveFiles(files, album_dir):
      for name in files:
        print "Deleting unused file %s" % (os.path.join(album_dir, name))
        os.remove(os.path.join(album_dir, name))
    
    
    def DownloadPhotos(photos, album_dir, limit=None):
      """download any new pictures and return the list of them
      Counter is required for the featured feed which doesn't seem to like
      it in the uri"""
      new_files = &#91;]
      i = 0
      for photo in photos.entry:
        fn = FormatFileName(photo.title.text)
        if not os.path.exists(os.path.join(album_dir, fn)):
          print "Downloading: %s -> %s" % (photo.content.src, os.path.join(album_dir, fn))
          download(photo.content.src, os.path.join(album_dir, fn))
          new_files.append(fn)
          i += 1
        if limit and i > limit: break
      return new_files
    
    
    def download(url, destination):
      out = open(destination, 'w')
      out.write(urllib2.urlopen(url).read())
    
    
    def GetCacheDir(username):
      """where to store the photos"""
      homedir = os.path.expanduser('~')
      return os.path.join(homedir, 'pwebc', username)
    
    
    if __name__ == '__main__':
      DoClientLogin()
    # users files to sync, where to load them on the device and the scaling you want used. 
      sync(Logins.username, GetCacheDir(Logins.username), imgmax='800u')
      GetFeatured(imgmax='800u')
    Using a Novatech X16 NV Pro

    Comment


      #3
      Re: Python kwallet

      Something else I'm interested in is retrieving the desktop dimensions to help with resizing correctly. Finding how to do this in PyKDE / PyQt isn't simple either.
      Using a Novatech X16 NV Pro

      Comment


        #4
        Re: Python kwallet

        OOOOooohhh

        Look what I've found:


        http://www.brighthub.com/hubfolio/ma...les/75598.aspx

        Using a Novatech X16 NV Pro

        Comment


          #5
          Re: Python kwallet

          https://github.com/garethd/pycsync

          Using a Novatech X16 NV Pro

          Comment

          Working...
          X