mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-09 14:13:35 +00:00
Clean up, small fixes (#299)
* Clean up, small fixes * Update as per Jay's suggestions * Add Jays'changes # Conflicts: # src/gam.py
This commit is contained in:
233
src/gam.py
233
src/gam.py
@ -20,21 +20,37 @@ u"""GAM is a command line tool which allows Administrators to control their Goog
|
|||||||
|
|
||||||
With GAM you can programatically create users, turn on/off services for users like POP and Forwarding and much more.
|
With GAM you can programatically create users, turn on/off services for users like POP and Forwarding and much more.
|
||||||
For more information, see http://git.io/gam
|
For more information, see http://git.io/gam
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = u'Jay Lee <jay0lee@gmail.com>'
|
__author__ = u'Jay Lee <jay0lee@gmail.com>'
|
||||||
__version__ = u'3.72'
|
__version__ = u'3.72'
|
||||||
__license__ = u'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
__license__ = u'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||||
|
|
||||||
import sys, os, time, datetime, random, socket, csv, platform, re, base64, string, codecs, StringIO, subprocess, collections, mimetypes
|
import sys
|
||||||
|
import os
|
||||||
|
import string
|
||||||
|
import time
|
||||||
|
import base64
|
||||||
|
import codecs
|
||||||
|
import collections
|
||||||
|
import csv
|
||||||
|
import datetime
|
||||||
|
from htmlentitydefs import name2codepoint
|
||||||
|
from HTMLParser import HTMLParser
|
||||||
import json
|
import json
|
||||||
import httplib2
|
import mimetypes
|
||||||
|
import platform
|
||||||
|
import random
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
|
import StringIO
|
||||||
|
import subprocess
|
||||||
|
|
||||||
import googleapiclient
|
import googleapiclient
|
||||||
import googleapiclient.discovery
|
import googleapiclient.discovery
|
||||||
import googleapiclient.errors
|
import googleapiclient.errors
|
||||||
import googleapiclient.http
|
import googleapiclient.http
|
||||||
|
import httplib2
|
||||||
import oauth2client.client
|
import oauth2client.client
|
||||||
import oauth2client.service_account
|
import oauth2client.service_account
|
||||||
import oauth2client.file
|
import oauth2client.file
|
||||||
@ -71,6 +87,7 @@ GAM_INFO = u'GAM {0} - {1} / {2} / Python {3}.{4}.{5} {6} / {7} {8} /'.format(__
|
|||||||
sys.version_info[0], sys.version_info[1], sys.version_info[2],
|
sys.version_info[0], sys.version_info[1], sys.version_info[2],
|
||||||
sys.version_info[3],
|
sys.version_info[3],
|
||||||
platform.platform(), platform.machine())
|
platform.platform(), platform.machine())
|
||||||
|
GAM_RELEASES = u'https://github.com/jay0lee/GAM/releases'
|
||||||
GAM_WIKI = u'https://github.com/jay0lee/GAM/wiki'
|
GAM_WIKI = u'https://github.com/jay0lee/GAM/wiki'
|
||||||
GAM_WIKI_CREATE_CLIENT_SECRETS = GAM_WIKI+u'/CreatingClientSecretsFile'
|
GAM_WIKI_CREATE_CLIENT_SECRETS = GAM_WIKI+u'/CreatingClientSecretsFile'
|
||||||
GAM_ALL_RELEASES = u'https://api.github.com/repos/jay0lee/GAM/releases'
|
GAM_ALL_RELEASES = u'https://api.github.com/repos/jay0lee/GAM/releases'
|
||||||
@ -355,9 +372,6 @@ def convertUTF8(data):
|
|||||||
return type(data)(map(convertUTF8, data))
|
return type(data)(map(convertUTF8, data))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
from HTMLParser import HTMLParser
|
|
||||||
from htmlentitydefs import name2codepoint
|
|
||||||
|
|
||||||
class _DeHTMLParser(HTMLParser):
|
class _DeHTMLParser(HTMLParser):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
HTMLParser.__init__(self)
|
HTMLParser.__init__(self)
|
||||||
@ -749,13 +763,15 @@ def SetGlobalVariables():
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def doGAMCheckForUpdates(forceCheck=False):
|
def doGAMCheckForUpdates(forceCheck=False):
|
||||||
import urllib2, calendar
|
import urllib2
|
||||||
|
import calendar
|
||||||
|
|
||||||
current_version = __version__
|
current_version = __version__
|
||||||
now_time = calendar.timegm(time.gmtime())
|
now_time = calendar.timegm(time.gmtime())
|
||||||
if forceCheck:
|
if forceCheck:
|
||||||
check_url = GAM_ALL_RELEASES # includes pre-releases
|
check_url = GAM_ALL_RELEASES # includes pre-releases
|
||||||
else:
|
else:
|
||||||
last_check_time_str = readFile(GM_Globals[GM_LAST_UPDATE_CHECK_TXT], continueOnError=True, displayError=forceCheck)
|
last_check_time_str = readFile(GM_Globals[GM_LAST_UPDATE_CHECK_TXT], continueOnError=True, displayError=False)
|
||||||
last_check_time = int(last_check_time_str) if last_check_time_str and last_check_time_str.isdigit() else 0
|
last_check_time = int(last_check_time_str) if last_check_time_str and last_check_time_str.isdigit() else 0
|
||||||
if last_check_time > now_time-604800:
|
if last_check_time > now_time-604800:
|
||||||
return
|
return
|
||||||
@ -768,8 +784,8 @@ def doGAMCheckForUpdates(forceCheck=False):
|
|||||||
release_data = json.loads(c.read())
|
release_data = json.loads(c.read())
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return
|
return
|
||||||
if type(release_data) is list:
|
if isinstance(release_data, list):
|
||||||
release_data = release_data[0] # only care about latest release
|
release_data = release_data[0] # only care about latest release
|
||||||
latest_version = release_data[u'tag_name']
|
latest_version = release_data[u'tag_name']
|
||||||
if latest_version[0].lower() == u'v':
|
if latest_version[0].lower() == u'v':
|
||||||
latest_version = latest_version[1:]
|
latest_version = latest_version[1:]
|
||||||
@ -898,7 +914,7 @@ def checkGAPIError(e, soft_errors=False, silent_errors=False, retryOnHttpError=F
|
|||||||
elif u'Mail service not enabled' in message:
|
elif u'Mail service not enabled' in message:
|
||||||
reason = GAPI_SERVICE_NOT_AVAILABLE
|
reason = GAPI_SERVICE_NOT_AVAILABLE
|
||||||
except KeyError:
|
except KeyError:
|
||||||
reason = http_status
|
reason = u'{0}'.format(http_status)
|
||||||
return (http_status, reason, message)
|
return (http_status, reason, message)
|
||||||
|
|
||||||
class GAPI_serviceNotAvailable(Exception):
|
class GAPI_serviceNotAvailable(Exception):
|
||||||
@ -907,9 +923,9 @@ class GAPI_serviceNotAvailable(Exception):
|
|||||||
def callGAPI(service, function,
|
def callGAPI(service, function,
|
||||||
silent_errors=False, soft_errors=False, throw_reasons=None, retry_reasons=None,
|
silent_errors=False, soft_errors=False, throw_reasons=None, retry_reasons=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
if throw_reasons == None:
|
if throw_reasons is None:
|
||||||
throw_reasons = []
|
throw_reasons = []
|
||||||
if retry_reasons == None:
|
if retry_reasons is None:
|
||||||
retry_reasons = []
|
retry_reasons = []
|
||||||
method = getattr(service, function)
|
method = getattr(service, function)
|
||||||
retries = 10
|
retries = 10
|
||||||
@ -947,7 +963,7 @@ def callGAPIpages(service, function, items,
|
|||||||
page_message=None, message_attribute=None,
|
page_message=None, message_attribute=None,
|
||||||
throw_reasons=None,
|
throw_reasons=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
if throw_reasons == None:
|
if throw_reasons is None:
|
||||||
throw_reasons = []
|
throw_reasons = []
|
||||||
pageToken = None
|
pageToken = None
|
||||||
all_pages = list()
|
all_pages = list()
|
||||||
@ -989,9 +1005,9 @@ def callGAPIpages(service, function, items,
|
|||||||
def callGAPIitems(service, function, items,
|
def callGAPIitems(service, function, items,
|
||||||
throw_reasons=None, retry_reasons=None,
|
throw_reasons=None, retry_reasons=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
if throw_reasons == None:
|
if throw_reasons is None:
|
||||||
throw_reasons = []
|
throw_reasons = []
|
||||||
if retry_reasons == None:
|
if retry_reasons is None:
|
||||||
retry_reasons = []
|
retry_reasons = []
|
||||||
results = callGAPI(service, function,
|
results = callGAPI(service, function,
|
||||||
throw_reasons=throw_reasons, retry_reasons=retry_reasons,
|
throw_reasons=throw_reasons, retry_reasons=retry_reasons,
|
||||||
@ -1221,7 +1237,7 @@ def showReport():
|
|||||||
else:
|
else:
|
||||||
print u'ERROR: %s is not a valid argument to "gam report"' % sys.argv[i]
|
print u'ERROR: %s is not a valid argument to "gam report"' % sys.argv[i]
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
if try_date == None:
|
if try_date is None:
|
||||||
try_date = str(datetime.date.today())
|
try_date = str(datetime.date.today())
|
||||||
if report in [u'users', u'user']:
|
if report in [u'users', u'user']:
|
||||||
while True:
|
while True:
|
||||||
@ -1372,6 +1388,7 @@ def gen_sha512_hash(password):
|
|||||||
return sha512_crypt.encrypt(password, rounds=5000)
|
return sha512_crypt.encrypt(password, rounds=5000)
|
||||||
|
|
||||||
def printShowDelegates(users, csvFormat):
|
def printShowDelegates(users, csvFormat):
|
||||||
|
emailsettings = buildGAPIObject(u'email-settings')
|
||||||
if csvFormat:
|
if csvFormat:
|
||||||
todrive = False
|
todrive = False
|
||||||
csvRows = []
|
csvRows = []
|
||||||
@ -1390,7 +1407,6 @@ def printShowDelegates(users, csvFormat):
|
|||||||
else:
|
else:
|
||||||
print u'ERROR: %s is not a valid argument for "gam <users> show delegates"' % sys.argv[i]
|
print u'ERROR: %s is not a valid argument for "gam <users> show delegates"' % sys.argv[i]
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
emailsettings = buildGAPIObject(u'email-settings')
|
|
||||||
for user in users:
|
for user in users:
|
||||||
if user.find(u'@') == -1:
|
if user.find(u'@') == -1:
|
||||||
userName = user
|
userName = user
|
||||||
@ -2103,7 +2119,7 @@ def doPrintShowGuardians(csvFormat):
|
|||||||
items = u'guardianInvitations'
|
items = u'guardianInvitations'
|
||||||
itemName = 'Guardian Invitations'
|
itemName = 'Guardian Invitations'
|
||||||
titles = [u'studentEmail', u'studentId', u'invitedEmailAddress', u'invitationId']
|
titles = [u'studentEmail', u'studentId', u'invitedEmailAddress', u'invitationId']
|
||||||
if states == None:
|
if states is None:
|
||||||
states = [u'COMPLETE', u'PENDING', u'GUARDIAN_INVITATION_STATE_UNSPECIFIED']
|
states = [u'COMPLETE', u'PENDING', u'GUARDIAN_INVITATION_STATE_UNSPECIFIED']
|
||||||
i += 1
|
i += 1
|
||||||
elif myarg == u'states':
|
elif myarg == u'states':
|
||||||
@ -2172,7 +2188,7 @@ def doDeleteGuardian():
|
|||||||
|
|
||||||
def doCreateCourse():
|
def doCreateCourse():
|
||||||
croom = buildGAPIObject(u'classroom')
|
croom = buildGAPIObject(u'classroom')
|
||||||
body = {}
|
body = {u'ownerId': u'me', u'name': u'Unknown Course'}
|
||||||
i = 3
|
i = 3
|
||||||
while i < len(sys.argv):
|
while i < len(sys.argv):
|
||||||
if sys.argv[i].lower() == u'name':
|
if sys.argv[i].lower() == u'name':
|
||||||
@ -2205,10 +2221,6 @@ def doCreateCourse():
|
|||||||
else:
|
else:
|
||||||
print u'ERROR: %s is not a valid argument for "gam create course".' % sys.argv[i]
|
print u'ERROR: %s is not a valid argument for "gam create course".' % sys.argv[i]
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
if not u'ownerId' in body:
|
|
||||||
body[u'ownerId'] = u'me'
|
|
||||||
if not u'name' in body:
|
|
||||||
body[u'name'] = u'Unknown Course'
|
|
||||||
result = callGAPI(croom.courses(), u'create', body=body)
|
result = callGAPI(croom.courses(), u'create', body=body)
|
||||||
print u'Created course %s' % result[u'id']
|
print u'Created course %s' % result[u'id']
|
||||||
|
|
||||||
@ -2761,7 +2773,7 @@ def doPrinterAddACL():
|
|||||||
result = callGAPI(cp.printers(), u'share', printerid=printer, role=role, scope=scope, public=public, skip_notification=skip_notification)
|
result = callGAPI(cp.printers(), u'share', printerid=printer, role=role, scope=scope, public=public, skip_notification=skip_notification)
|
||||||
checkCloudPrintResult(result)
|
checkCloudPrintResult(result)
|
||||||
who = scope
|
who = scope
|
||||||
if who == None:
|
if who is None:
|
||||||
who = u'public'
|
who = u'public'
|
||||||
role = u'user'
|
role = u'user'
|
||||||
print u'Added %s %s' % (role, who)
|
print u'Added %s %s' % (role, who)
|
||||||
@ -2779,7 +2791,7 @@ def doPrinterDelACL():
|
|||||||
result = callGAPI(cp.printers(), u'unshare', printerid=printer, scope=scope, public=public)
|
result = callGAPI(cp.printers(), u'unshare', printerid=printer, scope=scope, public=public)
|
||||||
checkCloudPrintResult(result)
|
checkCloudPrintResult(result)
|
||||||
who = scope
|
who = scope
|
||||||
if who == None:
|
if who is None:
|
||||||
who = u'public'
|
who = u'public'
|
||||||
print u'Removed %s' % who
|
print u'Removed %s' % who
|
||||||
|
|
||||||
@ -3071,7 +3083,7 @@ def doPrintJobSubmit():
|
|||||||
filepath = content
|
filepath = content
|
||||||
content = os.path.basename(content)
|
content = os.path.basename(content)
|
||||||
mimetype = mimetypes.guess_type(filepath)[0]
|
mimetype = mimetypes.guess_type(filepath)[0]
|
||||||
if mimetype == None:
|
if mimetype is None:
|
||||||
mimetype = u'application/octet-stream'
|
mimetype = u'application/octet-stream'
|
||||||
filecontent = readFile(filepath)
|
filecontent = readFile(filepath)
|
||||||
form_files[u'content'] = {u'filename': content, u'content': filecontent, u'mimetype': mimetype}
|
form_files[u'content'] = {u'filename': content, u'content': filecontent, u'mimetype': mimetype}
|
||||||
@ -3129,16 +3141,16 @@ def doCalendarShowACL():
|
|||||||
print u'Calendar: {0}, ACL: {1}{2}'.format(show_cal, formatACLRule(rule), currentCount(i, count))
|
print u'Calendar: {0}, ACL: {1}{2}'.format(show_cal, formatACLRule(rule), currentCount(i, count))
|
||||||
|
|
||||||
def doCalendarAddACL(calendarId=None, act_as=None, role=None, scope=None, entity=None):
|
def doCalendarAddACL(calendarId=None, act_as=None, role=None, scope=None, entity=None):
|
||||||
if act_as != None:
|
if act_as is not None:
|
||||||
act_as, cal = buildCalendarGAPIObject(act_as)
|
act_as, cal = buildCalendarGAPIObject(act_as)
|
||||||
else:
|
else:
|
||||||
cal = buildGAPIObject(u'calendar')
|
cal = buildGAPIObject(u'calendar')
|
||||||
body = {u'scope': {}}
|
body = {u'scope': {}}
|
||||||
if calendarId == None:
|
if calendarId is None:
|
||||||
calendarId = sys.argv[2]
|
calendarId = sys.argv[2]
|
||||||
if calendarId.find(u'@') == -1:
|
if calendarId.find(u'@') == -1:
|
||||||
calendarId = u'%s@%s' % (calendarId, GC_Values[GC_DOMAIN])
|
calendarId = u'%s@%s' % (calendarId, GC_Values[GC_DOMAIN])
|
||||||
if role != None:
|
if role is not None:
|
||||||
body[u'role'] = role
|
body[u'role'] = role
|
||||||
else:
|
else:
|
||||||
body[u'role'] = sys.argv[4].lower()
|
body[u'role'] = sys.argv[4].lower()
|
||||||
@ -3151,7 +3163,7 @@ def doCalendarAddACL(calendarId=None, act_as=None, role=None, scope=None, entity
|
|||||||
body[u'role'] = u'reader'
|
body[u'role'] = u'reader'
|
||||||
elif body[u'role'] == u'editor':
|
elif body[u'role'] == u'editor':
|
||||||
body[u'role'] = u'writer'
|
body[u'role'] = u'writer'
|
||||||
if scope != None:
|
if scope is not None:
|
||||||
body[u'scope'][u'type'] = scope
|
body[u'scope'][u'type'] = scope
|
||||||
else:
|
else:
|
||||||
body[u'scope'][u'type'] = sys.argv[5].lower()
|
body[u'scope'][u'type'] = sys.argv[5].lower()
|
||||||
@ -3160,7 +3172,7 @@ def doCalendarAddACL(calendarId=None, act_as=None, role=None, scope=None, entity
|
|||||||
body[u'scope'][u'type'] = u'user'
|
body[u'scope'][u'type'] = u'user'
|
||||||
i = 5
|
i = 5
|
||||||
try:
|
try:
|
||||||
if entity != None and body[u'scope'][u'type'] != u'default':
|
if entity is not None and body[u'scope'][u'type'] != u'default':
|
||||||
body[u'scope'][u'value'] = entity
|
body[u'scope'][u'value'] = entity
|
||||||
else:
|
else:
|
||||||
body[u'scope'][u'value'] = sys.argv[i].lower()
|
body[u'scope'][u'value'] = sys.argv[i].lower()
|
||||||
@ -3381,7 +3393,7 @@ def doPhoto(users):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
image_data = readFile(filename, continueOnError=True, displayError=True)
|
image_data = readFile(filename, continueOnError=True, displayError=True)
|
||||||
if image_data == None:
|
if image_data is None:
|
||||||
continue
|
continue
|
||||||
image_data = base64.urlsafe_b64encode(image_data)
|
image_data = base64.urlsafe_b64encode(image_data)
|
||||||
body = {u'photoData': image_data}
|
body = {u'photoData': image_data}
|
||||||
@ -3555,7 +3567,7 @@ def printDriveSettings(users):
|
|||||||
continue
|
continue
|
||||||
sys.stderr.write(u'Getting Drive settings for %s (%s/%s)\n' % (user, i, count))
|
sys.stderr.write(u'Getting Drive settings for %s (%s/%s)\n' % (user, i, count))
|
||||||
feed = callGAPI(drive.about(), u'get', soft_errors=True)
|
feed = callGAPI(drive.about(), u'get', soft_errors=True)
|
||||||
if feed == None:
|
if feed is None:
|
||||||
continue
|
continue
|
||||||
row = {u'email': user}
|
row = {u'email': user}
|
||||||
for setting in feed:
|
for setting in feed:
|
||||||
@ -4065,7 +4077,7 @@ def getDriveFileAttribute(i, body, parameters, myarg, update=False):
|
|||||||
parameters[DFA_LOCALFILENAME] = os.path.basename(parameters[DFA_LOCALFILEPATH])
|
parameters[DFA_LOCALFILENAME] = os.path.basename(parameters[DFA_LOCALFILEPATH])
|
||||||
body.setdefault(u'title', parameters[DFA_LOCALFILENAME])
|
body.setdefault(u'title', parameters[DFA_LOCALFILENAME])
|
||||||
body[u'mimeType'] = mimetypes.guess_type(parameters[DFA_LOCALFILEPATH])[0]
|
body[u'mimeType'] = mimetypes.guess_type(parameters[DFA_LOCALFILEPATH])[0]
|
||||||
if body[u'mimeType'] == None:
|
if body[u'mimeType'] is None:
|
||||||
body[u'mimeType'] = u'application/octet-stream'
|
body[u'mimeType'] = u'application/octet-stream'
|
||||||
parameters[DFA_LOCALMIMETYPE] = body[u'mimeType']
|
parameters[DFA_LOCALMIMETYPE] = body[u'mimeType']
|
||||||
i += 2
|
i += 2
|
||||||
@ -4123,7 +4135,7 @@ def getDriveFileAttribute(i, body, parameters, myarg, update=False):
|
|||||||
return i
|
return i
|
||||||
|
|
||||||
def doUpdateDriveFile(users):
|
def doUpdateDriveFile(users):
|
||||||
fileIdSelection = {u'fileIds': None, u'query': None}
|
fileIdSelection = {u'fileIds': [], u'query': None}
|
||||||
media_body = None
|
media_body = None
|
||||||
operation = u'update'
|
operation = u'update'
|
||||||
body, parameters = initializeDriveFileAttributes()
|
body, parameters = initializeDriveFileAttributes()
|
||||||
@ -4246,7 +4258,7 @@ DOCUMENT_FORMATS_MAP = {
|
|||||||
|
|
||||||
def downloadDriveFile(users):
|
def downloadDriveFile(users):
|
||||||
i = 5
|
i = 5
|
||||||
fileIdSelection = {u'fileIds': None, u'query': None}
|
fileIdSelection = {u'fileIds': [], u'query': None}
|
||||||
revisionId = None
|
revisionId = None
|
||||||
exportFormatName = u'openoffice'
|
exportFormatName = u'openoffice'
|
||||||
exportFormats = DOCUMENT_FORMATS_MAP[exportFormatName]
|
exportFormats = DOCUMENT_FORMATS_MAP[exportFormatName]
|
||||||
@ -4827,13 +4839,16 @@ def addUpdateSendAs(users, i, addCmd):
|
|||||||
signature = readFile(filename, encoding=encoding)
|
signature = readFile(filename, encoding=encoding)
|
||||||
else:
|
else:
|
||||||
i = getSendAsAttributes(i, myarg, body, tagReplacements, command)
|
i = getSendAsAttributes(i, myarg, body, tagReplacements, command)
|
||||||
if signature != None:
|
if signature is not None:
|
||||||
if not signature:
|
if not signature:
|
||||||
body[u'signature'] = None
|
body[u'signature'] = None
|
||||||
elif tagReplacements:
|
elif tagReplacements:
|
||||||
body[u'signature'] = _processTags(tagReplacements, signature)
|
body[u'signature'] = _processTags(tagReplacements, signature)
|
||||||
else:
|
else:
|
||||||
body[u'signature'] = signature
|
body[u'signature'] = signature
|
||||||
|
kwargs = {u'body': body}
|
||||||
|
if not addCmd:
|
||||||
|
kwargs[u'sendAsEmail'] = emailAddress
|
||||||
i = 0
|
i = 0
|
||||||
count = len(users)
|
count = len(users)
|
||||||
for user in users:
|
for user in users:
|
||||||
@ -4842,9 +4857,6 @@ def addUpdateSendAs(users, i, addCmd):
|
|||||||
if not gmail:
|
if not gmail:
|
||||||
continue
|
continue
|
||||||
print u"Allowing %s to send as %s (%s/%s)" % (user, emailAddress, i, count)
|
print u"Allowing %s to send as %s (%s/%s)" % (user, emailAddress, i, count)
|
||||||
kwargs = {u'body': body}
|
|
||||||
if not addCmd:
|
|
||||||
kwargs[u'sendAsEmail'] = emailAddress
|
|
||||||
callGAPI(gmail.users().settings().sendAs(), [u'patch', u'create'][addCmd],
|
callGAPI(gmail.users().settings().sendAs(), [u'patch', u'create'][addCmd],
|
||||||
soft_errors=True,
|
soft_errors=True,
|
||||||
userId=u'me', **kwargs)
|
userId=u'me', **kwargs)
|
||||||
@ -5096,7 +5108,7 @@ def doProcessMessages(users, function):
|
|||||||
kwargs = {}
|
kwargs = {}
|
||||||
else:
|
else:
|
||||||
kwargs = {u'body': {}}
|
kwargs = {u'body': {}}
|
||||||
for my_key in body.keys():
|
for my_key in body:
|
||||||
kwargs[u'body'][my_key] = labelsToLabelIds(gmail, body[my_key])
|
kwargs[u'body'][my_key] = labelsToLabelIds(gmail, body[my_key])
|
||||||
for a_message in listResult:
|
for a_message in listResult:
|
||||||
i += 1
|
i += 1
|
||||||
@ -5327,7 +5339,7 @@ def renameLabels(users):
|
|||||||
if label[u'type'] == u'system':
|
if label[u'type'] == u'system':
|
||||||
continue
|
continue
|
||||||
match_result = re.search(pattern, label[u'name'])
|
match_result = re.search(pattern, label[u'name'])
|
||||||
if match_result != None:
|
if match_result is not None:
|
||||||
new_label_name = replace % match_result.groups()
|
new_label_name = replace % match_result.groups()
|
||||||
print u' Renaming "%s" to "%s"' % (label[u'name'], new_label_name)
|
print u' Renaming "%s" to "%s"' % (label[u'name'], new_label_name)
|
||||||
try:
|
try:
|
||||||
@ -5394,50 +5406,62 @@ FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP = {
|
|||||||
|
|
||||||
def _printFilter(user, userFilter, labels):
|
def _printFilter(user, userFilter, labels):
|
||||||
row = {u'User': user, u'id': userFilter[u'id']}
|
row = {u'User': user, u'id': userFilter[u'id']}
|
||||||
for item in userFilter[u'criteria']:
|
if u'criteria' in userFilter:
|
||||||
if item in [u'hasAttachment', u'excludeChats']:
|
for item in userFilter[u'criteria']:
|
||||||
row[item] = item
|
if item in [u'hasAttachment', u'excludeChats']:
|
||||||
elif item == u'size':
|
row[item] = item
|
||||||
row[item] = u'size {0} {1}'.format(userFilter[u'criteria'][u'sizeComparison'], userFilter[u'criteria'][item])
|
elif item == u'size':
|
||||||
elif item == u'sizeComparison':
|
row[item] = u'size {0} {1}'.format(userFilter[u'criteria'][u'sizeComparison'], userFilter[u'criteria'][item])
|
||||||
pass
|
elif item == u'sizeComparison':
|
||||||
else:
|
pass
|
||||||
row[item] = u'{0} {1}'.format(item, userFilter[u'criteria'][item])
|
else:
|
||||||
for labelId in userFilter[u'action'].get(u'addLabelIds', []):
|
row[item] = u'{0} {1}'.format(item, userFilter[u'criteria'][item])
|
||||||
if labelId in FILTER_ADD_LABEL_TO_ARGUMENT_MAP:
|
else:
|
||||||
row[FILTER_ADD_LABEL_TO_ARGUMENT_MAP[labelId]] = FILTER_ADD_LABEL_TO_ARGUMENT_MAP[labelId]
|
row[u'error'] = u'NoCriteria'
|
||||||
else:
|
if u'action' in userFilter:
|
||||||
row[u'label'] = u'label {0}'.format(_getLabelName(labels, labelId))
|
for labelId in userFilter[u'action'].get(u'addLabelIds', []):
|
||||||
for labelId in userFilter[u'action'].get(u'removeLabelIds', []):
|
if labelId in FILTER_ADD_LABEL_TO_ARGUMENT_MAP:
|
||||||
if labelId in FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP:
|
row[FILTER_ADD_LABEL_TO_ARGUMENT_MAP[labelId]] = FILTER_ADD_LABEL_TO_ARGUMENT_MAP[labelId]
|
||||||
row[FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP[labelId]] = FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP[labelId]
|
else:
|
||||||
if userFilter[u'action'].get(u'forward'):
|
row[u'label'] = u'label {0}'.format(_getLabelName(labels, labelId))
|
||||||
row[u'forward'] = u'forward {0}'.format(userFilter[u'action'][u'forward'])
|
for labelId in userFilter[u'action'].get(u'removeLabelIds', []):
|
||||||
|
if labelId in FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP:
|
||||||
|
row[FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP[labelId]] = FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP[labelId]
|
||||||
|
if userFilter[u'action'].get(u'forward'):
|
||||||
|
row[u'forward'] = u'forward {0}'.format(userFilter[u'action'][u'forward'])
|
||||||
|
else:
|
||||||
|
row[u'error'] = u'NoActions'
|
||||||
return row
|
return row
|
||||||
|
|
||||||
def _showFilter(userFilter, j, jcount, labels):
|
def _showFilter(userFilter, j, jcount, labels):
|
||||||
print u' Filter: {0}{1}'.format(userFilter[u'id'], currentCount(j, jcount))
|
print u' Filter: {0}{1}'.format(userFilter[u'id'], currentCount(j, jcount))
|
||||||
print u' Criteria:'
|
print u' Criteria:'
|
||||||
for item in userFilter[u'criteria']:
|
if u'criteria' in userFilter:
|
||||||
if item in [u'hasAttachment', u'excludeChats']:
|
for item in userFilter[u'criteria']:
|
||||||
print u' {0}'.format(item)
|
if item in [u'hasAttachment', u'excludeChats']:
|
||||||
elif item == u'size':
|
print u' {0}'.format(item)
|
||||||
print u' {0} {1} {2}'.format(item, userFilter[u'criteria'][u'sizeComparison'], userFilter[u'criteria'][item])
|
elif item == u'size':
|
||||||
elif item == u'sizeComparison':
|
print u' {0} {1} {2}'.format(item, userFilter[u'criteria'][u'sizeComparison'], userFilter[u'criteria'][item])
|
||||||
pass
|
elif item == u'sizeComparison':
|
||||||
else:
|
pass
|
||||||
print convertUTF8(u' {0} "{1}"'.format(item, userFilter[u'criteria'][item]))
|
else:
|
||||||
|
print convertUTF8(u' {0} "{1}"'.format(item, userFilter[u'criteria'][item]))
|
||||||
|
else:
|
||||||
|
print u' ERROR: No Filter criteria'
|
||||||
print u' Actions:'
|
print u' Actions:'
|
||||||
for labelId in userFilter[u'action'].get(u'addLabelIds', []):
|
if u'action' in userFilter:
|
||||||
if labelId in FILTER_ADD_LABEL_TO_ARGUMENT_MAP:
|
for labelId in userFilter[u'action'].get(u'addLabelIds', []):
|
||||||
print u' {0}'.format(FILTER_ADD_LABEL_TO_ARGUMENT_MAP[labelId])
|
if labelId in FILTER_ADD_LABEL_TO_ARGUMENT_MAP:
|
||||||
else:
|
print u' {0}'.format(FILTER_ADD_LABEL_TO_ARGUMENT_MAP[labelId])
|
||||||
print convertUTF8(u' label "{0}"'.format(_getLabelName(labels, labelId)))
|
else:
|
||||||
for labelId in userFilter[u'action'].get(u'removeLabelIds', []):
|
print convertUTF8(u' label "{0}"'.format(_getLabelName(labels, labelId)))
|
||||||
if labelId in FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP:
|
for labelId in userFilter[u'action'].get(u'removeLabelIds', []):
|
||||||
print u' {0}'.format(FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP[labelId])
|
if labelId in FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP:
|
||||||
if userFilter[u'action'].get(u'forward'):
|
print u' {0}'.format(FILTER_REMOVE_LABEL_TO_ARGUMENT_MAP[labelId])
|
||||||
print u' Forwarding Address: {0}'.format(userFilter[u'action'][u'forward'])
|
if userFilter[u'action'].get(u'forward'):
|
||||||
|
print u' Forwarding Address: {0}'.format(userFilter[u'action'][u'forward'])
|
||||||
|
else:
|
||||||
|
print u' ERROR: No Filter actions'
|
||||||
#
|
#
|
||||||
FILTER_CRITERIA_CHOICES_MAP = {
|
FILTER_CRITERIA_CHOICES_MAP = {
|
||||||
u'excludechats': u'excludeChats',
|
u'excludechats': u'excludeChats',
|
||||||
@ -6109,7 +6133,7 @@ def doPrintShowUserSchemas(csvFormat):
|
|||||||
todrive = True
|
todrive = True
|
||||||
i += 1
|
i += 1
|
||||||
else:
|
else:
|
||||||
print u'ERROR: %s is not a valid argument for "gam <users> %s schemas"' % (myarg, [u'show', u'print'][csvFormat])
|
print u'ERROR: %s is not a valid argument for "gam %s schemas"' % (myarg, [u'show', u'print'][csvFormat])
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
schemas = callGAPI(cd.schemas(), u'list', customerId=GC_Values[GC_CUSTOMER_ID])
|
schemas = callGAPI(cd.schemas(), u'list', customerId=GC_Values[GC_CUSTOMER_ID])
|
||||||
if not schemas or u'schemas' not in schemas:
|
if not schemas or u'schemas' not in schemas:
|
||||||
@ -6139,7 +6163,7 @@ def checkClearBodyList(i, body, itemName):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def appendItemToBodyList(body, itemName, itemValue):
|
def appendItemToBodyList(body, itemName, itemValue):
|
||||||
if (itemName in body) and (body[itemName] == None):
|
if (itemName in body) and (body[itemName] is None):
|
||||||
del body[itemName]
|
del body[itemName]
|
||||||
body.setdefault(itemName, [])
|
body.setdefault(itemName, [])
|
||||||
body[itemName].append(itemValue)
|
body[itemName].append(itemValue)
|
||||||
@ -7170,7 +7194,7 @@ def doWhatIs():
|
|||||||
def doGetUserInfo(user_email=None):
|
def doGetUserInfo(user_email=None):
|
||||||
cd = buildGAPIObject(u'directory')
|
cd = buildGAPIObject(u'directory')
|
||||||
i = 3
|
i = 3
|
||||||
if user_email == None:
|
if user_email is None:
|
||||||
if len(sys.argv) > 3:
|
if len(sys.argv) > 3:
|
||||||
user_email = sys.argv[3]
|
user_email = sys.argv[3]
|
||||||
i = 4
|
i = 4
|
||||||
@ -7208,7 +7232,7 @@ def doGetUserInfo(user_email=None):
|
|||||||
getSchemas = False
|
getSchemas = False
|
||||||
projection = u'basic'
|
projection = u'basic'
|
||||||
i += 1
|
i += 1
|
||||||
elif myarg == u'schemas':
|
elif myarg in [u'custom', u'schemas']:
|
||||||
getSchemas = True
|
getSchemas = True
|
||||||
projection = u'custom'
|
projection = u'custom'
|
||||||
customFieldMask = sys.argv[i+1]
|
customFieldMask = sys.argv[i+1]
|
||||||
@ -7391,7 +7415,7 @@ def doGetGroupInfo(group_name=None):
|
|||||||
gs = buildGAPIObject(u'groupssettings')
|
gs = buildGAPIObject(u'groupssettings')
|
||||||
getAliases = getUsers = True
|
getAliases = getUsers = True
|
||||||
getGroups = False
|
getGroups = False
|
||||||
if group_name == None:
|
if group_name is None:
|
||||||
group_name = sys.argv[3]
|
group_name = sys.argv[3]
|
||||||
i = 4
|
i = 4
|
||||||
else:
|
else:
|
||||||
@ -7469,7 +7493,7 @@ def doGetGroupInfo(group_name=None):
|
|||||||
|
|
||||||
def doGetAliasInfo(alias_email=None):
|
def doGetAliasInfo(alias_email=None):
|
||||||
cd = buildGAPIObject(u'directory')
|
cd = buildGAPIObject(u'directory')
|
||||||
if alias_email == None:
|
if alias_email is None:
|
||||||
alias_email = sys.argv[3]
|
alias_email = sys.argv[3]
|
||||||
if alias_email.find(u'@') == -1:
|
if alias_email.find(u'@') == -1:
|
||||||
alias_email = u'%s@%s' % (alias_email, GC_Values[GC_DOMAIN])
|
alias_email = u'%s@%s' % (alias_email, GC_Values[GC_DOMAIN])
|
||||||
@ -7641,13 +7665,13 @@ def doGetMobileInfo():
|
|||||||
def print_json(object_name, object_value, spacing=u''):
|
def print_json(object_name, object_value, spacing=u''):
|
||||||
if object_name in [u'kind', u'etag', u'etags']:
|
if object_name in [u'kind', u'etag', u'etags']:
|
||||||
return
|
return
|
||||||
if object_name != None:
|
if object_name is not None:
|
||||||
sys.stdout.write(u'%s%s: ' % (spacing, object_name))
|
sys.stdout.write(u'%s%s: ' % (spacing, object_name))
|
||||||
if isinstance(object_value, list):
|
if isinstance(object_value, list):
|
||||||
if len(object_value) == 1 and isinstance(object_value[0], (str, unicode, int, bool)):
|
if len(object_value) == 1 and isinstance(object_value[0], (str, unicode, int, bool)):
|
||||||
sys.stdout.write(convertUTF8(u'%s\n' % object_value[0]))
|
sys.stdout.write(convertUTF8(u'%s\n' % object_value[0]))
|
||||||
return
|
return
|
||||||
if object_name != None:
|
if object_name is not None:
|
||||||
sys.stdout.write(u'\n')
|
sys.stdout.write(u'\n')
|
||||||
for a_value in object_value:
|
for a_value in object_value:
|
||||||
if isinstance(a_value, (str, unicode, int, bool)):
|
if isinstance(a_value, (str, unicode, int, bool)):
|
||||||
@ -7656,7 +7680,7 @@ def print_json(object_name, object_value, spacing=u''):
|
|||||||
print_json(None, a_value, u' %s' % spacing)
|
print_json(None, a_value, u' %s' % spacing)
|
||||||
elif isinstance(object_value, dict):
|
elif isinstance(object_value, dict):
|
||||||
print
|
print
|
||||||
if object_name != None:
|
if object_name is not None:
|
||||||
sys.stdout.write(u'\n')
|
sys.stdout.write(u'\n')
|
||||||
for another_object in object_value:
|
for another_object in object_value:
|
||||||
print_json(another_object, object_value[another_object], u' %s' % spacing)
|
print_json(another_object, object_value[another_object], u' %s' % spacing)
|
||||||
@ -7687,7 +7711,7 @@ def doUpdateNotification():
|
|||||||
else:
|
else:
|
||||||
print u'ERROR: %s is not a valid argument for "gam update notification"' % sys.argv[i]
|
print u'ERROR: %s is not a valid argument for "gam update notification"' % sys.argv[i]
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
if isUnread == None:
|
if isUnread is None:
|
||||||
print u'ERROR: notifications need to be marked as read or unread.'
|
print u'ERROR: notifications need to be marked as read or unread.'
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
if get_all:
|
if get_all:
|
||||||
@ -8148,7 +8172,7 @@ def doDeleteGroup():
|
|||||||
def doDeleteAlias(alias_email=None):
|
def doDeleteAlias(alias_email=None):
|
||||||
cd = buildGAPIObject(u'directory')
|
cd = buildGAPIObject(u'directory')
|
||||||
is_user = is_group = False
|
is_user = is_group = False
|
||||||
if alias_email == None:
|
if alias_email is None:
|
||||||
alias_email = sys.argv[3]
|
alias_email = sys.argv[3]
|
||||||
if alias_email.lower() == u'user':
|
if alias_email.lower() == u'user':
|
||||||
is_user = True
|
is_user = True
|
||||||
@ -8292,7 +8316,7 @@ def writeCSVfile(csvRows, titles, list_type, todrive):
|
|||||||
webbrowser.open(file_url)
|
webbrowser.open(file_url)
|
||||||
|
|
||||||
def flatten_json(structure, key=u'', path=u'', flattened=None, listLimit=None):
|
def flatten_json(structure, key=u'', path=u'', flattened=None, listLimit=None):
|
||||||
if flattened == None:
|
if flattened is None:
|
||||||
flattened = {}
|
flattened = {}
|
||||||
if not isinstance(structure, (dict, list)):
|
if not isinstance(structure, (dict, list)):
|
||||||
flattened[((path + u'.') if path else u'') + key] = structure
|
flattened[((path + u'.') if path else u'') + key] = structure
|
||||||
@ -8394,7 +8418,7 @@ def doPrintUsers():
|
|||||||
sortHeaders = True
|
sortHeaders = True
|
||||||
fieldsList = []
|
fieldsList = []
|
||||||
i += 1
|
i += 1
|
||||||
elif myarg == u'custom':
|
elif myarg in [u'custom', u'schemas']:
|
||||||
fieldsList.append(u'customSchemas')
|
fieldsList.append(u'customSchemas')
|
||||||
if sys.argv[i+1].lower() == u'all':
|
if sys.argv[i+1].lower() == u'all':
|
||||||
projection = u'full'
|
projection = u'full'
|
||||||
@ -8698,7 +8722,7 @@ def doPrintGroups():
|
|||||||
if key in [u'email', u'name', u'description', u'kind', u'etag']:
|
if key in [u'email', u'name', u'description', u'kind', u'etag']:
|
||||||
continue
|
continue
|
||||||
setting_value = settings[key]
|
setting_value = settings[key]
|
||||||
if setting_value == None:
|
if setting_value is None:
|
||||||
setting_value = u''
|
setting_value = u''
|
||||||
if key not in titles:
|
if key not in titles:
|
||||||
addTitleToCSVfile(key, titles)
|
addTitleToCSVfile(key, titles)
|
||||||
@ -8869,7 +8893,7 @@ def doPrintGroupMembers():
|
|||||||
if member[u'type'] == u'USER':
|
if member[u'type'] == u'USER':
|
||||||
try:
|
try:
|
||||||
mbinfo = callGAPI(cd.users(), u'get',
|
mbinfo = callGAPI(cd.users(), u'get',
|
||||||
throw_reasons=[u'notFound', u'forbidden'],
|
throw_reasons=[u'userNotFound', u'notFound', u'forbidden'],
|
||||||
userKey=member[u'id'], fields=u'name')
|
userKey=member[u'id'], fields=u'name')
|
||||||
memberName = mbinfo[u'name'][u'fullName']
|
memberName = mbinfo[u'name'][u'fullName']
|
||||||
except googleapiclient.errors.HttpError:
|
except googleapiclient.errors.HttpError:
|
||||||
@ -9200,9 +9224,9 @@ def doPrintResourceCalendars():
|
|||||||
|
|
||||||
def getUsersToModify(entity_type=None, entity=None, silent=False, member_type=None, checkNotSuspended=False):
|
def getUsersToModify(entity_type=None, entity=None, silent=False, member_type=None, checkNotSuspended=False):
|
||||||
got_uids = False
|
got_uids = False
|
||||||
if entity_type == None:
|
if entity_type is None:
|
||||||
entity_type = sys.argv[1].lower()
|
entity_type = sys.argv[1].lower()
|
||||||
if entity == None:
|
if entity is None:
|
||||||
entity = sys.argv[2]
|
entity = sys.argv[2]
|
||||||
cd = buildGAPIObject(u'directory')
|
cd = buildGAPIObject(u'directory')
|
||||||
if entity_type == u'user':
|
if entity_type == u'user':
|
||||||
@ -9212,7 +9236,7 @@ def getUsersToModify(entity_type=None, entity=None, silent=False, member_type=No
|
|||||||
elif entity_type == u'group':
|
elif entity_type == u'group':
|
||||||
got_uids = True
|
got_uids = True
|
||||||
group = entity
|
group = entity
|
||||||
if member_type == None:
|
if member_type is None:
|
||||||
member_type_message = u'all members'
|
member_type_message = u'all members'
|
||||||
else:
|
else:
|
||||||
member_type_message = u'%ss' % member_type.lower()
|
member_type_message = u'%ss' % member_type.lower()
|
||||||
@ -9650,7 +9674,8 @@ def batch_worker():
|
|||||||
GM_Globals[GM_BATCH_QUEUE].task_done()
|
GM_Globals[GM_BATCH_QUEUE].task_done()
|
||||||
|
|
||||||
def run_batch(items):
|
def run_batch(items):
|
||||||
import Queue, threading
|
import Queue
|
||||||
|
import threading
|
||||||
total_items = len(items)
|
total_items = len(items)
|
||||||
current_item = 0
|
current_item = 0
|
||||||
python_cmd = [sys.executable.lower(),]
|
python_cmd = [sys.executable.lower(),]
|
||||||
@ -9940,14 +9965,14 @@ def ProcessGAMCommand(args):
|
|||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif command == u'print':
|
elif command == u'print':
|
||||||
argument = sys.argv[2].lower()
|
argument = sys.argv[2].lower().replace(u'-', u'')
|
||||||
if argument == u'users':
|
if argument == u'users':
|
||||||
doPrintUsers()
|
doPrintUsers()
|
||||||
elif argument in [u'nicknames', u'aliases']:
|
elif argument in [u'nicknames', u'aliases']:
|
||||||
doPrintAliases()
|
doPrintAliases()
|
||||||
elif argument == u'groups':
|
elif argument == u'groups':
|
||||||
doPrintGroups()
|
doPrintGroups()
|
||||||
elif argument in [u'group-members', u'groups-members']:
|
elif argument in [u'groupmembers', u'groupsmembers']:
|
||||||
doPrintGroupMembers()
|
doPrintGroupMembers()
|
||||||
elif argument in [u'orgs', u'ous']:
|
elif argument in [u'orgs', u'ous']:
|
||||||
doPrintOrgs()
|
doPrintOrgs()
|
||||||
@ -9965,7 +9990,7 @@ def ProcessGAMCommand(args):
|
|||||||
doPrintShowUserSchemas(True)
|
doPrintShowUserSchemas(True)
|
||||||
elif argument in [u'courses', u'classes']:
|
elif argument in [u'courses', u'classes']:
|
||||||
doPrintCourses()
|
doPrintCourses()
|
||||||
elif argument in [u'course-participants', u'class-participants']:
|
elif argument in [u'courseparticipants', u'classparticipants']:
|
||||||
doPrintCourseParticipants()
|
doPrintCourseParticipants()
|
||||||
elif argument == u'printers':
|
elif argument == u'printers':
|
||||||
doPrintPrinters()
|
doPrintPrinters()
|
||||||
|
Reference in New Issue
Block a user