def request( resource_id: drive_api.ResourceID, email: str, *, email_message: Optional[str] = None, send_email: bool = False, transfer_ownership: bool = False, drive_service: Optional[discovery.Resource] = None, ) -> http.HttpRequest: """ Generate request to share specific resource with user. Email message can have multiple lines. """ if drive_service is None: drive_service = drive_api.build_service() user_permission = { "type": "user", "role": "writer" if not transfer_ownership else "owner", "emailAddress": email, } if transfer_ownership: send_email = True # API requires this return drive_service.permissions().create( fileId=resource_id, body=user_permission, emailMessage=email_message, sendNotificationEmail=send_email, transferOwnership=transfer_ownership, fields="", )
def resource( resource_name: str, *, parent_folder_id: drive_api.ResourceID, mime_type: Optional[str] = None, exact_match: bool = True, drive_service: Optional[discovery.Resource] = None, ) -> Optional[drive_api.ResourceID]: """ Helper for finding files and folders """ if drive_service is None: drive_service = drive_api.build_service() query = f"'{parent_folder_id}' in parents" query += (f" and name='{resource_name}'" if exact_match else f" and name contains '{resource_name}'") if mime_type: query += f" and mimeType='application/vnd.google-apps.{mime_type}'" results = (drive_service.files().list( q=query, pageSize=2, fields="nextPageToken, files(id)").execute()) files = results.get("files", []) if len(files) != 1: # empty or ambiguous results -> failure return None resource_id: drive_api.ResourceID = files[0]["id"] return resource_id
def api_rename_file(): payload = flask.request.get_json() drive_service = drive_api.build_service() arguments = generate_batch_arguments(payload=payload, parse_func=parse_rename, drive_service=drive_service) rename.batch(arguments=arguments, drive_service=drive_service) return "Rename file worked!"
def api_move_folder(): payload = flask.request.get_json() drive_service = drive_api.build_service() arguments = generate_batch_arguments(payload=payload, parse_func=parse_move, drive_service=drive_service) move.batch(arguments=arguments, drive_service=drive_service) return "Move folder worked!"
def api_remove_file(): payload = flask.request.get_json() drive_service = drive_api.build_service() # TODO: add mime type arguments = generate_batch_arguments(payload=payload, parse_func=parse_remove, drive_service=drive_service) remove.batch(arguments=arguments, drive_service=drive_service) return "Remove file worked!"
def api_create_folder(): payload = flask.request.get_json() drive_service = drive_api.build_service() arguments = generate_batch_arguments(payload=payload, parse_func=parse_create, drive_service=drive_service) create.batch_folder(arguments=arguments, drive_service=drive_service, include_output=False) return "Create folder worked!"
def request( resource_id: drive_api.ResourceID, *, drive_service: Optional[discovery.Resource] = None, ) -> http.HttpRequest: """ Generate request to remove specific resource. """ if drive_service is None: drive_service = drive_api.build_service() return drive_service.files().delete(fileId=resource_id)
def request( resource_id: drive_api.ResourceID, new_name: str, *, drive_service: Optional[discovery.Resource] = None, ) -> http.HttpRequest: """ Generate request to rename specific resource. """ if drive_service is None: drive_service = drive_api.build_service() file_metadata = {"name": new_name} return drive_service.files().update(fileId=resource_id, body=file_metadata)
def api_create_file(): payload = flask.request.get_json() drive_service = drive_api.build_service() arguments = generate_batch_arguments(payload=payload, parse_func=parse_create, drive_service=drive_service) create.batch( arguments=arguments, include_output=False, uniform_mime_type=parse_mime_type(payload), drive_service=drive_service, ) return "Create file worked!"
def name( resource_id: drive_api.ResourceID, *, drive_service: Optional[discovery.Resource] = None, ) -> str: """ Find the original name of the resource. """ if drive_service is None: drive_service = drive_api.build_service() result = drive_service.files().get(fileId=resource_id, fields="name").execute() name: str = result["name"] return name
def parent_folder_list( resource_id: drive_api.ResourceID, *, drive_service: Optional[discovery.Resource] = None, ) -> List[drive_api.ResourceID]: """ Find all parent folder IDs for resource. """ if drive_service is None: drive_service = drive_api.build_service() result = drive_service.files().get(fileId=resource_id, fields="parents").execute() parent_ids: List[drive_api.ResourceID] = result["parents"] return parent_ids
def api_copy_file(): payload = flask.request.get_json() drive_service = drive_api.build_service() global_source_resource_id = parse_global_source( payload, drive_service=drive_service) arguments = generate_batch_arguments( payload=payload, parse_func=parse_copy, drive_service=drive_service, original_resource_id=global_source_resource_id, ) copy.batch(arguments=arguments, drive_service=drive_service, include_output=False) return "Copy file worked!"
def request( name: str, *, mime_type: str, parent_folder_id: drive_api.ResourceID, drive_service: Optional[discovery.Resource] = None, ) -> http.HttpRequest: """ Generate request to create new resource. """ if drive_service is None: drive_service = drive_api.build_service() file_metadata = { "name": name, "mimeType": f"application/vnd.google-apps.{mime_type}", "parents": [parent_folder_id], } return drive_service.files().create(body=file_metadata, fields="id")
def request( *, origin_file_id: drive_api.ResourceID, new_name: str, target_parent_folder_id: drive_api.ResourceID, drive_service: Optional[discovery.Resource] = None, ) -> http.HttpRequest: """ Generate request to copy the file into targets. Should maintain permissions and file metadata. """ if drive_service is None: drive_service = drive_api.build_service() file_metadata = {"name": new_name, "parents": [target_parent_folder_id]} return drive_service.files().copy( fileId=origin_file_id, body=file_metadata, fields="id" )
def request( *, origin_resource_id: drive_api.ResourceID, target_folder_id: drive_api.ResourceID, drive_service: Optional[discovery.Resource] = None, ) -> http.HttpRequest: """ Generate request to move specific resource. """ if drive_service is None: drive_service = drive_api.build_service() previous_parents = find.parent_folder_list(resource_id=origin_resource_id) previous_parents_formatted = ", ".join(previous_parents) return drive_service.files().update( fileId=origin_resource_id, addParents=target_folder_id, removeParents=previous_parents_formatted, fields="id, parents", )
def linked_sheet_and_form( *, origin_sheet_id: drive_api.ResourceID, origin_form_id: drive_api.ResourceID, origin_parent_folder_id: Optional[drive_api.ResourceID] = None, new_sheet_name: str, new_form_name: str, target_parent_folder_id: drive_api.ResourceID, drive_service: Optional[discovery.Resource] = None, initial_form_search_delay: int = 10, timeout: int = 45, ) -> SheetAndForm: """ Copy both the spreadsheet and its accompanying form. This is because when you copy a spreadsheet linked to a form, the form will automatically be copied as well. So, this command will find that copied form, rename it, and move to the same parent. Because the form is not created instantly, uses a timeout mechanism to search multiple times. """ if drive_service is None: drive_service = drive_api.build_service() if origin_parent_folder_id is None: origin_parent_folder_id = find.parent_folder(origin_form_id) original_form_name = find.name(origin_form_id) copied_sheet_id = file( origin_file_id=origin_sheet_id, target_parent_folder_id=target_parent_folder_id, new_name=new_sheet_name, drive_service=drive_service, ) def find_copied_form( time_delay: int, total_time_elapsed: int = 0 ) -> drive_api.ResourceID: time.sleep(time_delay) copy_id = find.resource( resource_name=f"Copy of {original_form_name}", parent_folder_id=origin_parent_folder_id, mime_type=mime_types.gform, drive_service=drive_service, ) updated_time_elapsed = total_time_elapsed + time_delay time_remaining = timeout - updated_time_elapsed if copy_id is None: if time_remaining > timeout: raise OSError( "Cannot find the copied form. Check that it was created in Google Drive." ) print( textwrap.dedent( f"""\ Copy of the form {original_form_name} not found yet. Trying again, this time waiting {time_delay*2} seconds. Will timeout in {time_remaining} seconds.""" ) ) return find_copied_form( time_delay * 2, total_time_elapsed=updated_time_elapsed ) return copy_id # use time delay to make sure form created copied_form_id = find_copied_form(initial_form_search_delay) drive_api.batch_command( requests=[ rename.request( resource_id=copied_form_id, new_name=new_form_name, drive_service=drive_service, ), move.request( origin_resource_id=copied_form_id, target_folder_id=target_parent_folder_id, drive_service=drive_service, ), ], drive_service=drive_service, ) return SheetAndForm(sheet=copied_sheet_id, form=copied_form_id)