mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-29 18:31:38 +00:00
Implement Chrome version history (#1354)
* Implement Chrome version history * Update GamCommands.txt * Use httpObj
This commit is contained in:
@@ -53,6 +53,7 @@ from gam import fileutils
|
||||
from gam.gapi import calendar as gapi_calendar
|
||||
from gam.gapi import cloudidentity as gapi_cloudidentity
|
||||
from gam.gapi import cbcm as gapi_cbcm
|
||||
from gam.gapi import chromehistory as gapi_chromehistory
|
||||
from gam.gapi import chromemanagement as gapi_chromemanagement
|
||||
from gam.gapi import chromepolicy as gapi_chromepolicy
|
||||
from gam.gapi.cloudidentity import devices as gapi_cloudidentity_devices
|
||||
@@ -893,14 +894,14 @@ def getValidOauth2TxtCredentials(force_refresh=False, api=None):
|
||||
return credentials
|
||||
|
||||
|
||||
def getService(api, http):
|
||||
def getService(api, httpObj):
|
||||
api, version, api_version = getAPIVersion(api)
|
||||
if api in GM_Globals[GM_CURRENT_API_SERVICES] and version in GM_Globals[
|
||||
GM_CURRENT_API_SERVICES][api]:
|
||||
service = googleapiclient.discovery.build_from_document(
|
||||
GM_Globals[GM_CURRENT_API_SERVICES][api][version], http=http)
|
||||
GM_Globals[GM_CURRENT_API_SERVICES][api][version], http=httpObj)
|
||||
if GM_Globals[GM_CACHE_DISCOVERY_ONLY]:
|
||||
http.cache = None
|
||||
httpObj.cache = None
|
||||
return service
|
||||
if api in V1_DISCOVERY_APIS:
|
||||
discoveryServiceUrl = googleapiclient.discovery.DISCOVERY_URI
|
||||
@@ -912,7 +913,7 @@ def getService(api, http):
|
||||
service = googleapiclient.discovery.build(
|
||||
api,
|
||||
version,
|
||||
http=http,
|
||||
http=httpObj,
|
||||
cache_discovery=False,
|
||||
static_discovery=False,
|
||||
discoveryServiceUrl=discoveryServiceUrl)
|
||||
@@ -920,23 +921,25 @@ def getService(api, http):
|
||||
GM_Globals[GM_CURRENT_API_SERVICES][api][
|
||||
version] = service._rootDesc.copy()
|
||||
if GM_Globals[GM_CACHE_DISCOVERY_ONLY]:
|
||||
http.cache = None
|
||||
httpObj.cache = None
|
||||
return service
|
||||
except (httplib2.ServerNotFoundError, RuntimeError) as e:
|
||||
if n != retries:
|
||||
http.connections = {}
|
||||
httpObj.connections = {}
|
||||
controlflow.wait_on_failure(n, retries, str(e))
|
||||
continue
|
||||
controlflow.system_error_exit(4, str(e))
|
||||
except (googleapiclient.errors.InvalidJsonError, KeyError,
|
||||
ValueError) as e:
|
||||
http.cache = None
|
||||
httpObj.cache = None
|
||||
if n != retries:
|
||||
controlflow.wait_on_failure(n, retries, str(e))
|
||||
continue
|
||||
controlflow.system_error_exit(17, str(e))
|
||||
except (http_client.ResponseNotReady, OSError,
|
||||
googleapiclient.errors.HttpError) as e:
|
||||
if 'The request is missing a valid API key' in str(e):
|
||||
break
|
||||
if n != retries:
|
||||
controlflow.wait_on_failure(n, retries, str(e))
|
||||
continue
|
||||
@@ -946,12 +949,12 @@ def getService(api, http):
|
||||
disc_file, discovery = readDiscoveryFile(api_version)
|
||||
try:
|
||||
service = googleapiclient.discovery.build_from_document(discovery,
|
||||
http=http)
|
||||
http=httpObj)
|
||||
GM_Globals[GM_CURRENT_API_SERVICES].setdefault(api, {})
|
||||
GM_Globals[GM_CURRENT_API_SERVICES][api][
|
||||
version] = service._rootDesc.copy()
|
||||
if GM_Globals[GM_CACHE_DISCOVERY_ONLY]:
|
||||
http.cache = None
|
||||
httpObj.cache = None
|
||||
return service
|
||||
except (KeyError, ValueError):
|
||||
controlflow.invalid_json_exit(disc_file)
|
||||
@@ -961,9 +964,9 @@ def buildGAPIObject(api):
|
||||
GM_Globals[GM_CURRENT_API_USER] = None
|
||||
credentials = getValidOauth2TxtCredentials(api=getAPIVersion(api)[0])
|
||||
credentials.user_agent = GAM_INFO
|
||||
http = transport.AuthorizedHttp(
|
||||
httpObj = transport.AuthorizedHttp(
|
||||
credentials, transport.create_http(cache=GM_Globals[GM_CACHE_DIR]))
|
||||
service = getService(api, http)
|
||||
service = getService(api, httpObj)
|
||||
if GC_Values[GC_DOMAIN]:
|
||||
if not GC_Values[GC_CUSTOMER_ID]:
|
||||
resp, result = service._http.request(
|
||||
@@ -995,6 +998,12 @@ def buildGAPIObject(api):
|
||||
return service
|
||||
|
||||
|
||||
def buildGAPIObjectNoAuthentication(api):
|
||||
GM_Globals[GM_CURRENT_API_USER] = None
|
||||
httpObj = transport.create_http(cache=GM_Globals[GM_CACHE_DIR])
|
||||
service = getService(api, httpObj)
|
||||
return service
|
||||
|
||||
# Convert UID to email address
|
||||
def convertUIDtoEmailAddress(emailAddressOrUID, cd=None, email_types=['user']):
|
||||
if isinstance(email_types, str):
|
||||
@@ -1078,23 +1087,23 @@ def convertEmailAddressToUID(emailAddressOrUID, cd=None, email_type='user'):
|
||||
|
||||
|
||||
def buildGAPIServiceObject(api, act_as, showAuthError=True):
|
||||
http = transport.create_http(cache=GM_Globals[GM_CACHE_DIR])
|
||||
service = getService(api, http)
|
||||
httpObj = transport.create_http(cache=GM_Globals[GM_CACHE_DIR])
|
||||
service = getService(api, httpObj)
|
||||
GM_Globals[GM_CURRENT_API_USER] = act_as
|
||||
GM_Globals[GM_CURRENT_API_SCOPES] = API_SCOPE_MAPPING.get(
|
||||
api, service._rootDesc['auth']['oauth2']['scopes'])
|
||||
credentials = getSvcAcctCredentials(GM_Globals[GM_CURRENT_API_SCOPES],
|
||||
act_as)
|
||||
request = transport.create_request(http)
|
||||
request = transport.create_request(httpObj)
|
||||
retries = 3
|
||||
for n in range(1, retries + 1):
|
||||
try:
|
||||
credentials.refresh(request)
|
||||
service._http = transport.AuthorizedHttp(credentials, http=http)
|
||||
service._http = transport.AuthorizedHttp(credentials, http=httpObj)
|
||||
break
|
||||
except (httplib2.ServerNotFoundError, RuntimeError) as e:
|
||||
if n != retries:
|
||||
http.connections = {}
|
||||
httpObj.connections = {}
|
||||
controlflow.wait_on_failure(n, retries, str(e))
|
||||
continue
|
||||
controlflow.system_error_exit(4, e)
|
||||
@@ -11533,6 +11542,8 @@ def ProcessGAMCommand(args):
|
||||
gapi_chromemanagement.printAppDevices()
|
||||
elif argument in ['chromeversions']:
|
||||
gapi_chromemanagement.printVersions()
|
||||
elif argument in ['chromehistory']:
|
||||
gapi_chromehistory.printHistory()
|
||||
else:
|
||||
controlflow.invalid_argument_exit(argument, 'gam print')
|
||||
sys.exit(0)
|
||||
|
||||
153
src/gam/gapi/chromehistory.py
Normal file
153
src/gam/gapi/chromehistory.py
Normal file
@@ -0,0 +1,153 @@
|
||||
"""Chrome Version History API calls"""
|
||||
|
||||
import sys
|
||||
|
||||
import gam
|
||||
from gam.var import *
|
||||
from gam import controlflow
|
||||
from gam import display
|
||||
from gam import gapi
|
||||
from gam import utils
|
||||
|
||||
|
||||
def build():
|
||||
return gam.buildGAPIObjectNoAuthentication('versionhistory')
|
||||
|
||||
|
||||
CHROME_HISTORY_ENTITY_CHOICES = {
|
||||
'platforms',
|
||||
'channels',
|
||||
'versions',
|
||||
'releases',
|
||||
}
|
||||
CHROME_PLATFORM_CHOICE_MAP = {
|
||||
'all': 'all',
|
||||
'android': 'android',
|
||||
'ios': 'ios',
|
||||
'lacros': 'lacros',
|
||||
'linux': 'linux',
|
||||
'mac': 'mac',
|
||||
'macarm64': 'mac_arm64',
|
||||
'sebview': 'webview',
|
||||
'win': 'win',
|
||||
'win64': 'win64',
|
||||
}
|
||||
CHROME_CHANNEL_CHOICE_MAP = {
|
||||
'beta': 'beta',
|
||||
'canary': 'canary',
|
||||
'canaryasan': 'canary_asan',
|
||||
'dev': 'dev',
|
||||
'stable': 'stable',
|
||||
}
|
||||
CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP = {
|
||||
'versions': {
|
||||
'channel': 'channel',
|
||||
'name': 'name',
|
||||
'platform': 'platform',
|
||||
'version': 'version'
|
||||
},
|
||||
'releases': {
|
||||
'channel': 'channel',
|
||||
'endtime': 'endtime',
|
||||
'fraction': 'fraction',
|
||||
'name': 'name',
|
||||
'platform': 'platform',
|
||||
'starttime': 'starttime',
|
||||
'version': 'version'
|
||||
}
|
||||
}
|
||||
CHROME_VERSIONHISTORY_TITLES = {
|
||||
'platforms': ['name', 'platformType'],
|
||||
'channels': ['name', 'channelType'],
|
||||
'versions': ['name', 'version'],
|
||||
'releases': ['name', 'version', 'fraction', 'serving.startTime', 'serving.endTime']
|
||||
}
|
||||
|
||||
def printHistory():
|
||||
cv = build()
|
||||
entityType = sys.argv[3].lower().replace('_', '')
|
||||
if entityType not in CHROME_HISTORY_ENTITY_CHOICES:
|
||||
msg = f'{entityType} is not a valid argument to "gam print chromehistory"'
|
||||
controlflow.system_error_exit(3, msg)
|
||||
todrive = False
|
||||
csvRows = []
|
||||
cplatform = 'all'
|
||||
channel = 'all'
|
||||
version = 'all'
|
||||
kwargs = {}
|
||||
orderByList = []
|
||||
i = 4
|
||||
while i < len(sys.argv):
|
||||
myarg = sys.argv[i].lower().replace('_', '')
|
||||
if myarg == 'todrive':
|
||||
todrive = True
|
||||
i += 1
|
||||
elif entityType != 'platforms' and myarg == 'platform':
|
||||
cplatform = sys.argv[i + 1].lower().replace('_', '')
|
||||
if cplatform not in CHROME_PLATFORM_CHOICE_MAP:
|
||||
controlflow.expected_argument_exit('platform',
|
||||
', '.join(CHROME_PLATFORM_CHOICE_MAP),
|
||||
cplatform)
|
||||
cplatform = CHROME_PLATFORM_CHOICE_MAP[cplatform]
|
||||
i += 2
|
||||
elif entityType in {'versions', 'releases'} and myarg == 'channel':
|
||||
channel = sys.argv[i + 1].lower().replace('_', '')
|
||||
if channel not in CHROME_CHANNEL_CHOICE_MAP:
|
||||
controlflow.expected_argument_exit('channel',
|
||||
', '.join(CHROME_CHANNEL_CHOICE_MAP),
|
||||
channel)
|
||||
channel = CHROME_CHANNEL_CHOICE_MAP[channel]
|
||||
i += 2
|
||||
elif entityType == 'releases' and myarg == 'version':
|
||||
version = sys.argv[i + 1]
|
||||
i += 2
|
||||
elif entityType in {'versions', 'releases'} and myarg == 'orderby':
|
||||
fieldName = sys.argv[i + 1].lower().replace('_', '')
|
||||
i += 2
|
||||
if fieldName in CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[entityType]:
|
||||
fieldName = CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[entityType][fieldName]
|
||||
orderBy = ''
|
||||
if i < len(sys.argv):
|
||||
orderBy = sys.argv[i].lower()
|
||||
if orderBy in SORTORDER_CHOICES_MAP:
|
||||
orderBy = SORTORDER_CHOICES_MAP[orderBy]
|
||||
i += 1
|
||||
if orderBy != 'DESCENDING':
|
||||
orderByList.append(fieldName)
|
||||
else:
|
||||
orderByList.append(f'{fieldName} desc')
|
||||
else:
|
||||
controlflow.expected_argument_exit('orderby',
|
||||
', '.join(CHROME_VERSIONHISTORY_ORDERBY_CHOICE_MAP[entityType]),
|
||||
fieldName)
|
||||
elif entityType in {'versions', 'releases'} and myarg == 'filter':
|
||||
kwargs['filter'] = sys.argv[i + 1]
|
||||
i += 2
|
||||
else:
|
||||
msg = f'{myarg} is not a valid argument to "gam print chromehistory {entityType}"'
|
||||
controlflow.system_error_exit(3, msg)
|
||||
if orderByList:
|
||||
kwargs['orderBy'] = ','.join(orderByList)
|
||||
if entityType == 'platforms':
|
||||
svc = cv.platforms()
|
||||
parent = 'chrome'
|
||||
elif entityType == 'channels':
|
||||
svc = cv.platforms().channels()
|
||||
parent = f'chrome/platforms/{cplatform}'
|
||||
elif entityType == 'versions':
|
||||
svc = cv.platforms().channels().versions()
|
||||
parent = f'chrome/platforms/{cplatform}/channels/{channel}'
|
||||
else: #elif entityType == 'releases'
|
||||
svc = cv.platforms().channels().versions().releases()
|
||||
parent = f'chrome/platforms/{cplatform}/channels/{channel}/versions/{version}'
|
||||
reportTitle = f'Chrome Version History {entityType.capitalize()}'
|
||||
page_message = gapi.got_total_items_msg(reportTitle, '...\n')
|
||||
gam.printGettingAllItems(reportTitle, None)
|
||||
citems = gapi.get_all_pages(svc, 'list', entityType,
|
||||
page_message=page_message,
|
||||
parent=parent,
|
||||
fields=f'nextPageToken,{entityType}',
|
||||
**kwargs)
|
||||
for citem in citems:
|
||||
csvRows.append(utils.flatten_json(citem))
|
||||
display.write_csv_file(csvRows, CHROME_VERSIONHISTORY_TITLES[entityType], reportTitle, todrive)
|
||||
@@ -40,19 +40,19 @@ def create_http(cache=None,
|
||||
return httpObj
|
||||
|
||||
|
||||
def create_request(http=None):
|
||||
def create_request(httpObj=None):
|
||||
"""Creates a uniform Request object with a default http, if not provided.
|
||||
|
||||
Args:
|
||||
http: Optional httplib2.Http compatible object to be used with the request.
|
||||
httpObj: Optional httplib2.Http compatible object to be used with the request.
|
||||
If not provided, a default HTTP will be used.
|
||||
|
||||
Returns:
|
||||
Request: A google_auth_httplib2.Request compatible Request.
|
||||
"""
|
||||
if not http:
|
||||
http = create_http()
|
||||
return Request(http)
|
||||
if not httpObj:
|
||||
httpObj = create_http()
|
||||
return Request(httpObj)
|
||||
|
||||
|
||||
GAM_USER_AGENT = GAM_INFO
|
||||
|
||||
@@ -324,6 +324,7 @@ API_VER_MAPPING = {
|
||||
'siteVerification': 'v1',
|
||||
'storage': 'v1',
|
||||
'vault': 'v1',
|
||||
'versionhistory': 'v1',
|
||||
}
|
||||
|
||||
USERINFO_EMAIL_SCOPE = 'https://www.googleapis.com/auth/userinfo.email'
|
||||
|
||||
Reference in New Issue
Block a user