7cf9b4e7f8
- spec public functions (skipping controllers, views, live views and components) - use types instead of explanations in docs - remove redundant docs - fix typos
118 lines
3.6 KiB
Elixir
118 lines
3.6 KiB
Elixir
defmodule MusicBrainz.ReleaseSearchResult do
|
|
alias MusicBrainz.ReleaseGroup
|
|
|
|
@enforce_keys [:id, :title, :release_group, :artists, :date, :barcode, :media]
|
|
defstruct [:id, :title, :release_group, :artists, :date, :barcode, :media]
|
|
|
|
@type t :: %__MODULE__{
|
|
id: String.t(),
|
|
title: String.t(),
|
|
release_group: map() | nil,
|
|
artists: String.t(),
|
|
date: String.t() | nil,
|
|
barcode: String.t() | nil,
|
|
media: [map()]
|
|
}
|
|
|
|
@spec from_api_response(map()) :: t()
|
|
def from_api_response(r) do
|
|
%__MODULE__{
|
|
id: r["id"],
|
|
title: r["title"],
|
|
release_group: r["release-group"] && parse_release_group(r["release-group"]),
|
|
artists: Enum.map_join(r["artist-credit"] || [], ", ", fn ac -> ac["artist"]["name"] end),
|
|
date: r["date"],
|
|
barcode: r["barcode"],
|
|
media: parse_media(r["media"])
|
|
}
|
|
end
|
|
|
|
@doc """
|
|
Returns the physical format of a release based on its media.
|
|
|
|
Returns `:multi` when a release contains different format types.
|
|
|
|
## Examples
|
|
|
|
iex> MusicBrainz.ReleaseSearchResult.format(%MusicBrainz.ReleaseSearchResult{
|
|
...> id: "1", title: "T", release_group: nil, artists: "A", date: "2000", barcode: "0",
|
|
...> media: [%{format: "CD", disc_count: 1, track_count: 11}]
|
|
...> })
|
|
:cd
|
|
|
|
iex> MusicBrainz.ReleaseSearchResult.format(%MusicBrainz.ReleaseSearchResult{
|
|
...> id: "1", title: "T", release_group: nil, artists: "A", date: "2000", barcode: "0",
|
|
...> media: [%{format: "12\\" Vinyl", disc_count: 0, track_count: 8}]
|
|
...> })
|
|
:vinyl
|
|
|
|
iex> MusicBrainz.ReleaseSearchResult.format(%MusicBrainz.ReleaseSearchResult{
|
|
...> id: "1", title: "T", release_group: nil, artists: "A", date: "2000", barcode: "0",
|
|
...> media: [
|
|
...> %{format: "CD", disc_count: 1, track_count: 10},
|
|
...> %{format: "CD", disc_count: 1, track_count: 9}
|
|
...> ]
|
|
...> })
|
|
:cd
|
|
|
|
iex> MusicBrainz.ReleaseSearchResult.format(%MusicBrainz.ReleaseSearchResult{
|
|
...> id: "1", title: "T", release_group: nil, artists: "A", date: "2000", barcode: "0",
|
|
...> media: [
|
|
...> %{format: "CD", disc_count: 0, track_count: 11},
|
|
...> %{format: "DVD-Video", disc_count: 0, track_count: 22}
|
|
...> ]
|
|
...> })
|
|
:multi
|
|
|
|
"""
|
|
@spec format(t()) ::
|
|
:cd | :vinyl | :dvd | :blu_ray | :digital_download | :vhs | :multi | :unknown
|
|
def format(release_search_result) do
|
|
sorted_frequencies =
|
|
release_search_result.media
|
|
|> Enum.frequencies_by(& &1.format)
|
|
|> Enum.sort_by(fn {_, count} -> count end)
|
|
|
|
case sorted_frequencies do
|
|
[{format, _}] -> parse_format(format)
|
|
_ -> :multi
|
|
end
|
|
end
|
|
|
|
defp parse_release_group(rg) do
|
|
%{
|
|
id: rg["id"],
|
|
type: ReleaseGroup.parse_type(rg["primary-type"]),
|
|
title: rg["title"]
|
|
}
|
|
end
|
|
|
|
@spec parse_media([map()]) :: [map()]
|
|
def parse_media(media) do
|
|
Enum.map(media, fn m ->
|
|
%{
|
|
format: m["format"],
|
|
track_count: m["track-count"],
|
|
disc_count: m["disc-count"]
|
|
}
|
|
end)
|
|
end
|
|
|
|
defp parse_format(nil), do: :unknown
|
|
defp parse_format("CD"), do: :cd
|
|
defp parse_format("DVD-Audio"), do: :dvd
|
|
defp parse_format("DVD-Video"), do: :dvd
|
|
defp parse_format("DVD"), do: :dvd
|
|
defp parse_format("Blu-ray"), do: :blu_ray
|
|
defp parse_format("Digital Media"), do: :digital_download
|
|
|
|
defp parse_format(format) do
|
|
cond do
|
|
String.contains?(format, "Vinyl") -> :vinyl
|
|
String.contains?(format, "CD") -> :cd
|
|
String.contains?(format, "VHS") -> :vhs
|
|
true -> :unknown
|
|
end
|
|
end
|
|
end
|