Advertisement
Guest User

Untitled

a guest
Jan 26th, 2017
244
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.33 KB | None | 0 0
  1. """Simple command-line sample for the Google Drive API.
  2.  
  3. Command-line application that retrieves the list of files in google drive.
  4.  
  5. Usage:
  6.    $ python drive.py
  7.  
  8. You can also get help on all the command-line flags the program understands
  9. by running:
  10.  
  11.    $ python drive.py --help
  12.  
  13. To get detailed log output run:
  14.  
  15.    $ python drive.py --logging_level=DEBUG
  16. """
  17.  
  18.  
  19. import gflags, httplib2, logging, os, pprint, sys, re, time
  20. import pprint
  21.  
  22.  
  23. from apiclient.discovery import build
  24. from apiclient.discovery import build
  25. from oauth2client.file import Storage
  26. from oauth2client.client import AccessTokenRefreshError, flow_from_clientsecrets
  27. from oauth2client.tools import run_flow
  28.  
  29.  
  30. FLAGS = gflags.FLAGS
  31.  
  32. # CLIENT_SECRETS, name of a file containing the OAuth 2.0 information for this
  33. # application, including client_id and client_secret, which are found
  34. # on the API Access tab on the Google APIs
  35. # Console <http://code.google.com/apis/console>
  36. CLIENT_SECRETS = 'client_secrets.json'
  37.  
  38. # Helpful message to display in the browser if the CLIENT_SECRETS file
  39. # is missing.
  40. MISSING_CLIENT_SECRETS_MESSAGE = """
  41. WARNING: Please configure OAuth 2.0
  42.  
  43. To make this sample run you will need to populate the client_secrets.json file
  44. found at:
  45.  
  46.   %s
  47.  
  48. with information from the APIs Console <https://code.google.com/apis/console>.
  49.  
  50. """ % os.path.join(os.path.dirname(__file__), CLIENT_SECRETS)
  51.  
  52. # Set up a Flow object to be used if we need to authenticate.
  53. FLOW = flow_from_clientsecrets(CLIENT_SECRETS,
  54.     scope='https://www.googleapis.com/auth/drive',
  55.     message=MISSING_CLIENT_SECRETS_MESSAGE)
  56.  
  57.  
  58. # The gflags module makes defining command-line options easy for
  59. # applications. Run this program with the '--help' argument to see
  60. # all the flags that it understands.
  61. gflags.DEFINE_enum('logging_level', 'ERROR',
  62.                    ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
  63.                    'Set the level of logging detail.')
  64. gflags.DEFINE_string('destination', 'downloaded/', 'Destination folder location', short_name='d')
  65. gflags.DEFINE_boolean('debug', False, 'Log folder contents as being fetched' )
  66. gflags.DEFINE_string('logfile', 'drive.log', 'Location of file to write the log' )
  67. gflags.DEFINE_string('drive_id', 'root', 'ID of the folder whose contents are to be fetched' )
  68.  
  69.  
  70. def open_logfile():
  71.     if not re.match( '^/', FLAGS.logfile ):
  72.         FLAGS.logfile = FLAGS.destination + FLAGS.logfile
  73.     global LOG_FILE
  74.     LOG_FILE = open( FLAGS.logfile, 'w+' )
  75.  
  76. def log(str):
  77.     LOG_FILE.write( (str + '\n').encode('utf8') )
  78.  
  79. def ensure_dir(directory):
  80.     if not os.path.exists(directory):
  81.         log( "Creating directory: %s" % directory )
  82.         print "Creating directory: %s" % directory
  83.         os.makedirs(directory)
  84.  
  85. def is_google_doc(drive_file):
  86.     return True if re.match( '^application/vnd\.google-apps\..+', drive_file['mimeType'] ) else False
  87.  
  88. def is_file_modified(drive_file, local_file):
  89.     if os.path.exists( local_file ):
  90.         rtime = time.mktime( time.strptime( drive_file['modifiedDate'], '%Y-%m-%dT%H:%M:%S.%fZ' ) )
  91.         ltime = os.path.getmtime( local_file )
  92.         return rtime > ltime
  93.     else:
  94.         return True
  95.  
  96. def get_folder_contents( service, http, folder, base_path='./', depth=0 ):
  97.     if FLAGS.debug:
  98.         log( "\n" + '  ' * depth + "Getting contents of folder %s" % folder['title'] )
  99.         print "\n" + '  ' * depth + "Getting contents of folder %s" % folder['title']
  100.     try:
  101.         folder_contents = service.files().list( q="'%s' in parents" % folder['id'] ).execute()
  102.     except:
  103.         log( "ERROR: Couldn't get contents of folder %s. Retrying..." % folder['title'] )
  104.         print "ERROR: Couldn't get contents of folder %s. Retrying..." % folder['title']
  105.         get_folder_contents( service, http, folder, base_path, depth )
  106.         return
  107.     folder_contents = folder_contents['items']
  108.     dest_path = base_path + folder['title'].replace( '/', '_' ) + '/'
  109.  
  110.     def is_file(item):
  111.         return item['mimeType'] != 'application/vnd.google-apps.folder'
  112.  
  113.     def is_folder(item):
  114.         return item['mimeType'] == 'application/vnd.google-apps.folder'
  115.  
  116.     if FLAGS.debug:
  117.         for item in folder_contents:
  118.             if is_folder( item ):
  119.                 log( '  ' * depth + "[] " + item['title'] )
  120.                 print '  ' * depth + "[] " + item['title']
  121.             else:
  122.                 log( '  ' * depth + "-- " + item['title'] )
  123.                 print '  ' * depth + "-- " + item['title']
  124.  
  125.     ensure_dir( dest_path )
  126.  
  127.     for item in filter(is_file, folder_contents):
  128.         full_path = dest_path + item['title'].replace( '/', '_' )
  129.         if is_file_modified( item, full_path ):
  130.             is_file_new = not os.path.exists( full_path )
  131.             if download_file( service, item, dest_path ):
  132.                 if is_file_new:
  133.                     log( "Created %s" % full_path )
  134.                     print "Created %s" % full_path
  135.                 else:
  136.                     log( "Updated %s" % full_path )
  137.                     print "Updated %s" % full_path
  138.             else:
  139.                 log( "ERROR while saving %s" % full_path )
  140.                 print "ERROR while saving %s" % full_path
  141.  
  142.     for item in filter(is_folder, folder_contents):
  143.         get_folder_contents( service, http, item, dest_path, depth+1 )
  144.  
  145.  
  146. def download_file( service, drive_file, dest_path ):
  147.     """Download a file's content.
  148.  
  149.    Args:
  150.      service: Drive API service instance.
  151.      drive_file: Drive File instance.
  152.  
  153.    Returns:
  154.      File's content if successful, None otherwise.
  155.    """
  156.     file_location = dest_path + drive_file['title'].replace( '/', '_' )
  157.  
  158.     if is_google_doc(drive_file):
  159.         try:
  160.             download_url = drive_file['exportLinks']['application/pdf']
  161.         except KeyError:
  162.             download_url = None
  163.     else:
  164.         download_url = drive_file['downloadUrl']
  165.     if download_url:
  166.         try:
  167.             resp, content = service._http.request(download_url)
  168.         except httplib2.IncompleteRead:
  169.             log( 'Error while reading file %s. Retrying...' % drive_file['title'].replace( '/', '_' ) )
  170.             print 'Error while reading file %s. Retrying...' % drive_file['title'].replace( '/', '_' )
  171.             download_file( service, drive_file, dest_path )
  172.             return False
  173.         if resp.status == 200:
  174.             try:
  175.                 target = open( file_location, 'w+' )
  176.             except:
  177.                 log( "Could not open file %s for writing. Please check permissions." % file_location )
  178.                 print "Could not open file %s for writing. Please check permissions." % file_location
  179.                 return False
  180.             target.write( content )
  181.             return True
  182.         else:
  183.             log( 'An error occurred: %s' % resp )
  184.             print 'An error occurred: %s' % resp
  185.             return False
  186.     else:
  187.         # The file doesn't have any content stored on Drive.
  188.         return False
  189.  
  190.  
  191. def main(argv):
  192.     # Let the gflags module process the command-line arguments
  193.     try:
  194.         argv = FLAGS(argv)
  195.     except gflags.FlagsError, e:
  196.         print '%s\\nUsage: %s ARGS\\n%s' % (e, argv[0], FLAGS)
  197.         sys.exit(1)
  198.  
  199.     # Set the logging according to the command-line flag
  200.     logging.getLogger().setLevel(getattr(logging, FLAGS.logging_level))
  201.  
  202.     # If the Credentials don't exist or are invalid run through the native client
  203.     # flow. The Storage object will ensure that if successful the good
  204.     # Credentials will get written back to a file.
  205.     storage = Storage('drive.dat')
  206.     credentials = storage.get()
  207.  
  208.     if credentials is None or credentials.invalid:
  209.         credentials = tools.run_flow(FLOW, storage)
  210.  
  211.     # Create an httplib2.Http object to handle our HTTP requests and authorize it
  212.     # with our good Credentials.
  213.     http = httplib2.Http()
  214.     http = credentials.authorize(http)
  215.  
  216.     service = build("drive", "v2", http=http)
  217.  
  218.     open_logfile()
  219.  
  220.     try:
  221.         start_folder = service.files().get( fileId=FLAGS.drive_id ).execute()
  222.         get_folder_contents( service, http, start_folder, FLAGS.destination )
  223.     except AccessTokenRefreshError:
  224.         print ("The credentials have been revoked or expired, please re-run"
  225.                "the application to re-authorize")
  226.  
  227. if __name__ == '__main__':
  228.     main(sys.argv)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement