#!/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
"""