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:
@@ -13,6 +13,7 @@ defmodule LastFm.Album do
|
||||
field :title, :string
|
||||
end
|
||||
|
||||
@spec changeset(t(), map()) :: Ecto.Changeset.t()
|
||||
def changeset(album, attrs) do
|
||||
album
|
||||
|> cast(attrs, [:musicbrainz_id, :title])
|
||||
|
||||
@@ -4,6 +4,9 @@ defmodule LastFm.API do
|
||||
|
||||
require Logger
|
||||
|
||||
@type id_or_name :: {:musicbrainz_id, String.t()} | {:name, String.t()}
|
||||
|
||||
@spec get_session(String.t(), LastFm.Config.t()) :: {:ok, Session.t()} | {:error, term()}
|
||||
def get_session(token, config) do
|
||||
params =
|
||||
%{
|
||||
@@ -24,6 +27,7 @@ defmodule LastFm.API do
|
||||
|> get_request()
|
||||
end
|
||||
|
||||
@spec scrobble([map()], String.t(), LastFm.Config.t()) :: {:ok, map()} | {:error, term()}
|
||||
def scrobble(tracks, session_key, config) do
|
||||
params =
|
||||
%{"api_key" => config.api_key, "method" => "track.scrobble", "sk" => session_key}
|
||||
@@ -51,6 +55,7 @@ defmodule LastFm.API do
|
||||
|> post_request()
|
||||
end
|
||||
|
||||
@spec get_recent_tracks(keyword(), LastFm.Config.t()) :: {:ok, [Track.t()]} | {:error, term()}
|
||||
def get_recent_tracks(opts \\ [], config) do
|
||||
to_uts = Keyword.get(opts, :to_uts)
|
||||
limit = Keyword.get(opts, :limit, 100)
|
||||
@@ -69,6 +74,7 @@ defmodule LastFm.API do
|
||||
|> get_request()
|
||||
end
|
||||
|
||||
@spec get_artist_info(id_or_name(), LastFm.Config.t()) :: {:ok, Artist.t()} | {:error, term()}
|
||||
def get_artist_info(id_or_name_option, config) do
|
||||
params =
|
||||
config
|
||||
@@ -83,6 +89,8 @@ defmodule LastFm.API do
|
||||
|> get_request()
|
||||
end
|
||||
|
||||
@spec get_similar_artists(id_or_name(), LastFm.Config.t()) ::
|
||||
{:ok, [Artist.t()]} | {:error, term()}
|
||||
def get_similar_artists(id_or_name_option, config) do
|
||||
params =
|
||||
config
|
||||
@@ -97,6 +105,8 @@ defmodule LastFm.API do
|
||||
|> get_request()
|
||||
end
|
||||
|
||||
@spec get_artist_tags(id_or_name(), LastFm.Config.t()) ::
|
||||
{:ok, [{String.t(), integer()}]} | {:error, term()}
|
||||
def get_artist_tags(id_or_name_option, config) do
|
||||
params =
|
||||
config
|
||||
|
||||
@@ -1,6 +1,28 @@
|
||||
defmodule LastFm.API.ErrorResponse do
|
||||
defstruct [:error, :message]
|
||||
|
||||
@type error_atom ::
|
||||
:invalid_service
|
||||
| :invalid_method
|
||||
| :authentication_failed
|
||||
| :invalid_format
|
||||
| :invalid_parameters
|
||||
| :invalid_resource
|
||||
| :operation_failed
|
||||
| :invalid_session_key
|
||||
| :invalid_api_key
|
||||
| :service_offline
|
||||
| :invalid_method_signature
|
||||
| :transient_error
|
||||
| :suspended_api_key
|
||||
| :rate_limit_exceeded
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
error: error_atom(),
|
||||
message: String.t()
|
||||
}
|
||||
|
||||
@spec new(integer(), String.t()) :: t()
|
||||
def new(error_code, message) do
|
||||
%__MODULE__{error: map_error(error_code), message: message}
|
||||
end
|
||||
@@ -23,6 +45,7 @@ defmodule LastFm.API.ErrorResponse do
|
||||
@doc """
|
||||
Returns true if the error is retryable, false otherwise.
|
||||
"""
|
||||
@spec retryable_error?(atom()) :: boolean()
|
||||
def retryable_error?(error)
|
||||
when error in [:transient_error, :service_offline, :rate_limit_exceeded, :operation_failed],
|
||||
do: true
|
||||
@@ -33,6 +56,7 @@ defmodule LastFm.API.ErrorResponse do
|
||||
Returns the recommended retry delay in milliseconds for retryable errors.
|
||||
Returns nil for non-retryable errors.
|
||||
"""
|
||||
@spec retry_delay(atom()) :: pos_integer() | nil
|
||||
# 1 minute
|
||||
def retry_delay(:rate_limit_exceeded), do: 60_000
|
||||
# 30 seconds
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
defmodule LastFm.API.Signature do
|
||||
@spec generate(map() | keyword(), String.t()) :: String.t()
|
||||
def generate(params, shared_secret) do
|
||||
encoded_params =
|
||||
params
|
||||
|
||||
@@ -28,6 +28,7 @@ defmodule LastFm.Artist do
|
||||
field :image_data_hash, :string
|
||||
end
|
||||
|
||||
@spec from_api_response(map()) :: t()
|
||||
def from_api_response(api_response) do
|
||||
%__MODULE__{
|
||||
musicbrainz_id: api_response["mbid"],
|
||||
@@ -41,6 +42,7 @@ defmodule LastFm.Artist do
|
||||
}
|
||||
end
|
||||
|
||||
@spec changeset(t(), map()) :: Ecto.Changeset.t()
|
||||
def changeset(artist, attrs) do
|
||||
artist
|
||||
|> cast(attrs, [
|
||||
@@ -56,6 +58,7 @@ defmodule LastFm.Artist do
|
||||
|> validate_required([:name])
|
||||
end
|
||||
|
||||
@spec events_url(t()) :: String.t()
|
||||
def events_url(artist) do
|
||||
artist.base_url <> "/+events"
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
defmodule LastFm.Import do
|
||||
@spec batch(keyword()) :: {:ok, non_neg_integer()} | {:error, term()}
|
||||
def batch(opts) do
|
||||
with {:ok, tracks} <- LastFm.get_tracks(opts) do
|
||||
LastFm.Feed.update(tracks)
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
defmodule LastFm.Scrobble do
|
||||
defstruct [:track, :artist, :timestamp, :album, :album_artist, :mbid]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
track: String.t(),
|
||||
artist: String.t(),
|
||||
timestamp: integer(),
|
||||
album: String.t() | nil,
|
||||
album_artist: String.t() | nil,
|
||||
mbid: String.t() | nil
|
||||
}
|
||||
|
||||
@spec encode(t()) :: map()
|
||||
def encode(scrobble) do
|
||||
scrobble
|
||||
|> Map.from_struct()
|
||||
|
||||
@@ -3,6 +3,12 @@ defmodule LastFm.Session do
|
||||
|
||||
defstruct [:name, :key, :pro]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
name: String.t() | nil,
|
||||
key: String.t() | nil,
|
||||
pro: boolean() | nil
|
||||
}
|
||||
|
||||
Record.defrecord(
|
||||
:xmlAttribute,
|
||||
Record.extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl")
|
||||
@@ -32,6 +38,7 @@ defmodule LastFm.Session do
|
||||
pro: true
|
||||
}
|
||||
"""
|
||||
@spec parse(String.t()) :: t()
|
||||
def parse(xml_string) do
|
||||
doc = scan(xml_string)
|
||||
|
||||
@@ -77,6 +84,7 @@ defmodule LastFm.Session do
|
||||
:xmerl_xpath.string(to_charlist(path), node)
|
||||
end
|
||||
|
||||
@spec text(tuple() | nil) :: String.t() | nil
|
||||
def text(node), do: node |> xpath(~c"./text()") |> extract_text()
|
||||
|
||||
defp extract_text([xmlText(value: value)]), do: List.to_string(value)
|
||||
|
||||
@@ -35,6 +35,7 @@ defmodule LastFm.Track do
|
||||
field :last_fm_data, :map, default: %{}
|
||||
end
|
||||
|
||||
@spec from_api_response([map()]) :: [t()]
|
||||
def from_api_response(raw_tracks) do
|
||||
raw_tracks
|
||||
|> Enum.reject(&now_playing?/1)
|
||||
@@ -79,6 +80,7 @@ defmodule LastFm.Track do
|
||||
end
|
||||
end
|
||||
|
||||
@spec changeset(t(), map()) :: Ecto.Changeset.t()
|
||||
def changeset(track, attrs) do
|
||||
track
|
||||
|> cast(attrs, [
|
||||
|
||||
Reference in New Issue
Block a user