Dropbox – Restaurar carpeta a una fecha concreta

A veces, por errores, virus, o pura mala suerte, una carpeta de dropbox se echa a perder y necesitamos recuperarla tal y como estaba en una fecha anterior. Este Script de Python, preparado por clark800 -Kudos Clark!- es una solución magnifica que nos ahorrará mucho mucho tiempo y dolores de cabeza.

Hace poco lo tuve que usar y hacer algunos cambios para que funcionase con Python 3.5.2, así que lo comparto aquí tal y como me funcionó a mí.

Instrucciones de uso:

  1. Instala Python 3.5.2 desde la página de Python
  2. Asegúrate de añadir la ubicación de Python.exe a tu variable PATH si estás en Windows
  3. Descarga el sdk de Dropbox, puede hacerlo simplemente abriendo una ventana de comando (Windows+R > cmd) y tecleando >>
    pip install dropbox
  4. Crea una App de Dropbox en el área de desarrolladores. Guarda las claves para incluirlas luego en el script.
  5. Guarda el script como restore.py y actualizalo con tus claves
  6. Ejecuta el script desde una línea de comando >>
    python restore.py /ruta/carpeta/dentro/dropbox YYYY-MM-DD
  7. Tu ruta ha de empezar con “/”, donde “/” es la raiz de tu Dropbox
  8. La primera vez que ejecutes el script tendrás que autorizarlo con un token que obtendrás de la url que verás en pantalla

Te recomiendo que hagas pruebas con una carpeta sin valor antes de darle duro.

#!/usr/bin/env python
import sys, os, dropbox, time
from datetime import datetime

APP_KEY = ''   # INSERT APP_KEY HERE
APP_SECRET = ''     # INSERT APP_SECRET HERE
DELAY = 0.2 # delay between each file (try to stay under API rate limits)

HELP_MESSAGE = 
"""Note: You must specify the path starting with "/", where "/" is the root
of your dropbox folder. So if your dropbox directory is at "/home/user/dropbox"
and you want to restore "/home/user/dropbox/folder", the ROOTPATH is "/folder".
"""

HISTORY_WARNING = 
"""Dropbox only keeps historical file versions for 30 days (unless you have
enabled extended version history). Please specify a cutoff date within the past
30 days, or if you have extended version history, you may remove this check
from the source code."""

def authorize():
    flow = dropbox.client.DropboxOAuth2FlowNoRedirect(APP_KEY, APP_SECRET)
    authorize_url = flow.start()
    print('1. Go to: ' + authorize_url)
    print('2. Click "Allow" (you might have to log in first)')
    print('3. Copy the authorization code.')
    #try:
        #input = input
    #except NameError:
        #pass
    code = input("Enter the authorization code here: ").strip()
    access_token, user_id = flow.finish(code)
    return access_token


def login(token_save_path):
    if os.path.exists(token_save_path):
        with open(token_save_path) as token_file:
            access_token = token_file.read()
    else:
        access_token = authorize()
        with open(token_save_path, 'w') as token_file:
            token_file.write(access_token)
    return dropbox.client.DropboxClient(access_token)


def parse_date(s):
    a = s.split('+')[0].strip()
    return datetime.strptime(a, '%a, %d %b %Y %H:%M:%S')


def restore_file(client, path, cutoff_datetime, is_deleted, verbose=False):
    revisions = client.revisions(path)
    revision_dict = dict((parse_date(r['modified']), r) for r in revisions)

    # skip if current revision is the same as it was at the cutoff
    if max(revision_dict.keys()) < cutoff_datetime:
        if verbose:
            print(path + ' SKIP')
        return

    # look for the most recent revision before the cutoff
    pre_cutoff_modtimes = [d for d in revision_dict.keys()
                           if d < cutoff_datetime]
    if len(pre_cutoff_modtimes) > 0:
        modtime = max(pre_cutoff_modtimes)
        rev = revision_dict[modtime]['rev']
        if verbose:
            print(path + ' ' + str(modtime))
        client.restore(path, rev)
    else:   # there were no revisions before the cutoff, so delete
        if verbose:
            print(path + ' ' + ('SKIP' if is_deleted else 'DELETE'))
        if not is_deleted:
            client.file_delete(path)


def restore_folder(client, path, cutoff_datetime, verbose=False):
    if verbose:
        print(path)
        #print('Restoring folder: ' + path.encode('utf-8'))
    try:
        folder = client.metadata(path, list=True,
                                 include_deleted=True)
    except dropbox.rest.ErrorResponse as e:
        print(str(e))
        print(HELP_MESSAGE)
        return
    for item in folder.get('contents', []):
        if item.get('is_dir', False):
            restore_folder(client, item['path'], cutoff_datetime, verbose)
        else:
            restore_file(client, item['path'], cutoff_datetime,
                         item.get('is_deleted', False), verbose)
        time.sleep(DELAY)


def main():
    if len(sys.argv) != 3:
        usage = 'usage: {0} ROOTPATH YYYY-MM-DDn{1}'
        sys.exit(usage.format(sys.argv[0], HELP_MESSAGE))
    root_path_encoded, cutoff = sys.argv[1:]
    #root_path = root_path_encoded.decode('utf-8')
    root_path = root_path_encoded
    cutoff_datetime = datetime(*map(int, cutoff.split('-')))
    if (datetime.utcnow() - cutoff_datetime).days >= 30:
        sys.exit(HISTORY_WARNING)
    if cutoff_datetime > datetime.utcnow():
        sys.exit('Cutoff date must be in the past')
    client = login('token.dat')
    restore_folder(client, root_path, cutoff_datetime, verbose=True)


if __name__ == '__main__':
    main()

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Time limit exceeded. Please complete the captcha once again.

  • Antes de enviar tu consulta, échale un vistazo a la información básica sobre protección de datos aquí.

    Modelical.com le informa que los datos personales que usted proporcione serán tratados por MODELICAL CONSULTORIA S.L. como responsable de este sitio web.

    Finalidad de la recogida y tratamiento de los datos personales: Enviar la información que el usuario requiera a través del sitio web. - Legitimación: Consentimiento del interesado. - Destinatarios: Hosting: Gigas, hosting 100% español y 100% seguro. - Derechos: Podrá ejercer sus derechos de acceso, rectificación, limitación y supresión de los datos de unsubscribe@modelical.com así como el derecho a presentar una reclamación ante una autoridad de control.