First pass at uniformed types, specs and docs
- spec public functions (skipping controllers, views, live views and components) - use types instead of explanations in docs - remove redundant docs - fix typos
This commit is contained in:
@@ -206,6 +206,7 @@ defmodule MusicBrainz.API do
|
||||
}
|
||||
"""
|
||||
|
||||
@spec get_release_group(String.t(), MusicBrainz.Config.t()) :: {:ok, map()} | {:error, term()}
|
||||
def get_release_group(id, config) do
|
||||
config
|
||||
|> new_request()
|
||||
@@ -282,6 +283,7 @@ defmodule MusicBrainz.API do
|
||||
"title": "Clark (Soundtrack From the Netflix Series)"
|
||||
}
|
||||
"""
|
||||
@spec get_release(String.t(), MusicBrainz.Config.t()) :: {:ok, map()} | {:error, term()}
|
||||
def get_release(id, config) do
|
||||
config
|
||||
|> new_request()
|
||||
@@ -295,6 +297,8 @@ defmodule MusicBrainz.API do
|
||||
|> get_request()
|
||||
end
|
||||
|
||||
@spec get_releases(String.t(), keyword(), MusicBrainz.Config.t()) ::
|
||||
{:ok, map()} | {:error, term()}
|
||||
def get_releases(release_group_id, opts, config) do
|
||||
Keyword.validate!(opts, [:limit, :offset])
|
||||
|
||||
@@ -314,6 +318,8 @@ defmodule MusicBrainz.API do
|
||||
|> get_request()
|
||||
end
|
||||
|
||||
@spec search_release_by_barcode(String.t(), MusicBrainz.Config.t()) ::
|
||||
{:ok, [ReleaseSearchResult.t()]} | {:error, term()}
|
||||
def search_release_by_barcode(barcode, config) do
|
||||
config
|
||||
|> new_request()
|
||||
@@ -430,6 +436,9 @@ defmodule MusicBrainz.API do
|
||||
]
|
||||
}
|
||||
"""
|
||||
@spec search_release_group(String.t(), keyword(), MusicBrainz.Config.t()) ::
|
||||
{:ok, %{total_count: non_neg_integer(), release_groups: [ReleaseGroupSearchResult.t()]}}
|
||||
| {:error, term()}
|
||||
def search_release_group(query, opts, config) do
|
||||
Keyword.validate!(opts, [:limit, :offset])
|
||||
|
||||
@@ -451,6 +460,7 @@ defmodule MusicBrainz.API do
|
||||
|> get_request()
|
||||
end
|
||||
|
||||
@spec get_artist(String.t(), MusicBrainz.Config.t()) :: {:ok, Artist.t()} | {:error, term()}
|
||||
def get_artist(musicbrainz_id, config) do
|
||||
config
|
||||
|> new_request()
|
||||
@@ -468,6 +478,8 @@ defmodule MusicBrainz.API do
|
||||
@doc """
|
||||
Uses the [cover art](https://musicbrainz.org/doc/Cover_Art_Archive/API) endpoint with the release group id to get the cover image.
|
||||
"""
|
||||
@spec get_cover_art({:musicbrainz_id, String.t()} | {:url, String.t()}, MusicBrainz.Config.t()) ::
|
||||
{:ok, binary()} | {:error, :cover_not_available}
|
||||
def get_cover_art({:musicbrainz_id, musicbrainz_id}, config) do
|
||||
url = "https://coverartarchive.org/release-group/#{musicbrainz_id}/front"
|
||||
|
||||
|
||||
@@ -2,6 +2,16 @@ defmodule MusicBrainz.Artist do
|
||||
@enforce_keys [:id, :name, :sort_name]
|
||||
defstruct [:id, :name, :sort_name, :country, :relations, :musicbrainz_data]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: String.t(),
|
||||
name: String.t(),
|
||||
sort_name: String.t(),
|
||||
country: String.t() | nil,
|
||||
relations: [map()] | nil,
|
||||
musicbrainz_data: map() | nil
|
||||
}
|
||||
|
||||
@spec from_api_response(map()) :: t()
|
||||
def from_api_response(r) do
|
||||
%__MODULE__{
|
||||
id: r["id"],
|
||||
@@ -15,6 +25,7 @@ defmodule MusicBrainz.Artist do
|
||||
|
||||
# MASSIVE ASSUMPTION: if there's more than one Discogs link,
|
||||
# take the one with the lowest ID, as it's likely to be the main one.
|
||||
@spec get_discogs_id(t()) :: integer() | nil
|
||||
def get_discogs_id(r) do
|
||||
candidates =
|
||||
r.relations
|
||||
@@ -32,6 +43,7 @@ defmodule MusicBrainz.Artist do
|
||||
end
|
||||
end
|
||||
|
||||
@spec get_wikidata_id(t()) :: String.t() | nil
|
||||
def get_wikidata_id(r) do
|
||||
Enum.find_value(r.relations, fn relation ->
|
||||
if relation.type == "wikidata" do
|
||||
@@ -40,6 +52,7 @@ defmodule MusicBrainz.Artist do
|
||||
end)
|
||||
end
|
||||
|
||||
@spec url(String.t()) :: String.t()
|
||||
def url(id) do
|
||||
"https://musicbrainz.org/artist/#{id}"
|
||||
end
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
defmodule MusicBrainz.ExternalLink do
|
||||
defstruct [:name, :url]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
name: atom(),
|
||||
url: String.t()
|
||||
}
|
||||
|
||||
@spec external_links(map(), map() | String.t() | nil) :: [t()] | [String.t()]
|
||||
def external_links(musicbrainz_data, patterns) when is_map(patterns) do
|
||||
Enum.reduce(patterns, [], fn {name, pattern}, acc ->
|
||||
case external_links(musicbrainz_data, pattern) do
|
||||
|
||||
@@ -24,33 +24,73 @@ defmodule MusicBrainz.Release do
|
||||
:media
|
||||
]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: String.t(),
|
||||
title: String.t(),
|
||||
disambiguation: String.t() | nil,
|
||||
packaging: String.t() | nil,
|
||||
artists: [Artist.t()],
|
||||
date: String.t() | nil,
|
||||
barcode: String.t() | nil,
|
||||
catalog_number: String.t(),
|
||||
country: String.t() | nil,
|
||||
media: [Medium.t()]
|
||||
}
|
||||
|
||||
defmodule Artist do
|
||||
@enforce_keys [:id, :name, :sort_name]
|
||||
defstruct [:id, :name, :sort_name]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: String.t(),
|
||||
name: String.t(),
|
||||
sort_name: String.t()
|
||||
}
|
||||
end
|
||||
|
||||
defmodule Medium do
|
||||
@enforce_keys [:title, :format, :number, :track_count, :tracks]
|
||||
defstruct [:title, :format, :number, :track_count, :tracks]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
title: String.t() | nil,
|
||||
format: String.t() | nil,
|
||||
number: non_neg_integer(),
|
||||
track_count: non_neg_integer(),
|
||||
tracks: [MusicBrainz.Release.Track.t()]
|
||||
}
|
||||
end
|
||||
|
||||
defmodule Track do
|
||||
@enforce_keys [:id, :title, :artists, :length, :number, :position]
|
||||
defstruct [:id, :title, :artists, :length, :number, :position]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: String.t(),
|
||||
title: String.t(),
|
||||
artists: [MusicBrainz.Release.Artist.t()],
|
||||
length: non_neg_integer() | nil,
|
||||
number: String.t(),
|
||||
position: non_neg_integer()
|
||||
}
|
||||
end
|
||||
|
||||
@spec media_count(t()) :: non_neg_integer()
|
||||
def media_count(release) do
|
||||
Enum.count(release.media)
|
||||
end
|
||||
|
||||
@spec get_medium(t(), non_neg_integer()) :: Medium.t() | nil
|
||||
def get_medium(release, medium_number) do
|
||||
Enum.find(release.media, fn m -> m.number == medium_number end)
|
||||
end
|
||||
|
||||
@spec medium_duration(Medium.t()) :: non_neg_integer()
|
||||
def medium_duration(medium) do
|
||||
Enum.sum_by(medium.tracks, fn track -> track.length || 0 end)
|
||||
end
|
||||
|
||||
@spec medium_tracks(t(), non_neg_integer()) :: [Track.t()]
|
||||
def medium_tracks(release, medium_number) do
|
||||
case Enum.find(release.media, fn m -> m.number == medium_number end) do
|
||||
nil -> []
|
||||
@@ -58,14 +98,17 @@ defmodule MusicBrainz.Release do
|
||||
end
|
||||
end
|
||||
|
||||
@spec release_duration(t()) :: non_neg_integer()
|
||||
def release_duration(release) do
|
||||
Enum.sum_by(release.media, fn medium -> medium_duration(medium) end)
|
||||
end
|
||||
|
||||
@spec tracks(t()) :: [Track.t()]
|
||||
def tracks(release) do
|
||||
Enum.flat_map(release.media, fn medium -> medium.tracks end)
|
||||
end
|
||||
|
||||
@spec from_api_response(map()) :: t()
|
||||
def from_api_response(r) do
|
||||
%__MODULE__{
|
||||
id: r["id"],
|
||||
@@ -81,6 +124,7 @@ defmodule MusicBrainz.Release do
|
||||
}
|
||||
end
|
||||
|
||||
@spec thumb_url(t()) :: String.t()
|
||||
def thumb_url(release) do
|
||||
"https://coverartarchive.org/release/#{release.id}/front-250"
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
defmodule MusicBrainz.ReleaseGroup do
|
||||
alias MusicBrainz.ReleaseGroupSearchResult
|
||||
|
||||
@spec included_release_groups(map()) :: [ReleaseGroupSearchResult.t()]
|
||||
def included_release_groups(release_group) do
|
||||
release_group
|
||||
|> get_release_groups()
|
||||
@@ -9,27 +10,32 @@ defmodule MusicBrainz.ReleaseGroup do
|
||||
end)
|
||||
end
|
||||
|
||||
@spec releases(map()) :: [map()]
|
||||
def releases(release_group) do
|
||||
release_group
|
||||
|> Map.get("releases", [])
|
||||
end
|
||||
|
||||
@spec release_ids(map()) :: [String.t()]
|
||||
def release_ids(release_group) do
|
||||
release_group
|
||||
|> Map.get("releases", [])
|
||||
|> Enum.map(fn release -> release["id"] end)
|
||||
end
|
||||
|
||||
@spec included_release_group_ids(map()) :: [String.t()]
|
||||
def included_release_group_ids(release_group) do
|
||||
release_group
|
||||
|> included_release_groups()
|
||||
|> Enum.map(fn rg -> rg.id end)
|
||||
end
|
||||
|
||||
@spec url(String.t()) :: String.t()
|
||||
def url(id) do
|
||||
"https://musicbrainz.org/release-group/#{id}"
|
||||
end
|
||||
|
||||
@spec parse_type(String.t() | nil) :: :album | :ep | :live | :compilation | :single | :other
|
||||
def parse_type("Album"), do: :album
|
||||
def parse_type("EP"), do: :ep
|
||||
def parse_type("Live"), do: :live
|
||||
|
||||
@@ -4,6 +4,15 @@ defmodule MusicBrainz.ReleaseGroupSearchResult do
|
||||
@enforce_keys [:id, :type, :title, :artists, :release_date]
|
||||
defstruct [:id, :type, :title, :artists, :release_date]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
id: String.t(),
|
||||
type: :album | :ep | :live | :compilation | :single | :other,
|
||||
title: String.t(),
|
||||
artists: String.t(),
|
||||
release_date: String.t() | nil
|
||||
}
|
||||
|
||||
@spec from_api_response(map()) :: t()
|
||||
def from_api_response(rg) do
|
||||
%__MODULE__{
|
||||
id: rg["id"],
|
||||
@@ -14,6 +23,7 @@ defmodule MusicBrainz.ReleaseGroupSearchResult do
|
||||
}
|
||||
end
|
||||
|
||||
@spec thumb_url(t()) :: String.t()
|
||||
def thumb_url(rgr) do
|
||||
"https://coverartarchive.org/release-group/#{rgr.id}/front-250"
|
||||
end
|
||||
|
||||
@@ -4,6 +4,17 @@ defmodule MusicBrainz.ReleaseSearchResult do
|
||||
@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"],
|
||||
@@ -54,6 +65,8 @@ defmodule MusicBrainz.ReleaseSearchResult do
|
||||
: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
|
||||
@@ -74,6 +87,7 @@ defmodule MusicBrainz.ReleaseSearchResult do
|
||||
}
|
||||
end
|
||||
|
||||
@spec parse_media([map()]) :: [map()]
|
||||
def parse_media(media) do
|
||||
Enum.map(media, fn m ->
|
||||
%{
|
||||
|
||||
Reference in New Issue
Block a user