Beispiel #1
0
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="",
    )
Beispiel #2
0
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
Beispiel #3
0
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!"
Beispiel #4
0
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!"
Beispiel #5
0
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!"
Beispiel #6
0
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!"
Beispiel #7
0
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)
Beispiel #8
0
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)
Beispiel #9
0
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!"
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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!"
Beispiel #13
0
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")
Beispiel #14
0
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"
    )
Beispiel #15
0
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",
    )
Beispiel #16
0
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)