#!/usr/bin/env python """ gmv GDataCopier, http://gdatacopier.googlecode.com/ Copyright 2010 Eternity Technologies. Distributed under the terms and conditions of the GNU/GPL v3 GDataCopier is free software and comes with absolutely NO WARRANTY. Use of this software is completely at YOUR OWN RISK. Version 2.1.3 """ __version__ = "2.1.3" __author__ = "Devraj Mukherjee, Frederik Orellana" """ Imports the required modules """ try: from optparse import OptionParser import datetime import sys import os import re import signal import getpass import traceback except: sys.stderr.write("gmv failed to find some basic python modules, please validate the environment\n") exit(1) try: import gdata.docs import gdata.docs.service except: sys.stderr.write("gmv %s requires gdata-python-client v2.0+, fetch from Google at " % __version__) sys.stderr.write("\n") exit(1) try: import gls except: sys.stderr.write("gmv failed to find some basic python modules, please validate the environment\n") exit(1) """ Helpers """ """ Checks to see if the desired folder exists """ def folder_name_exists(gd_client, folder_name, options): if not options.destination_id == None: folder_name_query = gdata.docs.service.DocumentQuery() base_path = folder_name_query.ToUri()+"/" if not options.silent: sys.stdout.write("Fetching document feed from Google servers for %s ... " % (base_path+options.destination_id)) entry = gd_client.GetDocumentListEntry(base_path+options.destination_id) if not entry == None: return entry else: folder_name_query = gdata.docs.service.DocumentQuery(categories=['folder'], params={'showfolders': 'true'}) if not options.silent: sys.stdout.write("Fetching document list feed from Google servers for %s ... " % (folder_name_query.ToUri())) gls.add_title_match_filter(folder_name_query, folder_name) folder_feed = gd_client.Query(folder_name_query.ToUri()) if folder_feed.entry: # Destination folder must be an exact match if len(folder_feed.entry)>1: sys.stderr.write( "Only one destination folder is supported.\n") sys.exit(2) return folder_feed.entry[0] return False """ Makes a list of all documents that match the criteria and moves them to the desired folder """ def move_documents(server_string, destination_folder, options): username, document_path = server_string.split(':', 1) # Counters for the moves success_counter = 0 failure_counter = 0 if not gls.is_email(username): sys.stderr.write( "Usernames must be provided as your full Gmail address, hosted domains included.\n") sys.exit(2) # Get a handle to the document list service if not options.silent: sys.stdout.write("Logging into Google server as %s ... \n" % (username)) #gd_client = gdata.docs.service.DocsService(source="etk-gdatacopier-v2") gd_client = gdata.docs.service.DocsService() document_query = gdata.docs.service.DocumentQuery() try: # Authenticate to the document service gd_client.ClientLogin(username, options.password) if not options.source_id == None: base_path = document_query.ToUri()+"/" if not options.silent: sys.stdout.write("Fetching document list feeds from Google servers for %s, %s ... " % (username, base_path+options.source_id)) entry = gd_client.GetDocumentListEntry(base_path+options.source_id) entries = [entry] else: if options.docs_type != None: gls.add_category_filter(document_query, options.docs_type) if not options.silent: sys.stdout.write("\nlooking for %s in %s\n\n" % (options.docs_type, destination_folder)) if not options.origin_folder == None and not options.origin_folder == "all": document_query.AddNamedFolder(username, options.origin_folder) gls.add_title_match_filter(document_query, document_path) if not options.silent: sys.stdout.write("Fetching document list feeds from Google servers for %s ... " % (username)) feed = gd_client.Query(document_query.ToUri()) entries = feed.entry if not options.silent: sys.stdout.write("done.\n\n") folder_resource = folder_name_exists(gd_client, destination_folder, options) for entry in entries: if not options.silent: sys.stdout.write("%-50s -m-> " % os.path.basename(entry.title.text)[-50:]) try: if destination_folder == "/": for link in entry.link: if link.rel[-7:] == "#parent": folder_doc_feed = gd_client.GetDocumentListEntry(link.href) folder_folder_feed = gd_client.GetDocumentListFeed(folder_doc_feed.content.src) for fe in folder_folder_feed.entry: if fe.id.text.endswith("/document%3A"+options.source_id): gd_client.MoveOutOfFolder(fe) else: gd_client.MoveIntoFolder(entry, folder_resource) if not options.silent: print "MOVED" success_counter = success_counter + 1 except: if not options.silent: tb = traceback.format_exc() print tb print "FAILED." failure_counter = failure_counter + 1 except gdata.service.BadAuthentication: sys.stderr.write( "Failed, Bad Password!\n") sys.exit(2) except gdata.service.Error: sys.stderr.write("Failed!\n") sys.exit(2) except gdata.service.CaptchaRequired: sys.stdout.write("Captcha required, please login using the web interface and try again.\n") sys.exit(2) if not options.silent: sys.stdout.write("\n%i success, %i failed\n" % (success_counter, failure_counter)) def parse_user_input(): usage = "usage: %prog [options] username@domain.com:title* [destination-folder]\n" parser = OptionParser(usage) parser.add_option('-s', '--silent', action = 'store_true', dest = 'silent', default = False, help = 'decreases verbosity, supresses all messages but summaries and critical errors') parser.add_option('-p', '--password', dest = 'password', help = 'password for the user account, use with extreme caution. Could be stored in logs/history') parser.add_option('-t', '--type', dest = 'docs_type', help = 'document type') parser.add_option('-o', '--origin', dest = 'origin_folder', help = 'origin folder title') parser.add_option('-i', '--id', dest = 'source_id', help = 'source file ID') parser.add_option('-d', '--destination', dest = 'destination_id', help = 'destination folder ID') (options, args) = parser.parse_args() greet(options) if not gls.is_remote_server_string(args[0]): sys.stderr.write("you most provide a remote server address as username@gmail.com:[path]\n") exit(1) username, document_path = args[0].split(':', 1) if len(args) == 1 and gls.is_remote_server_string(args[0]) and options.destination_id == None: sys.stderr.write("you must provide a destination folder, use / for root folder\n") exit(1) if len(args) == 1 and gls.is_remote_server_string(args[0]) and (document_path == None or document_path == "" or document_path == "/") and options.source_id == None: sys.stderr.write("you must provide an object to move\n") exit(1) # If password not provided as part of the command line arguments, prompt the user # to enter the password on the command line if options.password == None: options.password = getpass.getpass() return (args, options) # Prints Greeting def greet(options): if not options.silent: sys.stdout.write("gmv %s, folder creation utility. Copyright 2010 Eternity Technologies. Extended by Frederik Orellana\n" % __version__) sys.stdout.write("Released under the GNU/GPL v3 at .\n\n") # main() is where things come together, this joins all the messages defined above # these messages must be executed in the defined order def main(): signal.signal(signal.SIGINT, gls.signal_handler) (args, options) = parse_user_input() # Check to see we have the right options or exit dest = None if len(args) == 2: dest = args[1] move_documents(args[0], dest, options) # Begin execution of the main method since we are at the bottom of the script if __name__ == "__main__": main() """ End of Python file """