Source

pp.core / pp / core / fs_dropbox.py

################################################################
# pp.core - Produce & Publish
# (C) 2013, ZOPYX Limited, www.zopyx.com
################################################################

import os
import cPickle
from os.path import expanduser
import time
from dropbox import client 
from dropbox import rest
from dropbox import session
from dropboxfs import DropboxFS
from splinter import Browser
import fs.wrapfs

from pp.core.logger import LOG


access_type = 'dropbox'


class DropboxFSWrapper(fs.wrapfs.WrapFS):
    """ A wrapper for a DropboxFS in order to sandbox
        all Filesystem operations below a certain
        subpath since the DropboxFS core implementation
        does not support FS sandboxing.
    """

    def __init__(self, fs, prefix='wrapper'):
        super(DropboxFSWrapper, self).__init__(fs)
        self.prefix = prefix
    
    def _encode(self, path):
        return self.prefix + '/' + path

    def _decode(self, path):
        if path.startswith('/'):
            return path.replace('/' + self.prefix + '/', '')
        else:
            return path.replace(self.prefix + '/', '')

def dropboxfs_factory(app_key, app_secret, username, password):

    home = expanduser("~")
    token_filename = os.path.join(home, '.ppcore_{}'.format(username))

    if os.path.exists(token_filename):

        with open(token_filename, 'rb') as fp:
            access_token = cPickle.loads(fp.read())

    else:

        access_token = None
        sess = session.DropboxSession(app_key, app_secret, access_type)
        request_token = sess.obtain_request_token()
        urlDropbox = sess.build_authorize_url(request_token)

        browser = Browser('phantomjs')
        LOG.debug('Starting phantomjs browser {}'.format(urlDropbox))
        browser.visit(urlDropbox)

        browser.find_by_id('email-field').first.find_by_id('login_email').first.fill(username)
        LOG.debug('Email form successfully filled')

        browser.find_by_id('login_password').first.fill(password)
        LOG.debug('Password form successfully filled')

        submitButton = browser.is_element_present_by_name('login_submit_dummy')

        if submitButton == True:
            LOG.debug('Pausing for 5 seconds to avoid clicking errors')
            time.sleep(5)
            browser.find_by_name('login_submit_dummy').first.click()
            LOG.debug('"Submit" button successfully clicked')

            # Allow connection with Dropbox
            allowButton = browser.is_element_present_by_css('.freshbutton-blue')

            if allowButton == True:
                browser.find_by_css('.freshbutton-blue').click()
                browser.quit()
                access_token = sess.obtain_access_token(request_token)
                with open(token_filename, 'wb') as fp:
                    fp.write(cPickle.dumps(access_token))

            else:
                LOG.error('The "Allow" button is not present, quitting.')
                browser.quit()

        else:
            LOG.error('The "Submit" button was not present, quitting.')
            browser.quit()

    if access_token:
        fs = DropboxFS(app_key,
                       app_secret,
                       access_type, 
                       access_token.key, 
                       access_token.secret)
        return DropboxFSWrapper(fs)
    else:
        raise RuntimeError('Unable to get hold of Dropbox access token')