From d9ca2f03dc3258d66eeebc407fb45011111dab1d Mon Sep 17 00:00:00 2001 From: nathan-moore-97 Date: Fri, 29 Mar 2024 14:36:48 -0400 Subject: [PATCH 1/2] Adding a new endpoint to list all vendor response object IDs and another to download a JSON resource given an object id --- gdrive/drive_client.py | 54 +++++++++++++++++++++++++++++++++++++++++- gdrive/export_api.py | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/gdrive/drive_client.py b/gdrive/drive_client.py index d148e2b..8011226 100644 --- a/gdrive/drive_client.py +++ b/gdrive/drive_client.py @@ -1,10 +1,12 @@ import io import logging +import json import mimetypes +import pprint from typing import List from google.oauth2 import service_account -from googleapiclient.discovery import build +from googleapiclient.discovery import build, mimetypes from googleapiclient.http import MediaIoBaseUpload from gdrive import settings, error @@ -17,6 +19,8 @@ service = build("drive", "v3", credentials=creds) +DIRECTORY_MIME_TYPE = "application/vnd.google-apps.folder" + def init(): drive = drives_list() @@ -174,9 +178,57 @@ def get_files(filename: str) -> List: return results["files"] +def get_files_by_drive_id(filename: str, drive_id: str): + """ + Get list of files by filename + """ + + results = ( + service.files() + .list( + q=f"name = '{filename}'", + corpora="drive", + driveId=drive_id, + includeTeamDriveItems=True, + supportsTeamDrives=True, + ) + .execute() + ) + + return results["files"] + + +def get_files_in_folder(id: str) -> List: + """ + Get list of files within a folder by folder ID + """ + files = [] + page_token = None + while True: + results = ( + service.files() + .list( + q=f"'{id}' in parents and trashed=false", + supportsAllDrives=True, + includeItemsFromAllDrives=True, + pageToken=page_token, + ) + .execute() + ) + files.extend(results.get("files", [])) + page_token = results.get("nextPageToken") + if not page_token: + break + return files + + def delete_file(id: str) -> None: """ Delete file by id """ service.files().delete(fileId=id, supportsAllDrives=True).execute() + + +def export_to_json(id: str) -> str: + return json.loads(service.files().get_media(fileId=id).execute()) diff --git a/gdrive/export_api.py b/gdrive/export_api.py index 6c9ddd3..cec08e8 100644 --- a/gdrive/export_api.py +++ b/gdrive/export_api.py @@ -153,3 +153,47 @@ async def find(find: FindModel): ) export_data = export_client.find(responseId, find.field, find.values, result) return export_data + + +# ------------------------------- Archive API -------------------------------------- + + +class InteractionModel(BaseModel): + interactionId: str + driveId: str + + +@router.post("/export/vendor-response-list") +async def get_vendor_responses(request: InteractionModel): + """ + Returns a list of Google Drive object IDs that contain the + vendor responses for this particular interaction + """ + interaction_folders = drive_client.get_files_by_drive_id( + filename=request.interactionId, drive_id=request.driveId + ) + vendor_file_ids = [] + for dir in interaction_folders: + files = drive_client.get_files_in_folder(id=dir["id"]) + for file in files: + if file["mimeType"] == "application/json" and ( + "analytics" not in file["name"] + ): + vendor_file_ids.append(file["id"]) + + return responses.JSONResponse(status_code=202, content=vendor_file_ids) + + +class JsonResourceModel(BaseModel): + resourceId: str + + +@router.post("/export/resource") +async def export_resource(request: JsonResourceModel): + try: + result = drive_client.export_to_json(request.resourceId) + except UnicodeDecodeError as e: + return responses.JSONResponse( + status_code=400, content="Resource could not be JSON encoded" + ) + return responses.JSONResponse(status_code=202, content=result) From 215b60f092ac834ed0cd8fac28ecc63e5c4452f3 Mon Sep 17 00:00:00 2001 From: nathan-moore-97 Date: Tue, 2 Apr 2024 14:48:34 -0400 Subject: [PATCH 2/2] CR Comments --- gdrive/drive_client.py | 9 +++------ gdrive/export_api.py | 33 ++++++++++++++------------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/gdrive/drive_client.py b/gdrive/drive_client.py index 8011226..dd687c1 100644 --- a/gdrive/drive_client.py +++ b/gdrive/drive_client.py @@ -2,11 +2,10 @@ import logging import json import mimetypes -import pprint from typing import List from google.oauth2 import service_account -from googleapiclient.discovery import build, mimetypes +from googleapiclient.discovery import build from googleapiclient.http import MediaIoBaseUpload from gdrive import settings, error @@ -19,8 +18,6 @@ service = build("drive", "v3", credentials=creds) -DIRECTORY_MIME_TYPE = "application/vnd.google-apps.folder" - def init(): drive = drives_list() @@ -230,5 +227,5 @@ def delete_file(id: str) -> None: service.files().delete(fileId=id, supportsAllDrives=True).execute() -def export_to_json(id: str) -> str: - return json.loads(service.files().get_media(fileId=id).execute()) +def export(id: str) -> any: + return service.files().get_media(fileId=id).execute() diff --git a/gdrive/export_api.py b/gdrive/export_api.py index cec08e8..5b08378 100644 --- a/gdrive/export_api.py +++ b/gdrive/export_api.py @@ -156,44 +156,39 @@ async def find(find: FindModel): # ------------------------------- Archive API -------------------------------------- - - class InteractionModel(BaseModel): interactionId: str driveId: str -@router.post("/export/vendor-response-list") -async def get_vendor_responses(request: InteractionModel): +@router.post("/export/interaction-files") +async def get_files_by_id(request: InteractionModel): """ Returns a list of Google Drive object IDs that contain the vendor responses for this particular interaction """ interaction_folders = drive_client.get_files_by_drive_id( - filename=request.interactionId, drive_id=request.driveId + filename=request.interactionId, drive_id=settings.ROOT_DIRECTORY ) + vendor_file_ids = [] for dir in interaction_folders: files = drive_client.get_files_in_folder(id=dir["id"]) for file in files: - if file["mimeType"] == "application/json" and ( - "analytics" not in file["name"] - ): - vendor_file_ids.append(file["id"]) + vendor_file_ids.append(file) - return responses.JSONResponse(status_code=202, content=vendor_file_ids) + return responses.JSONResponse( + status_code=202, + content={"interaction": request.interactionId, "data": vendor_file_ids}, + ) -class JsonResourceModel(BaseModel): +class ResourceModel(BaseModel): resourceId: str @router.post("/export/resource") -async def export_resource(request: JsonResourceModel): - try: - result = drive_client.export_to_json(request.resourceId) - except UnicodeDecodeError as e: - return responses.JSONResponse( - status_code=400, content="Resource could not be JSON encoded" - ) - return responses.JSONResponse(status_code=202, content=result) +async def export_resource(request: ResourceModel): + return responses.Response( + status_code=202, content=drive_client.export(request.resourceId) + )