Packages

Elixir client for the Microsoft Graph API

Current section

Files

Jump to
keen_microsoft_graphapi lib graph_api resources files.ex
Raw

lib/graph_api/resources/files.ex

defmodule GraphApi.Files do
@moduledoc """
Operations on OneDrive/SharePoint files (`/drives`, `/drive/items`, etc.).
## Examples
{:ok, drive} = GraphApi.Files.get_drive("user-id")
{:ok, %{"value" => items}} = GraphApi.Files.list_root_children("drive-id")
{:ok, content} = GraphApi.Files.download_content("drive-id", "item-id")
"""
alias GraphApi.Batch
alias GraphApi.Delta
alias GraphApi.Resource
alias GraphApi.Response
@doc """
Gets a user's default drive.
"""
@spec get_drive(String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def get_drive(user_id, opts \\ []), do: Resource.execute(get_drive_query(user_id, opts), opts)
@doc "Batch query variant of `get_drive/2`."
@spec get_drive_query(String.t(), keyword()) :: Batch.Request.t()
def get_drive_query(user_id, opts \\ []), do: build_query("GET", "/users/#{user_id}/drive", nil, opts)
@doc """
Lists children of the root folder in a drive.
"""
@spec list_root_children(String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def list_root_children(drive_id, opts \\ []), do: Resource.execute(list_root_children_query(drive_id, opts), opts)
@doc "Batch query variant of `list_root_children/2`."
@spec list_root_children_query(String.t(), keyword()) :: Batch.Request.t()
def list_root_children_query(drive_id, opts \\ []), do: build_query("GET", "/drives/#{drive_id}/root/children", nil, opts)
@doc """
Lists children of a specific item in a drive.
"""
@spec list_children(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def list_children(drive_id, item_id, opts \\ []), do: Resource.execute(list_children_query(drive_id, item_id, opts), opts)
@doc "Batch query variant of `list_children/3`."
@spec list_children_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def list_children_query(drive_id, item_id, opts \\ []) do
build_query("GET", "/drives/#{drive_id}/items/#{item_id}/children", nil, opts)
end
@doc """
Gets a drive item by ID.
"""
@spec get_item(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def get_item(drive_id, item_id, opts \\ []), do: Resource.execute(get_item_query(drive_id, item_id, opts), opts)
@doc "Batch query variant of `get_item/3`."
@spec get_item_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def get_item_query(drive_id, item_id, opts \\ []) do
build_query("GET", "/drives/#{drive_id}/items/#{item_id}", nil, opts)
end
@doc """
Gets a drive item by path.
The path should be relative to the root (e.g., "Documents/report.docx").
"""
@spec get_item_by_path(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def get_item_by_path(drive_id, path, opts \\ []), do: Resource.execute(get_item_by_path_query(drive_id, path, opts), opts)
@doc "Batch query variant of `get_item_by_path/3`."
@spec get_item_by_path_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def get_item_by_path_query(drive_id, path, opts \\ []) do
encoded_path = URI.encode(path)
build_query("GET", "/drives/#{drive_id}/root:/#{encoded_path}:", nil, opts)
end
@doc """
Downloads the content of a drive item.
Returns `{:ok, binary}` with the raw file content.
"""
@spec download_content(String.t(), String.t(), keyword()) ::
{:ok, binary()} | {:error, term()}
def download_content(drive_id, item_id, opts \\ []) do
client = Resource.resolve_client(opts)
req_opts = [url: "/drives/#{drive_id}/items/#{item_id}/content"]
req_opts = maybe_put_token(req_opts, opts)
client
|> Req.get(req_opts)
|> Response.normalize()
end
@doc "Batch query variant of `download_content/3`."
@spec download_content_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def download_content_query(drive_id, item_id, opts \\ []) do
build_query("GET", "/drives/#{drive_id}/items/#{item_id}/content", nil, opts)
end
@doc """
Uploads a small file (up to 4 MB) to a drive.
For larger files, use `create_upload_session/4`.
"""
@spec upload_small(String.t(), String.t(), binary(), keyword()) ::
{:ok, map()} | {:error, term()}
def upload_small(drive_id, path, content, opts \\ []) do
client = Resource.resolve_client(opts)
encoded_path = URI.encode(path)
req_opts = [
url: "/drives/#{drive_id}/root:/#{encoded_path}:/content",
body: content,
headers: [{"content-type", "application/octet-stream"}]
]
req_opts = maybe_put_token(req_opts, opts)
client
|> Req.put(req_opts)
|> Response.normalize()
end
@doc "Batch query variant of `upload_small/4`."
@spec upload_small_query(String.t(), String.t(), binary(), keyword()) :: Batch.Request.t()
def upload_small_query(drive_id, path, content, opts \\ []) do
encoded_path = URI.encode(path)
{as, opts} = Keyword.pop(opts, :as)
{query, _opts} = Keyword.pop(opts, :query)
%Batch.Request{
method: "PUT",
url: "/drives/#{drive_id}/root:/#{encoded_path}:/content",
body: content,
headers: %{"Content-Type" => "application/octet-stream"},
query: query,
as: as
}
end
@doc """
Creates an upload session for large file uploads (> 4 MB).
Returns the upload URL to use for uploading file chunks.
"""
@spec create_upload_session(String.t(), String.t(), map(), keyword()) ::
{:ok, map()} | {:error, term()}
def create_upload_session(drive_id, path, attrs \\ %{}, opts \\ []) do
Resource.execute(create_upload_session_query(drive_id, path, attrs, opts), opts)
end
@doc "Batch query variant of `create_upload_session/4`."
@spec create_upload_session_query(String.t(), String.t(), map(), keyword()) :: Batch.Request.t()
def create_upload_session_query(drive_id, path, attrs \\ %{}, opts \\ []) do
encoded_path = URI.encode(path)
body = %{"item" => attrs}
build_query("POST", "/drives/#{drive_id}/root:/#{encoded_path}:/createUploadSession", body, opts)
end
# ---------------------------------------------------------------------------
# Drive-level
# ---------------------------------------------------------------------------
@doc """
Lists all drives available to a user.
"""
@spec list_drives(String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def list_drives(user_id, opts \\ []), do: Resource.execute(list_drives_query(user_id, opts), opts)
@doc "Batch query variant of `list_drives/2`."
@spec list_drives_query(String.t(), keyword()) :: Batch.Request.t()
def list_drives_query(user_id, opts \\ []), do: build_query("GET", "/users/#{user_id}/drives", nil, opts)
@doc """
Gets a special folder (e.g., "documents", "photos", "approot") in a drive.
"""
@spec get_special_folder(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def get_special_folder(drive_id, name, opts \\ []), do: Resource.execute(get_special_folder_query(drive_id, name, opts), opts)
@doc "Batch query variant of `get_special_folder/3`."
@spec get_special_folder_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def get_special_folder_query(drive_id, name, opts \\ []) do
build_query("GET", "/drives/#{drive_id}/special/#{name}", nil, opts)
end
@doc """
Searches for items in a drive matching the given query string.
"""
@spec search(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def search(drive_id, query, opts \\ []), do: Resource.execute(search_query(drive_id, query, opts), opts)
@doc "Batch query variant of `search/3`."
@spec search_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def search_query(drive_id, query, opts \\ []) do
encoded_query = URI.encode(query)
build_query("GET", "/drives/#{drive_id}/root/search(q='#{encoded_query}')", nil, opts)
end
# ---------------------------------------------------------------------------
# Item CRUD
# ---------------------------------------------------------------------------
@doc """
Creates a new folder under the given parent item.
"""
@spec create_folder(String.t(), String.t(), map(), keyword()) :: {:ok, map()} | {:error, term()}
def create_folder(drive_id, parent_item_id, attrs, opts \\ []) do
Resource.execute(create_folder_query(drive_id, parent_item_id, attrs, opts), opts)
end
@doc "Batch query variant of `create_folder/4`."
@spec create_folder_query(String.t(), String.t(), map(), keyword()) :: Batch.Request.t()
def create_folder_query(drive_id, parent_item_id, attrs, opts \\ []) do
body = Map.merge(%{"folder" => %{}, "@microsoft.graph.conflictBehavior" => "rename"}, attrs)
build_query("POST", "/drives/#{drive_id}/items/#{parent_item_id}/children", body, opts)
end
@doc """
Updates a drive item's metadata (name, description, etc.).
"""
@spec update_item(String.t(), String.t(), map(), keyword()) :: {:ok, map()} | {:error, term()}
def update_item(drive_id, item_id, attrs, opts \\ []) do
Resource.execute(update_item_query(drive_id, item_id, attrs, opts), opts)
end
@doc "Batch query variant of `update_item/4`."
@spec update_item_query(String.t(), String.t(), map(), keyword()) :: Batch.Request.t()
def update_item_query(drive_id, item_id, attrs, opts \\ []) do
build_query("PATCH", "/drives/#{drive_id}/items/#{item_id}", attrs, opts)
end
@doc """
Deletes a drive item.
"""
@spec delete_item(String.t(), String.t(), keyword()) :: :ok | {:error, term()}
def delete_item(drive_id, item_id, opts \\ []) do
Resource.execute(delete_item_query(drive_id, item_id, opts), opts)
end
@doc "Batch query variant of `delete_item/3`."
@spec delete_item_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def delete_item_query(drive_id, item_id, opts \\ []) do
build_query("DELETE", "/drives/#{drive_id}/items/#{item_id}", nil, opts)
end
@doc """
Copies a drive item to a new location. Returns 202 Accepted with an async monitor URL.
"""
@spec copy_item(String.t(), String.t(), map(), keyword()) :: {:ok, map()} | {:error, term()}
def copy_item(drive_id, item_id, attrs, opts \\ []) do
Resource.execute(copy_item_query(drive_id, item_id, attrs, opts), opts)
end
@doc "Batch query variant of `copy_item/4`."
@spec copy_item_query(String.t(), String.t(), map(), keyword()) :: Batch.Request.t()
def copy_item_query(drive_id, item_id, attrs, opts \\ []) do
build_query("POST", "/drives/#{drive_id}/items/#{item_id}/copy", attrs, opts)
end
# ---------------------------------------------------------------------------
# Permissions
# ---------------------------------------------------------------------------
@doc """
Lists permissions on a drive item.
"""
@spec list_permissions(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def list_permissions(drive_id, item_id, opts \\ []) do
Resource.execute(list_permissions_query(drive_id, item_id, opts), opts)
end
@doc "Batch query variant of `list_permissions/3`."
@spec list_permissions_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def list_permissions_query(drive_id, item_id, opts \\ []) do
build_query("GET", "/drives/#{drive_id}/items/#{item_id}/permissions", nil, opts)
end
@doc """
Creates a sharing link for a drive item.
"""
@spec create_sharing_link(String.t(), String.t(), map(), keyword()) :: {:ok, map()} | {:error, term()}
def create_sharing_link(drive_id, item_id, attrs, opts \\ []) do
Resource.execute(create_sharing_link_query(drive_id, item_id, attrs, opts), opts)
end
@doc "Batch query variant of `create_sharing_link/4`."
@spec create_sharing_link_query(String.t(), String.t(), map(), keyword()) :: Batch.Request.t()
def create_sharing_link_query(drive_id, item_id, attrs, opts \\ []) do
build_query("POST", "/drives/#{drive_id}/items/#{item_id}/createLink", attrs, opts)
end
@doc """
Invites recipients and adds permissions to a drive item.
"""
@spec add_permission(String.t(), String.t(), map(), keyword()) :: {:ok, map()} | {:error, term()}
def add_permission(drive_id, item_id, attrs, opts \\ []) do
Resource.execute(add_permission_query(drive_id, item_id, attrs, opts), opts)
end
@doc "Batch query variant of `add_permission/4`."
@spec add_permission_query(String.t(), String.t(), map(), keyword()) :: Batch.Request.t()
def add_permission_query(drive_id, item_id, attrs, opts \\ []) do
build_query("POST", "/drives/#{drive_id}/items/#{item_id}/invite", attrs, opts)
end
@doc """
Deletes a permission from a drive item.
"""
@spec delete_permission(String.t(), String.t(), String.t(), keyword()) :: :ok | {:error, term()}
def delete_permission(drive_id, item_id, perm_id, opts \\ []) do
Resource.execute(delete_permission_query(drive_id, item_id, perm_id, opts), opts)
end
@doc "Batch query variant of `delete_permission/4`."
@spec delete_permission_query(String.t(), String.t(), String.t(), keyword()) :: Batch.Request.t()
def delete_permission_query(drive_id, item_id, perm_id, opts \\ []) do
build_query("DELETE", "/drives/#{drive_id}/items/#{item_id}/permissions/#{perm_id}", nil, opts)
end
# ---------------------------------------------------------------------------
# Versions & Thumbnails
# ---------------------------------------------------------------------------
@doc """
Lists versions of a drive item.
"""
@spec list_versions(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def list_versions(drive_id, item_id, opts \\ []) do
Resource.execute(list_versions_query(drive_id, item_id, opts), opts)
end
@doc "Batch query variant of `list_versions/3`."
@spec list_versions_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def list_versions_query(drive_id, item_id, opts \\ []) do
build_query("GET", "/drives/#{drive_id}/items/#{item_id}/versions", nil, opts)
end
@doc """
Lists thumbnails for a drive item.
"""
@spec list_thumbnails(String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def list_thumbnails(drive_id, item_id, opts \\ []) do
Resource.execute(list_thumbnails_query(drive_id, item_id, opts), opts)
end
@doc "Batch query variant of `list_thumbnails/3`."
@spec list_thumbnails_query(String.t(), String.t(), keyword()) :: Batch.Request.t()
def list_thumbnails_query(drive_id, item_id, opts \\ []) do
build_query("GET", "/drives/#{drive_id}/items/#{item_id}/thumbnails", nil, opts)
end
# ---------------------------------------------------------------------------
# Shared Items
# ---------------------------------------------------------------------------
@doc """
Gets a shared drive item by its sharing token or encoded sharing URL.
"""
@spec get_shared_item(String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def get_shared_item(share_id, opts \\ []), do: Resource.execute(get_shared_item_query(share_id, opts), opts)
@doc "Batch query variant of `get_shared_item/2`."
@spec get_shared_item_query(String.t(), keyword()) :: Batch.Request.t()
def get_shared_item_query(share_id, opts \\ []), do: build_query("GET", "/shares/#{share_id}/driveItem", nil, opts)
# ---------------------------------------------------------------------------
# Delta
# ---------------------------------------------------------------------------
@doc """
Delta query for a drive's root folder. Returns file/folder changes since the last sync.
"""
@spec drive_delta(String.t(), keyword()) :: {:ok, Delta.delta_page()} | {:error, term()}
def drive_delta(drive_id, opts \\ []), do: Delta.query("/drives/#{drive_id}/root/delta", opts)
@doc "Batch query variant of `drive_delta/2`."
@spec drive_delta_query(String.t(), keyword()) :: Batch.Request.t()
def drive_delta_query(drive_id, opts \\ []), do: build_query("GET", "/drives/#{drive_id}/root/delta", nil, opts)
defp maybe_put_token(req_opts, opts) do
case Keyword.get(opts, :access_token) do
nil -> req_opts
token -> Keyword.put(req_opts, :access_token, token)
end
end
defp build_query(method, url, body, opts) do
{as, opts} = Keyword.pop(opts, :as)
{query, _opts} = Keyword.pop(opts, :query)
%Batch.Request{method: method, url: url, body: body, query: query, as: as}
end
end