python/googleDriveList.py
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
def err(*m):
print('error in', __file__ + ':', *m)
x = 1 / 0
def credentials(crt):
if type(crt) != str or len(crt) < 1:
err(f"bad certification name: {crt} {type(crt)}")
""" load the credentials form google OAuth2,
see Google APPI Console https://console.developers.google.com/?authuser=0&project=quickstart-1611556606696
"""
# If modifying these scopes, delete the file token.pickle.
SCOPES =[ 'https://www.googleapis.com/auth/drive.metadata.readonly' # drive readonly
, 'https://www.googleapis.com/auth/drive' # drive file update
, 'https://www.googleapis.com/auth/documents.readonly' # docs readonly
#, 'https://www.googleapis.com/auth/documents' # docs readWrite
]
tokPiFi = f'token-{crt}.pickle' # the file to cache authorization
credJson = '/wkData/pc/googleAPIcredentials.json' # the credentials file generated by google API
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(tokPiFi):
with open(tokPiFi, 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(credJson, SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(tokPiFi, 'wb') as token:
pickle.dump(creds, token)
return creds
import sys
def driveInfo():
global srvDrive
# Call the Drive v3 API
ab = srvDrive.about().get(fields='user(displayName, emailAddress, kind), storageQuota').execute()
# print(ab)
print(ab['user']['kind'], ab['user']['displayName'], ab['user']['emailAddress']
, '; storage (MB) usage', round(int(ab['storageQuota']['usage'])/1048576), ', trash', round(int(ab['storageQuota']['usageInDriveTrash'])/1048576)
, ', limit', round(int(ab['storageQuota']['limit'])/1048576))
def testDrive():
global srvDrive
# Call the Drive v3 API
print('abo', dir(srvDrive.about()))
print('get', srvDrive.about().get(fields='*').execute())
print('root', srvDrive.files().get(fileId='root',fields='*').execute())
next = None
for p in range(2):
results = srvDrive.files().list(
pageSize=10, pageToken=next, fields="nextPageToken, files(id, name, kind, parents)"
, q="mimeType = 'application/vnd.google-apps.folder' and name = 'akt' or name = 'spWal' or name = 'sitzung'").execute()
items = results.get('files', [])
next = results.get('nextPageToken')
print('page', p, 'next', next)
if not items:
print('No more files found.')
return
print('Files:', items)
for item in items:
print('\nfile',item['name'], item)
# data = srvDrive.files().get(fileId=item['id'],fields='name,kind,mimeType,id,parents,shared,ownedByMe').execute()
data = srvDrive.files().get(fileId=item['id'],fields='*').execute()
print('get',data)
if 'parents' in item:
print("parent", srvDrive.files().get(fileId=item['parents'][0], fields='name,kind,mimeType,id,parents,shared,ownedByMe').execute())
def testList():
next = None
res = srvDrive.files().list(
pageSize=500, pageToken=next, fields="nextPageToken, files(id, name, mimeType, kind, parents,modifiedTime,owners(emailAddress))"
, q="'root' in parents", orderBy="folder, name desc"
).execute()
fi = res.get('files', [])
print('#files', len(fi))
for f in fi:
print(f)
def simList(fo):
next = None
while True:
res = srvDrive.files().list(
pageSize=5, pageToken=next, fields="nextPageToken, files(name, id, kind, mimeType, modifiedTime, parents, owners(emailAddress))"
, q="'" + fo + "' in parents", orderBy="name"
).execute()
fi = res.get('files', [])
next = res.get('nextPageToken')
print('#files', len(fi), 'next', next)
for f in fi:
if len(f['parents']) != 1:
err('parents in', f);
f['parent'] = f['parents'][0]
del f['parents']
if len(f['owners']) != 1 or 'emailAddress' not in f['owners'][0]:
err('owners in', f);
f['owner'] = f['owners'][0]['emailAddress']
del f['owners']
print(f)
if next == None:
break
def fldWalk(fo, cb, lv, nm):
fFlds = "name, id, kind, mimeType, createdTime, modifiedTime, trashed, parents, owners(emailAddress)"
ff = []
if lv == -1 :
ff.append(srvDrive.files().get(fileId=fo,fields=fFlds).execute())
else:
next = None
while True:
res = srvDrive.files().list(
pageSize=500, pageToken=next, fields=f"nextPageToken, files({fFlds})"
, q="'" + fo + "' in parents", orderBy="name"
).execute()
ff += res.get('files', [])
next = res.get('nextPageToken')
if next == None:
break
fc = 0
for f in ff:
fc += int(f['mimeType'] == 'application/vnd.google-apps.folder')
print('{:39} {}'.format('{:30}'.format(' ' * lv + nm) + ' #' + str(fc) + '/' + str(len(ff)) + '#', fo))
for f in ff:
print(1, f)
if 'parents' not in f:
if lv == -1:
f['parent'] = ''
else:
err('no parent', f)
elif len(f['parents']) != 1:
err('parents in', f);
else:
f['parent'] = f['parents'][0]
del f['parents']
if len(f['owners']) != 1 or 'emailAddress' not in f['owners'][0]:
err('owners in', f);
f['owner'] = f['owners'][0]['emailAddress']
del f['owners']
# print(f)
cb(f)
for f in ff:
if f['mimeType'] == 'application/vnd.google-apps.folder':
fldWalk(f['id'], cb, lv+1, f['name'])
import csv
def fo2csv(fo, fn, foN):
with open(fn, 'w', newline='') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=['name', 'id', 'kind', 'mimeType', 'createdTime', 'modifiedTime', 'trashed', 'trashedTime', 'parent', 'owner'])
writer.writeheader()
fldWalk(fo, lambda d: writer.writerow(d), -1, foN)
tSeq = 0
def treeListOne(fd, pNo):
global tSeq
tSeq+=1
fd['seq'] = tSeq
fd['paS'] = pNo
print('{0:5d} {1:5d}'.format(pNo, tSeq), fd['name'], fd['mimeType'], fd['id'])
return fd
fId2fi = dict()
fId2fo = dict()
def treeDictAdd(fd):
global fId2fi
if fd['id'] not in fId2fi:
fId2fi[fd['id']] = fd
next = None
fls = []
print('folder start', fd['name'])
while True:
results = srvDrive.files().list(
pageSize=500, pageToken=next, fields="nextPageToken, files(id, name, mimeType, kind, parents)"
, q="'" + fd['id'] + "' in parents").execute()
fls += results.get('files', [])
print('+= get', [ f['name'] for f in fls])
next = results.get('nextPageToken')
if next == None:
break
fls.sort(key=lambda f: f['name'])
print('sort', [ f['name'] for f in fls])
for f in fls:
fId2fi[f['id']] = f
print('dict', [ f['name'] for f in fId2fi.values()])
for f in fls:
if f['mimeType'] == 'application/vnd.google-apps.folder':
treeDictAdd(f)
def testList():
next = None
res = srvDrive.files().list(
pageSize=500, pageToken=next, fields="nextPageToken, files(id, name, mimeType, kind, parents,modifiedTime,owners(emailAddress))"
, q="'root' in parents", orderBy="folder, name desc"
).execute()
fi = res.get('files', [])
print('#files', len(fi))
for f in fi:
print(f)
def allDict():
global fId2fi, fId2fo
fi = dict()
root = srvDrive.files().get(fileId='root',fields='name,kind,mimeType,id,parents,modifiedTime,owners(emailAddress)').execute()
fi[root['id']] = root
print('root', root)
fId2fo = { root['id']: []}
next = None
while True:
results = srvDrive.files().list(
pageSize=500, pageToken=next, fields="nextPageToken, files(id, name, mimeType, kind, parents,modifiedTime,owners(emailAddress))").execute()
for f in results.get('files', []):
if f['id'] in fi:
print('duplicate file', f)
else:
fi[f['id']] = f
if f['mimeType'] == 'application/vnd.google-apps.folder':
fId2fo[f['id']] = []
print('next', len(fi), len(fId2fo))
next = results.get('nextPageToken')
if next == None:
break
nopa = []
for f in fi.values():
if 'parents' not in f or len(f['parents']) == 0:
nopa.append(f['id'])
# print('orphan has no paren', f)
elif len(f['parents']) != 1:
err('not 1 parents', f)
else:
p = f['parents'][0]
if p not in fi:
err('parent missing', f)
elif fi[p]['mimeType'] != 'application/vnd.google-apps.folder':
err('parent of', f , 'is not folder', fi[p])
fId2fo[p].append(f['id'])
del nopa[0:1]
nopa.sort(key=lambda i: fi[i]['name'])
nopa[0:0] = [root['id']]
allAdd(nopa, fi, fId2fo)
foPrint(nopa, 0)
def allAdd(a, fi, fo):
for i in a:
fId2fi[i] = fi[i]
for i in a:
if i in fo:
fo[i].sort(key=lambda k: fi[k]['name'])
allAdd(fo[i], fi, fo)
def foPrint(fo, lv):
global fId2fi, fId2fo
for f in fo:
fi = fId2fi[f]
print(' ' * lv, fi['name'], fi['mimeType'])
if fi['mimeType'] == 'application/vnd.google-apps.folder':
foPrint(fId2fo[fi['id']], lv+1)
def treePrint(td):
seq=0
f2s = dict()
for id, f in td.items():
seq += 1
if f['mimeType'] == 'application/vnd.google-apps.folder':
f2s[id] = seq
if 'parents' not in f or len(f['parents']) == 0:
p=-1
elif len(f['parents']) == 1:
p = f2s[f['parents'][0]]
else:
err('not 1 parents', f)
if 'owners' not in f or len(f['owners']) < 1 :
o = ''
elif len(f['owners']) == 1 :
o = f['owners'][0]['emailAddress']
else:
o = '???selever users??? ' + ', '.join([ o['emailAddress'] for o in f['owners']])
print('{0:5d} {1:5d}'.format(seq, p), f['name'], f['mimeType'], f['id'], f['modifiedTime'], o)
def chown(fold):
global srvDrive, chownFlds
print('get', dUser := srvDrive.about().get(fields='user/emailAddress').execute())
print('fold', fo := srvDrive.files().get(fileId=fold,fields=chownFlds).execute())
print('my user', dUser['user']['emailAddress'], 'folder', fo['name'], 'owners', fo['owners'][0]['emailAddress'])
chown3(dUser['user']['emailAddress'], fo['owners'][0]['emailAddress'], fo)
def chown3(ownO, ownN, fold):
global srvDrive, chownFlds
print('chown3', ownO, '==>', ownN, 'in', fold)
fls = []
next = None
while True:
res = srvDrive.files().list(
pageSize=2, pageToken=next, fields="nextPageToken, files(" + chownFlds + ")"
, q="'" + fold['id'] + "' in parents and ('" + ownO + "' in owners or mimeType = 'application/vnd.google-apps.folder')").execute()
fls += res.get('files')
next = res.get('nextPageToken')
if next == None:
break
print('list got', [ f['name'] for f in fls])
for f in fls:
if f['owners'][0]['emailAddress'] == ownO :
print('f', f)
prms = srvDrive.permissions().list(fileId=f['id'], fields='*').execute()['permissions']
print('prms', prms)
pN = [p for p in prms if p['emailAddress'] == ownN]
print('pN ***', len(pN), pN)
res = srvDrive.permissions().update(fileId=f['id'], permissionId=pN[0]['id'], transferOwnership=True, body={'role': 'owner'}).execute()
print(res)
print('file now', srvDrive.files().get(fileId=f['id'],fields=chownFlds).execute())
for f in fls:
if f['mimeType'] == 'application/vnd.google-apps.folder':
chown3(ownO, ownN, f)
def mainOld():
global srvDrive, fId2fi
srvDrive = build('drive', 'v3', credentials=credentials())
driveInfo()
# print('get', srvDrive.about().get(fields='*').execute())
#print('root', srvDrive.files().get(fileId='root',fields='*').execute())
fo2csv('root', 'ffid.csv', 'root')
exit()
# testDrive(srvDrive)
# treeDictAdd(srvDrive.files().get(fileId='root',fields='name,kind,mimeType,id,parents').execute())
allDict()
#sys.stdout = open('out.txt', 'w')
treePrint(fId2fi)
chown('1tskVV0t5SGgLCGYSe39hnuJiNL01-B4h') #testWK
# chown('1SGWizH84Yn5vgUc-b5Cc2xOcJd-KpVHA') #spWal
#err('error in code want to exit', 3)
import argparse
def main():
global srvDrive
parser = argparse.ArgumentParser(description="ffId.py: google drive files folders Id's: list print to ffId.csv")
parser.add_argument('cert', help='prefix for certificate. hint a=admin@spWallisellen.ch f=fiwiko@wlkl.ch w=wa@wlkl.ch')
parser.add_argument('fun', nargs='?', default='l', help='function to perform')
# parser.print_help()
# print('after print_help')
print(f"{(args := parser.parse_args())=}")
print(f"{args.cert=} {args.fun=}")
srvDrive = build('drive', 'v3', credentials=credentials(args.cert))
driveInfo()
if args.fun == 'l':
fo2csv('root', 'ffId.csv', 'root')
else:
err('bad fun:', args.fun)
if __name__ == '__main__':
main()