From cc86d67c264f98a937b684bfccc9c4437db9c220 Mon Sep 17 00:00:00 2001 From: Ross Scroggs Date: Thu, 2 Aug 2018 17:51:47 -0700 Subject: [PATCH 1/2] Add textcolor and backgroundcolor to add label/update labelsettings (#770) * Add textcolor and backgroundcolor to add/update label pylint cleanup in new valult code * Check that both textcolor and backgroundcolor are specified --- src/GamCommands.txt | 11 +++++ src/gam.py | 114 +++++++++++++++++++++++++------------------- src/var.py | 13 +++++ 3 files changed, 90 insertions(+), 48 deletions(-) diff --git a/src/GamCommands.txt b/src/GamCommands.txt index d993d0f8..7d308544 100644 --- a/src/GamCommands.txt +++ b/src/GamCommands.txt @@ -40,6 +40,15 @@ If an item contains spaces, it should be surrounded by ". tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen ::= csv|html|txt|tsv|jpeg|jpg|png|svg|pdf|rtf|pptx|xlsx|docx|odt|ods|openoffice|ms|microsoft|micro$oft + ::= + #000000|#076239|#0b804b|#149e60|#16a766|#1a764d|#1c4587|#285bac| + #2a9c68|#3c78d8|#3dc789|#41236d|#434343|#43d692|#44b984|#4a86e8| + #653e9b|#666666|#68dfa9|#6d9eeb|#822111|#83334c|#89d3b2|#8e63ce| + #999999|#a0eac9|#a46a21|#a479e2|#a4c2f4|#aa8831|#ac2b16|#b65775| + #b694e8|#b9e4d0|#c6f3de|#c9daf8|#cc3a21|#cccccc|#cf8933|#d0bcf1| + #d5ae49|#e07798|#e4d7f5|#e66550|#eaa041|#efa093|#efefef|#f2c960| + #f3f3f3|#f691b3|#f6c5be|#f7a7c0|#fad165|#fb4c2f|#fbc8d9|#fcda83| + #fcdee8|#fce8b3|#fef1d1|#ffad47|#ffbc6b|#ffd6a2|#ffe6c7|#ffffff ::= ach|af|ag|ak|am|ar|az|be|bem|bg|bn|br|bs|ca|chr|ckb|co|crs|cs|cy|da|de|ee|el|en|en-gb|en-us|eo|es|es-419|et|eu| fa|fi|fo|fr|fr-ca|fy|ga|gaa|gd|gl|gn|gu|ha|haw|he|hi|hr|ht|hu|hy|ia|id|ig|in|is|it|iw|ja|jw| @@ -1146,7 +1155,9 @@ gam update user gam deprovision|deprov gam [create|add] label|labels [messagelistvisibility hide|show] [labellistvisibility hide|show|showifunread] + [backgroundcolor ] [textcolor ] gam update labelsettings [name ] [messagelistvisibility hide|show] [labellistvisibility hide|show|showifunread] + [backgroundcolor ] [textcolor ] gam update label|labels [search ] [replace ] [merge] gam delete|del label|labels |regex:|--ALL_LABELS-- gam show labels|label [onlyuser] [showcounts] diff --git a/src/gam.py b/src/gam.py index 520de6cc..435953ab 100755 --- a/src/gam.py +++ b/src/gam.py @@ -206,6 +206,16 @@ def getColor(color): return tg.group(0) systemErrorExit(2, u'A color must be a valid name or # and six hex characters (#012345); got {0}'.format(color)) +def getLabelColor(color): + color = color.lower().strip() + tg = COLORHEX_PATTERN.match(color) + if tg: + color = tg.group(0) + if color in LABEL_COLORS: + return color + systemErrorExit(2, u'A label color must be in the list: {0}; got {1}'.format(u'|'.join(LABEL_COLORS), color)) + systemErrorExit(2, u'A label color must be # and six hex characters (#012345); got {0}'.format(color)) + def integerLimits(minVal, maxVal, item=u'integer'): if (minVal is not None) and (maxVal is not None): return u'{0} {1}<=x<={2}'.format(item, minVal, maxVal) @@ -5390,30 +5400,53 @@ def addSmime(users): callGAPI(gmail.users().settings().sendAs().smimeInfo(), u'setDefault', userId=u'me', sendAsEmail=sendAsEmail, id=result[u'id']) print u'Added S/MIME certificate for user %s sendas %s issued by %s' % (user, sendAsEmail, result[u'issuerCn']) +def getLabelAttributes(i, myarg, body): + if myarg == u'labellistvisibility': + value = sys.argv[i+1].lower().replace(u'_', u'') + if value == u'hide': + body[u'labelListVisibility'] = u'labelHide' + elif value == u'show': + body[u'labelListVisibility'] = u'labelShow' + elif value == u'showifunread': + body[u'labelListVisibility'] = u'labelShowIfUnread' + else: + systemErrorExit(2, 'label_list_visibility must be one of hide, show, show_if_unread; got %s' % value) + i += 2 + elif myarg == u'messagelistvisibility': + value = sys.argv[i+1].lower().replace(u'_', u'') + if value not in [u'hide', u'show']: + systemErrorExit(2, 'message_list_visibility must be show or hide; got %s' % value) + body[u'messageListVisibility'] = value + i += 2 + elif myarg == u'backgroundcolor': + body.setdefault(u'color', {}) + body[u'color']['backgroundColor'] = getLabelColor(sys.argv[i+1]) + i += 2 + elif myarg == u'textcolor': + body.setdefault(u'color', {}) + body[u'color']['textColor'] = getLabelColor(sys.argv[i+1]) + i += 2 + else: + systemErrorExit(2, '%s is not a valid argument for this command.' % myarg) + return i + +def checkLabelColor(body): + if u'color' not in body: + return + if u'backgroundColor' in body[u'color']: + if u'textColor' in body[u'color']: + return + systemErrorExit(2, 'textcolor is required.' % myarg) + systemErrorExit(2, 'backgroundcolor is required.' % myarg) + def doLabel(users, i): label = sys.argv[i] i += 1 body = {u'name': label} while i < len(sys.argv): myarg = sys.argv[i].lower().replace(u'_', u'') - if myarg == u'labellistvisibility': - value = sys.argv[i+1].lower().replace(u'_', u'') - if value == u'hide': - body[u'labelListVisibility'] = u'labelHide' - elif value == u'show': - body[u'labelListVisibility'] = u'labelShow' - elif value == u'showifunread': - body[u'labelListVisibility'] = u'labelShowIfUnread' - else: - systemErrorExit(2, 'label_list_visibility must be one of hide, show, show_if_unread; got %s' % sys.argv[i+1]) - i += 2 - elif myarg == u'messagelistvisibility': - body[u'messageListVisibility'] = sys.argv[i+1].lower().replace(u'_', u'') - if body[u'messageListVisibility'] not in [u'hide', u'show']: - systemErrorExit(2, 'message_list_visibility must be show or hide; got %s' % sys.argv[i+1]) - i += 2 - else: - systemErrorExit(2, '%s is not a valid argument for this command.' % sys.argv[i]) + i = getLabelAttributes(i, myarg, body) + checkLabelColor(body) i = 0 count = len(users) for user in users: @@ -5712,24 +5745,9 @@ def updateLabels(users): if myarg == u'name': body[u'name'] = sys.argv[i+1] i += 2 - elif myarg == u'labellistvisibility': - value = sys.argv[i+1].lower().replace(u'_', u'') - if value == u'hide': - body[u'labelListVisibility'] = u'labelHide' - elif value == u'show': - body[u'labelListVisibility'] = u'labelShow' - elif value == u'showifunread': - body[u'labelListVisibility'] = u'labelShowIfUnread' - else: - systemErrorExit(2, 'label_list_visibility must be hide, show, show_if_unread; got %s' % sys.argv[i+1]) - i += 2 - elif myarg == u'messagelistvisibility': - body[u'messageListVisibility'] = sys.argv[i+1].lower().replace(u'_', u'') - if body[u'messageListVisibility'] not in [u'hide', u'show']: - systemErrorExit(2, 'message_list_visibility must be show or hide; got %s' % sys.argv[i+1]) - i += 2 else: - systemErrorExit(2, '%s is not a valid argument for "gam update labels"' % sys.argv[i]) + i = getLabelAttributes(i, myarg, body) + checkLabelColor(body) for user in users: user, gmail = buildGmailGAPIObject(user) if not gmail: @@ -7500,7 +7518,7 @@ def doGetVaultExport(): exportId = sys.argv[4] export = callGAPI(v.matters().exports(), u'get', matterId=matterId, exportId=exportId) print_json(None, export) - + def doDownloadVaultExport(): verifyFiles = True extractFiles = True @@ -7545,18 +7563,18 @@ def doDownloadVaultExport(): extract_nested_zip(filename, u'/home/jay/GAM/src/') def extract_nested_zip(zippedFile, toFolder, spacing=u' '): - """ Extract a zip file including any nested zip files - Delete the zip file(s) after extraction - """ - print u'%sextracting %s' % (spacing, zippedFile) - with zipfile.ZipFile(zippedFile, 'r') as zfile: - inner_files = zfile.infolist() - for inner_file in inner_files: - print u'%s %s' % (spacing, inner_file.filename) - zfile.extract(inner_file) - if re.search(r'\.zip$', inner_file.filename): - extract_nested_zip(inner_file.filename, toFolder, spacing=spacing+u' ') - os.remove(zippedFile) + """ Extract a zip file including any nested zip files + Delete the zip file(s) after extraction + """ + print u'%sextracting %s' % (spacing, zippedFile) + with zipfile.ZipFile(zippedFile, 'r') as zfile: + inner_files = zfile.infolist() + for inner_file in inner_files: + print u'%s %s' % (spacing, inner_file.filename) + zfile.extract(inner_file) + if re.search(r'\.zip$', inner_file.filename): + extract_nested_zip(inner_file.filename, toFolder, spacing=spacing+u' ') + os.remove(zippedFile) def doCreateVaultHold(): v = buildGAPIObject(u'vault') diff --git a/src/var.py b/src/var.py index 6b975921..68ce18b1 100644 --- a/src/var.py +++ b/src/var.py @@ -1020,6 +1020,19 @@ WEBCOLOR_MAP = { u'yellow': u'#ffff00', u'yellowgreen': u'#9acd32', } + +# Gmail label colors +LABEL_COLORS = [ + u'#000000', u'#076239', u'#0b804b', u'#149e60', u'#16a766', u'#1a764d', u'#1c4587', u'#285bac', + u'#2a9c68', u'#3c78d8', u'#3dc789', u'#41236d', u'#434343', u'#43d692', u'#44b984', u'#4a86e8', + u'#653e9b', u'#666666', u'#68dfa9', u'#6d9eeb', u'#822111', u'#83334c', u'#89d3b2', u'#8e63ce', + u'#999999', u'#a0eac9', u'#a46a21', u'#a479e2', u'#a4c2f4', u'#aa8831', u'#ac2b16', u'#b65775', + u'#b694e8', u'#b9e4d0', u'#c6f3de', u'#c9daf8', u'#cc3a21', u'#cccccc', u'#cf8933', u'#d0bcf1', + u'#d5ae49', u'#e07798', u'#e4d7f5', u'#e66550', u'#eaa041', u'#efa093', u'#efefef', u'#f2c960', + u'#f3f3f3', u'#f691b3', u'#f6c5be', u'#f7a7c0', u'#fad165', u'#fb4c2f', u'#fbc8d9', u'#fcda83', + u'#fcdee8', u'#fce8b3', u'#fef1d1', u'#ffad47', u'#ffbc6b', u'#ffd6a2', u'#ffe6c7', u'#ffffff', + ] + # Valid language codes LANGUAGE_CODES_MAP = { u'ach': u'ach', u'af': u'af', u'ag': u'ga', u'ak': u'ak', u'am': u'am', u'ar': u'ar', u'az': u'az', #Luo, Afrikaans, Irish, Akan, Amharic, Arabica, Azerbaijani From e865d81dad6227eb90c3b87e787b8a62779612f9 Mon Sep 17 00:00:00 2001 From: Ross Scroggs Date: Fri, 3 Aug 2018 02:39:00 -0700 Subject: [PATCH 2/2] Fix my mistake, keep pylint happy, set export folder (#771) * Fix my mistake, keep pylint happy, set export folder 5439/5440: copy/paste mistake 7531/7550: file and object are Python objects, pylint gets very unhappy when you redefine them 7529, 7534, 7564: Use user-defined drive folder * Cleanup download message --- src/gam.py | 23 ++++++++++++----------- src/var.py | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/gam.py b/src/gam.py index 435953ab..96ca6488 100755 --- a/src/gam.py +++ b/src/gam.py @@ -5436,8 +5436,8 @@ def checkLabelColor(body): if u'backgroundColor' in body[u'color']: if u'textColor' in body[u'color']: return - systemErrorExit(2, 'textcolor is required.' % myarg) - systemErrorExit(2, 'backgroundcolor is required.' % myarg) + systemErrorExit(2, 'textcolor is required.') + systemErrorExit(2, 'backgroundcolor is required.') def doLabel(users, i): label = sys.argv[i] @@ -7526,27 +7526,28 @@ def doDownloadVaultExport(): s = buildGAPIObject(u'storage') matterId = sys.argv[3] exportId = sys.argv[4] + targetFolder = GC_Values[GC_DRIVE_DIR] export = callGAPI(v.matters().exports(), u'get', matterId=matterId, exportId=exportId) - for file in export[u'cloudStorageSink']['files']: - bucket = file['bucketName'] - object = file['objectName'] - filename = object.replace(u'/', u'-') + for s_file in export[u'cloudStorageSink']['files']: + bucket = s_file['bucketName'] + s_object = s_file['objectName'] + filename = os.path.join(targetFolder, s_object.replace(u'/', u'-')) print u'saving to %s' % filename - request = s.objects().get_media(bucket=bucket, object=object) + request = s.objects().get_media(bucket=bucket, object=s_object) f = open(filename, 'wb') downloader = googleapiclient.http.MediaIoBaseDownload(f, request) done = False while not done: status, done = downloader.next_chunk() - sys.stdout.write(" %d%%" % int(status.progress() * 100)) + sys.stdout.write(u' Downloaded: {0:>7.2%}\r'.format(status.progress())) sys.stdout.flush() - print u'\n Download complete, flushing to disk...' + sys.stdout.write(u'\n Download complete, flushing to disk...\n') f.flush() os.fsync(f.fileno()) f.close() f = open(filename, 'rb') if verifyFiles: - expected_hash = file['md5Hash'] + expected_hash = s_file['md5Hash'] sys.stdout.write(u' Verifying file hash is %s...' % expected_hash) sys.stdout.flush() hash_md5 = hashlib.md5() @@ -7560,7 +7561,7 @@ def doDownloadVaultExport(): sys.exit(6) f.close() if extractFiles and re.search(r'\.zip$', filename): - extract_nested_zip(filename, u'/home/jay/GAM/src/') + extract_nested_zip(filename, targetFolder) def extract_nested_zip(zippedFile, toFolder, spacing=u' '): """ Extract a zip file including any nested zip files diff --git a/src/var.py b/src/var.py index 68ce18b1..bd9bc218 100644 --- a/src/var.py +++ b/src/var.py @@ -110,6 +110,7 @@ API_VER_MAPPING = { u'reports': u'reports_v1', u'reseller': u'v1', u'siteVerification': u'v1', + u'storage': u'v1', u'urlshortener': u'v1', u'vault': u'v1', }