Return to Snippet

Revision: 40288
at January 28, 2011 23:08 by doqtu84


Initial Code
import flickrapi
import sqlite3
import gdata.photos.service
import gdata.media
import gdata.geo
import urllib
import re
import os
import time
import urllib2
import socket
import sys

#===============================================================================
# o = MyFLickrPicasa()
# o.flickr_init()
# o.do_loopbackup()
# o.flickrdb_release()
#===============================================================================

class MyFLickrPicasa:
    """Flickr"""
    flickr_api_key = '------------------------------------'
    flickr_api_secret = '------------------------------------'
    flickr_token = None
    flickr_frob = None
    flickr = None
    
    """Sqlite"""
    conn = None
    c = None
    
    """Picasa Web API"""
    picasa_email = '[email protected]'
    picasa_pass  = '------------------------------------'
    gd_client = None
    
    def __init__(self):
        # Kiem tra internet connection den google
        if self.picasa_checkinternetconn() <> True:
            sys.exit("Internet connection failed!")
        self.flickrdb_init()
        self.picasa_auth()
    
    def flickr_init(self):
        self.flickr = flickrapi.FlickrAPI(self.flickr_api_key, self.flickr_api_secret)
        (self.flickr_token, self.flickr_frob) = self.flickr.get_token_part_one(perms='write')
        if not self.flickr_token: raw_input("Press ENTER after you authorized this program")
        self.flickr.get_token_part_two((self.flickr_token, self.flickr_frob))
        
    def flickr_walkall(self):
        print 'fetch all your photos...'
        for photo in self.flickr.walk(user_id='me', content_type=7, media='photos'):
            x = photo.get('id')
            self.flickrdb_add(x)
            print x
        
    def flickrdb_init(self):
        self.conn = sqlite3.connect('flickr.db')
        self.conn.isolation_level = None
        self.c = self.conn.cursor()
        # Create table
        self.c.execute('''CREATE TABLE IF NOT EXISTS photos (photoid text)''')
        
    def flickrdb_add(self, photoid):
        self.conn.execute("insert into photos(photoid) values ('%s')" % photoid)
        
    def flickrdb_release(self):
        self.conn.close()
        
    def picasa_auth(self):
        self.gd_client = gdata.photos.service.PhotosService()
        self.gd_client.email = self.picasa_email
        self.gd_client.password = self.picasa_pass
        self.gd_client.source = 'exampleCo-exampleApp-1'
        self.gd_client.ProgrammaticLogin()
        
    def picasa_test(self):
        albums = self.gd_client.GetUserFeed()
        for album in albums.entry:
            print 'Album: %s (%s)' % (album.title.text, album.numphotos.text)
            
    def picasa_checkinternetconn(self):
        try:
            s = socket.socket()
            s.connect(('www.google.com', 80))
            s.shutdown(socket.SHUT_RDWR)
            s.close()
            return True
        except:
            return False
    
    def picasa_privatizealbum(self, album):
        album.access.text = 'private'
        updated_album = self.gd_client.Put(album, album.GetEditLink().href, converter=gdata.photos.AlbumEntryFromString)
        return updated_album
    
    def flickrdb_count(self):
        self.c.execute("SELECT count(*) FROM photos")
        photoid = self.c.fetchone()
        photoid = str(photoid[0])
        print "Hien co: " + photoid + " photos"
        
    def do_downloadfile(self, remotef, localf):
        try:
            os.remove(localf)
        except:
            print ""       
        
        try:
            u = urllib2.urlopen(remotef)
            localFile = open(localf, 'wb')
            localFile.write(u.read())
            localFile.close()
            remote_bytes = int(u.info().getheader('Content-Length', None))
            local_bytes = int(os.path.getsize(localf))
            
            if remote_bytes <> local_bytes:
                return False
            else:
                return local_bytes
            
        except:
            return False
        
        return False
    
    def do_getalbum(self, photoid):
        defaultalbum_maxno = 0
        defaultalbum_object = {}
        # Thu lay ten album tren Flickr
        try:
            sets = self.flickr.photos_getAllContexts(photo_id=photoid)
            sets = sets.find('set').attrib['title']
            sets = re.sub(r"(?i)[^\x2D\sa-zA-Z0-9]", "a", sets)
        except:
            # Khong co set, thu gan ten album mac dinh cua Picasa
            sets = None #'Default Album'
        
        albums = self.gd_client.GetUserFeed()
        for album in albums.entry:
            # album.title.text,album.numphotos.text, album.gphoto_id.text
            if album.title.text == sets and int(album.numphotosremaining) > 3:
                return album
            
            match = re.search(r"Default Album (\d{1,5})", album.title.text, re.IGNORECASE)
            if match:
                x = int(match.group(1))
                if x > defaultalbum_maxno:
                    defaultalbum_maxno = x
                if int(album.numphotosremaining) > 3:
                    defaultalbum_object[x] = album                    
           
        # Khong co album nao duoc tim thay, tao moi 1 album
        if sets <> None:
            album = self.gd_client.InsertAlbum(title=sets, summary='This is an album')
            return album
        else:
            if len(defaultalbum_object) > 0:
                # Lay bat ky album nao va add vao
                for k, v in defaultalbum_object.iteritems():
                    album = v
                    return album
            else:
                album = "Default Album " + str(defaultalbum_maxno + 1)
                album = self.gd_client.InsertAlbum(title=album, summary='This is an album')
                return album

    def picasa_checkquota(self):
        # Kiem tra quota upload cua user
        x = self.gd_client.GetUserFeed()
        x = float(x.quotacurrent.text) / float(x.quotalimit.text)
        if x > 0.8:
            # Da het quota
            return False
        else:
            return True

    def do_loopbackup(self):
        m_time = 0
        while True:
            now_time = time.time()
            if m_time == 0:
                m_time = time.time()
            if (now_time - m_time) > (5*60*60):
                m_time = 0
                ok = raw_input('Nhan y de tiep tuc, nhan n de thoat chuong trinh:')
                if ok in ('n', 'no', 'nop', 'nope'):
                    return False
            
            self.do_flickr2picasa()

    
    def do_flickr2picasa(self):
        # Kiem tra internet connection den google
        if self.picasa_checkinternetconn() <> True:
            print "Internet connection failed!"
            time.sleep(30) # Dung 30s truoc khi thu lai
            return None
        
        # Kiem tra quota
        if self.picasa_checkquota() <> True:
            print "Out of quota! Please upgrade!"
            return None
            
        # Lay mot photoid bat ky trong FlickrDB
        try:
            self.c.execute("select photoid from photos limit 1")
            photoid = self.c.fetchone()
            photoid = photoid[0]
        except:
            print "Khong co bat ky ID nao trong DB"
            return None
        # Ket noi voi Flickr de nhan thong tin ve Photo
        #photoid = '3278705476'
        print "---------------------------------------------------------"
        self.flickrdb_count()
        print "Backing up photo #" + str(photoid)
        photo = self.flickr.photos_getInfo(photo_id=photoid)
        if photo.attrib['stat'] <> 'ok':
            return None
        # Chuan bi cac bien de post len Picasa
        photo_url = "http://farm"+photo.find('photo').attrib['farm']+".static.flickr.com/"+photo.find('photo').attrib['server']+"/"+photo.find('photo').attrib['id']+"_"+photo.find('photo').attrib['originalsecret']+"_o."+photo.find('photo').attrib['originalformat']+""
        photo_local = photo.find('photo').attrib['id'] +"."+ photo.find('photo').attrib['originalformat']
        photo_title = str(photoid)
        photo_summary = "Photo: " + unicode(photo.find('photo').find('title').text) + " - " + unicode(photo.find('photo').find('description').text) + " . FlickrID:" + str(photoid)
        photo_summary = photo_summary[:250]
        
        #unicode
        photo_title = photo_title.decode("utf-8", "replace")
        #photo_summary = photo_summary.decode("utf-8", "replace")
        # Them tag, geotag vao photo
        # <dates posted="1234610523" taken="2009-02-14 03:37:11" takengranularity="0" lastupdate="1278990813" />
        try:
            e_taglist = []
            for e in photo.find('photo').find('tags').findall('tag'):
                if int(e.attrib['machine_tag']) == 0:
                    e_taglist.append(re.sub(r"(?i)[^\x2D\sa-zA-Z0-9]", "a", e.text))
            e_tag = ",".join(e_taglist)
            print "Tags: " + e_tag
        except:
            e_tag = ""
                
        try:
            e_geotag = photo.find('photo').find('location')
            e_geotag = '%s %s' % (e_geotag.attrib['latitude'], e_geotag.attrib['longitude'])
        except:
            e_geotag = '%s %s' % ('16.04389', '108.19944')        
        
        # Download anh goc ve may tinh

                
        try:
            #x = None
            #urllib.urlretrieve (photo_url, photo_local)
            photo_bytes = self.do_downloadfile(photo_url, photo_local)
            if photo_bytes < 1 or photo_bytes is False:
                raise Exception()
        except:
            print "Khong the download duoc file"
            return None
        
        # File da download,  connect den Picasa
        # Tim va xu ly Album
        photo_picasa_album = self.picasa_privatizealbum(self.do_getalbum(photoid))
        photo_picasa_album_url = '/data/feed/api/user/%s/albumid/%s' % ('default', photo_picasa_album.gphoto_id.text)
        
        
        try:
            new_entry = self.gd_client.InsertPhotoSimple(photo_picasa_album_url, photo_title, photo_summary, photo_local)
            # kiem tra tinh xac thuc cua anh duoc upload
            uploaded_bytes = int(new_entry.size.text)
            if uploaded_bytes <> photo_bytes:
                # Xoa anh da upload
                self.gd_client.Delete(new_entry)
                raise Exception()
        except:
            print "Khong the upload duoc file"
            print sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
            return None
        
        try:
            new_entry.media.keywords = gdata.media.Keywords()
            new_entry.media.keywords.text = e_tag
        except:
            print sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

        new_entry.geo = gdata.geo.Where()
        new_entry.geo.Point = gdata.geo.Point()
        new_entry.geo.Point.pos = gdata.geo.Pos(text=e_geotag)
        updated_entry = self.gd_client.UpdatePhotoMetadata(new_entry)        
        
        # Da upload thanh cong, xoa file local
        try:
            os.remove(photo_local)
        except:
            print ""
            
        # Sau khi da xoa file, xoa entry trong database Sqlite
        self.c.execute("delete from photos where photoid='"+photoid+"'")
        print "Successfully backed up #" + str(photoid)
        return True
        
        #print photo_picasa_album.title.text
        #print photo_picasa_album.gphoto_id.text        
        #print photo_url
        #print e_geotag
        #print photo_picasa_album_url

Initial URL


Initial Description
A command line tool to transfer all photos from Flickr to Picasa

Initial Title
Flickr-to-Picasa Migration tool

Initial Tags


Initial Language
Python