lib/operations/activity.ex

defmodule GitHub.Activity do
  @moduledoc """
  Provides API endpoints, struct, and type related to activity
  """
  use GitHub.Encoder

  @default_client GitHub.Client

  @type t :: %__MODULE__{
          __info__: map,
          activity_type: String.t(),
          actor: GitHub.User.simple() | nil,
          after: String.t(),
          before: String.t(),
          id: integer,
          node_id: String.t(),
          ref: String.t(),
          timestamp: String.t()
        }

  defstruct [:__info__, :activity_type, :actor, :after, :before, :id, :node_id, :ref, :timestamp]

  @doc false
  @spec __fields__(atom) :: keyword
  def __fields__(type \\ :t)

  def __fields__(:t) do
    [
      activity_type: :string,
      actor: {:nullable, {GitHub.User, :simple}},
      after: :string,
      before: :string,
      id: :integer,
      node_id: :string,
      ref: :string,
      timestamp: :string
    ]
  end

  @doc """
  Check if a repository is starred by the authenticated user

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/starring#check-if-a-repository-is-starred-by-the-authenticated-user)

  """
  @spec check_repo_is_starred_by_authenticated_user(String.t(), String.t(), keyword) ::
          :ok | {:error, GitHub.Error.t()}
  def check_repo_is_starred_by_authenticated_user(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :check_repo_is_starred_by_authenticated_user},
      url: "/user/starred/#{owner}/#{repo}",
      method: :get,
      response: [
        {204, nil},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}},
        {404, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  Delete a repository subscription

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/watching#delete-a-repository-subscription)

  """
  @spec delete_repo_subscription(String.t(), String.t(), keyword) ::
          :ok | {:error, GitHub.Error.t()}
  def delete_repo_subscription(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :delete_repo_subscription},
      url: "/repos/#{owner}/#{repo}/subscription",
      method: :delete,
      response: [{204, nil}],
      opts: opts
    })
  end

  @doc """
  Delete a thread subscription

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#delete-a-thread-subscription)

  """
  @spec delete_thread_subscription(integer, keyword) :: :ok | {:error, GitHub.Error.t()}
  def delete_thread_subscription(thread_id, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [thread_id: thread_id],
      call: {GitHub.Activity, :delete_thread_subscription},
      url: "/notifications/threads/#{thread_id}/subscription",
      method: :delete,
      response: [
        {204, nil},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  Get feeds

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/feeds#get-feeds)

  """
  @spec get_feeds(keyword) :: {:ok, GitHub.Feed.t()} | {:error, GitHub.Error.t()}
  def get_feeds(opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      call: {GitHub.Activity, :get_feeds},
      url: "/feeds",
      method: :get,
      response: [{200, {GitHub.Feed, :t}}],
      opts: opts
    })
  end

  @doc """
  Get a repository subscription

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/watching#get-a-repository-subscription)

  """
  @spec get_repo_subscription(String.t(), String.t(), keyword) ::
          {:ok, GitHub.Repository.Subscription.t()} | {:error, GitHub.Error.t()}
  def get_repo_subscription(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :get_repo_subscription},
      url: "/repos/#{owner}/#{repo}/subscription",
      method: :get,
      response: [
        {200, {GitHub.Repository.Subscription, :t}},
        {403, {GitHub.BasicError, :t}},
        {404, nil}
      ],
      opts: opts
    })
  end

  @doc """
  Get a thread

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#get-a-thread)

  """
  @spec get_thread(integer, keyword) :: {:ok, GitHub.Thread.t()} | {:error, GitHub.Error.t()}
  def get_thread(thread_id, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [thread_id: thread_id],
      call: {GitHub.Activity, :get_thread},
      url: "/notifications/threads/#{thread_id}",
      method: :get,
      response: [
        {200, {GitHub.Thread, :t}},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  Get a thread subscription for the authenticated user

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#get-a-thread-subscription-for-the-authenticated-user)

  """
  @spec get_thread_subscription_for_authenticated_user(integer, keyword) ::
          {:ok, GitHub.ThreadSubscription.t()} | {:error, GitHub.Error.t()}
  def get_thread_subscription_for_authenticated_user(thread_id, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [thread_id: thread_id],
      call: {GitHub.Activity, :get_thread_subscription_for_authenticated_user},
      url: "/notifications/threads/#{thread_id}/subscription",
      method: :get,
      response: [
        {200, {GitHub.ThreadSubscription, :t}},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  List events for the authenticated user

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-events-for-the-authenticated-user)

  """
  @spec list_events_for_authenticated_user(String.t(), keyword) ::
          {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_events_for_authenticated_user(username, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [username: username],
      call: {GitHub.Activity, :list_events_for_authenticated_user},
      url: "/users/#{username}/events",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Event, :t}}}],
      opts: opts
    })
  end

  @doc """
  List notifications for the authenticated user

  ## Options

    * `all` (boolean): If `true`, show notifications marked as read.
    * `participating` (boolean): If `true`, only shows notifications in which the user is directly participating or mentioned.
    * `since` (String.t()): Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.
    * `before` (String.t()): Only show notifications updated before the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.
    * `page` (integer): Page number of the results to fetch.
    * `per_page` (integer): The number of results per page (max 50).

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user)

  """
  @spec list_notifications_for_authenticated_user(keyword) ::
          {:ok, [GitHub.Thread.t()]} | {:error, GitHub.Error.t()}
  def list_notifications_for_authenticated_user(opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:all, :before, :page, :participating, :per_page, :since])

    client.request(%{
      call: {GitHub.Activity, :list_notifications_for_authenticated_user},
      url: "/notifications",
      method: :get,
      query: query,
      response: [
        {200, {:array, {GitHub.Thread, :t}}},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}},
        {422, {GitHub.ValidationError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  List organization events for the authenticated user

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-organization-events-for-the-authenticated-user)

  """
  @spec list_org_events_for_authenticated_user(String.t(), String.t(), keyword) ::
          {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_org_events_for_authenticated_user(username, org, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [username: username, org: org],
      call: {GitHub.Activity, :list_org_events_for_authenticated_user},
      url: "/users/#{username}/events/orgs/#{org}",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Event, :t}}}],
      opts: opts
    })
  end

  @doc """
  List public events

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-public-events)

  """
  @spec list_public_events(keyword) :: {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_public_events(opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      call: {GitHub.Activity, :list_public_events},
      url: "/events",
      method: :get,
      query: query,
      response: [
        {200, {:array, {GitHub.Event, :t}}},
        {304, nil},
        {403, {GitHub.BasicError, :t}},
        {503, :map}
      ],
      opts: opts
    })
  end

  @doc """
  List public events for a network of repositories

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-public-events-for-a-network-of-repositories)

  """
  @spec list_public_events_for_repo_network(String.t(), String.t(), keyword) ::
          {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_public_events_for_repo_network(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :list_public_events_for_repo_network},
      url: "/networks/#{owner}/#{repo}/events",
      method: :get,
      query: query,
      response: [
        {200, {:array, {GitHub.Event, :t}}},
        {301, {GitHub.BasicError, :t}},
        {304, nil},
        {403, {GitHub.BasicError, :t}},
        {404, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  List public events for a user

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-public-events-for-a-user)

  """
  @spec list_public_events_for_user(String.t(), keyword) ::
          {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_public_events_for_user(username, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [username: username],
      call: {GitHub.Activity, :list_public_events_for_user},
      url: "/users/#{username}/events/public",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Event, :t}}}],
      opts: opts
    })
  end

  @doc """
  List public organization events

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-public-organization-events)

  """
  @spec list_public_org_events(String.t(), keyword) ::
          {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_public_org_events(org, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [org: org],
      call: {GitHub.Activity, :list_public_org_events},
      url: "/orgs/#{org}/events",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Event, :t}}}],
      opts: opts
    })
  end

  @doc """
  List events received by the authenticated user

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-events-received-by-the-authenticated-user)

  """
  @spec list_received_events_for_user(String.t(), keyword) ::
          {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_received_events_for_user(username, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [username: username],
      call: {GitHub.Activity, :list_received_events_for_user},
      url: "/users/#{username}/received_events",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Event, :t}}}],
      opts: opts
    })
  end

  @doc """
  List public events received by a user

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-public-events-received-by-a-user)

  """
  @spec list_received_public_events_for_user(String.t(), keyword) ::
          {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_received_public_events_for_user(username, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [username: username],
      call: {GitHub.Activity, :list_received_public_events_for_user},
      url: "/users/#{username}/received_events/public",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Event, :t}}}],
      opts: opts
    })
  end

  @doc """
  List repository events

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/events#list-repository-events)

  """
  @spec list_repo_events(String.t(), String.t(), keyword) ::
          {:ok, [GitHub.Event.t()]} | {:error, GitHub.Error.t()}
  def list_repo_events(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :list_repo_events},
      url: "/repos/#{owner}/#{repo}/events",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Event, :t}}}],
      opts: opts
    })
  end

  @doc """
  List repository notifications for the authenticated user

  ## Options

    * `all` (boolean): If `true`, show notifications marked as read.
    * `participating` (boolean): If `true`, only shows notifications in which the user is directly participating or mentioned.
    * `since` (String.t()): Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.
    * `before` (String.t()): Only show notifications updated before the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.
    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#list-repository-notifications-for-the-authenticated-user)

  """
  @spec list_repo_notifications_for_authenticated_user(String.t(), String.t(), keyword) ::
          {:ok, [GitHub.Thread.t()]} | {:error, GitHub.Error.t()}
  def list_repo_notifications_for_authenticated_user(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:all, :before, :page, :participating, :per_page, :since])

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :list_repo_notifications_for_authenticated_user},
      url: "/repos/#{owner}/#{repo}/notifications",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Thread, :t}}}],
      opts: opts
    })
  end

  @doc """
  List repositories starred by the authenticated user

  ## Options

    * `sort` (String.t()): The property to sort the results by. `created` means when the repository was starred. `updated` means when the repository was last pushed to.
    * `direction` (String.t()): The direction to sort the results by.
    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/starring#list-repositories-starred-by-the-authenticated-user)

  """
  @spec list_repos_starred_by_authenticated_user(keyword) ::
          {:ok, [GitHub.Repository.t()]} | {:error, GitHub.Error.t()}
  def list_repos_starred_by_authenticated_user(opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:direction, :page, :per_page, :sort])

    client.request(%{
      call: {GitHub.Activity, :list_repos_starred_by_authenticated_user},
      url: "/user/starred",
      method: :get,
      query: query,
      response: [
        {200, {:array, {GitHub.Repository, :t}}},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  List repositories starred by a user

  ## Options

    * `sort` (String.t()): The property to sort the results by. `created` means when the repository was starred. `updated` means when the repository was last pushed to.
    * `direction` (String.t()): The direction to sort the results by.
    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/starring#list-repositories-starred-by-a-user)

  """
  @spec list_repos_starred_by_user(String.t(), keyword) ::
          {:ok, [GitHub.Repository.t()] | [GitHub.StarredRepository.t()]}
          | {:error, GitHub.Error.t()}
  def list_repos_starred_by_user(username, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:direction, :page, :per_page, :sort])

    client.request(%{
      args: [username: username],
      call: {GitHub.Activity, :list_repos_starred_by_user},
      url: "/users/#{username}/starred",
      method: :get,
      query: query,
      response: [
        {200, {:union, array: {GitHub.StarredRepository, :t}, array: {GitHub.Repository, :t}}}
      ],
      opts: opts
    })
  end

  @doc """
  List repositories watched by a user

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/watching#list-repositories-watched-by-a-user)

  """
  @spec list_repos_watched_by_user(String.t(), keyword) ::
          {:ok, [GitHub.Repository.minimal()]} | {:error, GitHub.Error.t()}
  def list_repos_watched_by_user(username, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [username: username],
      call: {GitHub.Activity, :list_repos_watched_by_user},
      url: "/users/#{username}/subscriptions",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.Repository, :minimal}}}],
      opts: opts
    })
  end

  @doc """
  List stargazers

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/starring#list-stargazers)

  """
  @spec list_stargazers_for_repo(String.t(), String.t(), keyword) ::
          {:ok, [GitHub.Stargazer.t()] | [GitHub.User.simple()]} | {:error, GitHub.Error.t()}
  def list_stargazers_for_repo(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :list_stargazers_for_repo},
      url: "/repos/#{owner}/#{repo}/stargazers",
      method: :get,
      query: query,
      response: [
        {200, {:union, array: {GitHub.User, :simple}, array: {GitHub.Stargazer, :t}}},
        {422, {GitHub.ValidationError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  List repositories watched by the authenticated user

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/watching#list-repositories-watched-by-the-authenticated-user)

  """
  @spec list_watched_repos_for_authenticated_user(keyword) ::
          {:ok, [GitHub.Repository.minimal()]} | {:error, GitHub.Error.t()}
  def list_watched_repos_for_authenticated_user(opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      call: {GitHub.Activity, :list_watched_repos_for_authenticated_user},
      url: "/user/subscriptions",
      method: :get,
      query: query,
      response: [
        {200, {:array, {GitHub.Repository, :minimal}}},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  List watchers

  ## Options

    * `per_page` (integer): The number of results per page (max 100).
    * `page` (integer): Page number of the results to fetch.

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/watching#list-watchers)

  """
  @spec list_watchers_for_repo(String.t(), String.t(), keyword) ::
          {:ok, [GitHub.User.simple()]} | {:error, GitHub.Error.t()}
  def list_watchers_for_repo(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client
    query = Keyword.take(opts, [:page, :per_page])

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :list_watchers_for_repo},
      url: "/repos/#{owner}/#{repo}/subscribers",
      method: :get,
      query: query,
      response: [{200, {:array, {GitHub.User, :simple}}}],
      opts: opts
    })
  end

  @doc """
  Mark notifications as read

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#mark-notifications-as-read)

  """
  @spec mark_notifications_as_read(map, keyword) :: {:ok, map} | {:error, GitHub.Error.t()}
  def mark_notifications_as_read(body, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [body: body],
      call: {GitHub.Activity, :mark_notifications_as_read},
      url: "/notifications",
      body: body,
      method: :put,
      request: [{"application/json", :map}],
      response: [
        {202, :map},
        {205, nil},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  Mark repository notifications as read

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#mark-repository-notifications-as-read)

  """
  @spec mark_repo_notifications_as_read(String.t(), String.t(), map, keyword) ::
          {:ok, map} | {:error, GitHub.Error.t()}
  def mark_repo_notifications_as_read(owner, repo, body, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [owner: owner, repo: repo, body: body],
      call: {GitHub.Activity, :mark_repo_notifications_as_read},
      url: "/repos/#{owner}/#{repo}/notifications",
      body: body,
      method: :put,
      request: [{"application/json", :map}],
      response: [{202, :map}, {205, nil}],
      opts: opts
    })
  end

  @doc """
  Mark a thread as read

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#mark-a-thread-as-read)

  """
  @spec mark_thread_as_read(integer, keyword) :: :ok | {:error, GitHub.Error.t()}
  def mark_thread_as_read(thread_id, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [thread_id: thread_id],
      call: {GitHub.Activity, :mark_thread_as_read},
      url: "/notifications/threads/#{thread_id}",
      method: :patch,
      response: [{205, nil}, {304, nil}, {403, {GitHub.BasicError, :t}}],
      opts: opts
    })
  end

  @doc """
  Set a repository subscription

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/watching#set-a-repository-subscription)

  """
  @spec set_repo_subscription(String.t(), String.t(), map, keyword) ::
          {:ok, GitHub.Repository.Subscription.t()} | {:error, GitHub.Error.t()}
  def set_repo_subscription(owner, repo, body, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [owner: owner, repo: repo, body: body],
      call: {GitHub.Activity, :set_repo_subscription},
      url: "/repos/#{owner}/#{repo}/subscription",
      body: body,
      method: :put,
      request: [{"application/json", :map}],
      response: [{200, {GitHub.Repository.Subscription, :t}}],
      opts: opts
    })
  end

  @doc """
  Set a thread subscription

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/notifications#set-a-thread-subscription)

  """
  @spec set_thread_subscription(integer, map, keyword) ::
          {:ok, GitHub.ThreadSubscription.t()} | {:error, GitHub.Error.t()}
  def set_thread_subscription(thread_id, body, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [thread_id: thread_id, body: body],
      call: {GitHub.Activity, :set_thread_subscription},
      url: "/notifications/threads/#{thread_id}/subscription",
      body: body,
      method: :put,
      request: [{"application/json", :map}],
      response: [
        {200, {GitHub.ThreadSubscription, :t}},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  Star a repository for the authenticated user

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/starring#star-a-repository-for-the-authenticated-user)

  """
  @spec star_repo_for_authenticated_user(String.t(), String.t(), keyword) ::
          :ok | {:error, GitHub.Error.t()}
  def star_repo_for_authenticated_user(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :star_repo_for_authenticated_user},
      url: "/user/starred/#{owner}/#{repo}",
      method: :put,
      response: [
        {204, nil},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}},
        {404, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end

  @doc """
  Unstar a repository for the authenticated user

  ## Resources

    * [API method documentation](https://docs.github.com/rest/activity/starring#unstar-a-repository-for-the-authenticated-user)

  """
  @spec unstar_repo_for_authenticated_user(String.t(), String.t(), keyword) ::
          :ok | {:error, GitHub.Error.t()}
  def unstar_repo_for_authenticated_user(owner, repo, opts \\ []) do
    client = opts[:client] || @default_client

    client.request(%{
      args: [owner: owner, repo: repo],
      call: {GitHub.Activity, :unstar_repo_for_authenticated_user},
      url: "/user/starred/#{owner}/#{repo}",
      method: :delete,
      response: [
        {204, nil},
        {304, nil},
        {401, {GitHub.BasicError, :t}},
        {403, {GitHub.BasicError, :t}},
        {404, {GitHub.BasicError, :t}}
      ],
      opts: opts
    })
  end
end