From 15bd6beebdf1b77890d833d6e6f4a210b0754861 Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Fri, 27 Jan 2017 11:03:25 -0500 Subject: [PATCH] Threads and batch support for Gmail modify/delete --- src/gam.py | 69 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/src/gam.py b/src/gam.py index 5fb7f975..671e2854 100755 --- a/src/gam.py +++ b/src/gam.py @@ -4662,7 +4662,7 @@ def labelsToLabelIds(gmail, labels): parent_label = parent_label[:parent_label.rfind(u'/')] return labelIds -def doProcessMessages(users, function): +def doProcessMessagesOrThreads(users, function, unit=u'messages'): query = None doIt = False maxToProcess = 1 @@ -4688,7 +4688,7 @@ def doProcessMessages(users, function): body[u'removeLabelIds'].append(sys.argv[i+1]) i += 2 else: - print u'ERROR: %s is not a valid argument for "gam %s messages"' % (sys.argv[i], function) + print u'ERROR: %s is not a valid argument for "gam %s %s"' % (sys.argv[i], function, unit) sys.exit(2) if not query: print u'ERROR: No query specified. You must specify some query!' @@ -4698,9 +4698,10 @@ def doProcessMessages(users, function): user, gmail = buildGmailGAPIObject(user) if not gmail: continue - print u'Searching messages for %s' % user - page_message = u'Got %%%%total_items%%%% messages for user %s' % user - listResult = callGAPIpages(gmail.users().messages(), u'list', u'messages', page_message=page_message, + print u'Searching %s for %s' % (unit, user) + unitmethod = getattr(gmail.users(), unit) + page_message = u'Got %%%%total_items%%%% %s for user %s' % (unit, user) + listResult = callGAPIpages(unitmethod(), u'list', unit, page_message=page_message, userId=u'me', q=query, includeSpamTrash=True, soft_errors=True) result_count = len(listResult) if not doIt or result_count == 0: @@ -4709,33 +4710,34 @@ def doProcessMessages(users, function): elif result_count > maxToProcess: print u'WARNING: refusing to %s ANY messages for %s since max messages to process is %s and messages to be %s is %s\n' % (function, user, maxToProcess, action, result_count) continue + kwargs = {u'body': {}} + for my_key in body: + kwargs[u'body'][my_key] = labelsToLabelIds(gmail, body[my_key]) + if not kwargs[u'body']: + del(kwargs[u'body']) i = 0 - if function == u'delete': + if unit == u'messages' and function in [u'delete', u'modify']: + batchFunction = u'batch%s' % function.title() id_batches = [[]] - for del_me in listResult: - id_batches[i].append(del_me[u'id']) + for a_unit in listResult: + id_batches[i].append(a_unit[u'id']) if len(id_batches[i]) == 1000: i += 1 id_batches.append([]) - deleted_messages = 0 + processed_messages = 0 for id_batch in id_batches: - print u'deleting %s messages' % len(id_batch) - callGAPI(gmail.users().messages(), u'batchDelete', - body={u'ids': id_batch}, userId=u'me') - deleted_messages += len(id_batch) - print u'deleted %s of %s messages' % (deleted_messages, result_count) + kwargs[u'body'][u'ids'] = id_batch + print u'%s %s messages' % (function, len(id_batch)) + callGAPI(unitmethod(), batchFunction, + userId=u'me', **kwargs) + processed_messages += len(id_batch) + print u'%s %s of %s messages' % (function, processed_messages, result_count) continue - if not body: - kwargs = {} - else: - kwargs = {u'body': {}} - for my_key in body: - kwargs[u'body'][my_key] = labelsToLabelIds(gmail, body[my_key]) - for a_message in listResult: + for a_unit in listResult: i += 1 - print u' %s message %s for user %s (%s/%s)' % (function, a_message[u'id'], user, i, result_count) - callGAPI(gmail.users().messages(), function, - id=a_message[u'id'], userId=u'me', **kwargs) + print u' %s %s %s for user %s (%s/%s)' % (function, unit, a_unit[u'id'], user, i, result_count) + callGAPI(unitmethod(), function, + id=a_unit[u'id'], userId=u'me', **kwargs) def doDeleteLabel(users): label = sys.argv[5] @@ -10066,21 +10068,27 @@ def ProcessGAMCommand(args): elif command == u'modify': modifyWhat = sys.argv[4].lower() if modifyWhat in [u'message', u'messages']: - doProcessMessages(users, u'modify') + doProcessMessagesOrThreads(users, u'modify', u'messages') + elif modifyWhat in [u'thread', u'threads']: + doProcessMessagesOrThreads(users, u'modify', u'threads') else: print u'ERROR: %s is not a valid argument for "gam modify"' % modifyWhat sys.exit(2) elif command == u'trash': trashWhat = sys.argv[4].lower() if trashWhat in [u'message', u'messages']: - doProcessMessages(users, u'trash') + doProcessMessagesOrThreads(users, u'trash', u'messages') + elif trashWhat in [u'thread', u'threads']: + doProcessMessagesOrThreads(users, u'trash', u'threads') else: print u'ERROR: %s is not a valid argument for "gam trash"' % trashWhat sys.exit(2) elif command == u'untrash': untrashWhat = sys.argv[4].lower() - if untrashWhat in [u'message', u'messages']: - doProcessMessages(users, u'untrash') + if untrashWhat in [u'message', u'messages', u'messages']: + doProcessMessagesOrThreads(users, u'untrash') + elif untrashWhat in [u'thread', u'threads']: + doProcessMessagesOrThreads(u'users', u'untrash', u'threads') else: print u'ERROR: %s is not a valid argument for "gam untrash"' % untrashWhat sys.exit(2) @@ -10093,8 +10101,9 @@ def ProcessGAMCommand(args): elif delWhat == u'label': doDeleteLabel(users) elif delWhat in [u'message', u'messages']: - #doProcessMessages(users, u'delete') - runCmdForUsers(doProcessMessages, users, default_to_batch=True, function=u'delete') + runCmdForUsers(doProcessMessagesOrThreads, users, default_to_batch=True, function=u'delete', unit=u'messages') + elif delWhat in [u'thread', u'threads']: + runCmdForUsers(doProcessMessagesOrThreads, users, default_to_batch=True, function=u'delete', unit=u'threads') elif delWhat == u'photo': deletePhoto(users) elif delWhat in [u'license', u'licence']: