From c7b9aadb70457abf6cfb9a1dd5d7550f6d3e6f02 Mon Sep 17 00:00:00 2001 From: Claudio Ortolina Date: Mon, 11 Nov 2024 20:51:00 +0000 Subject: [PATCH] Add types and specs for LastFm module --- lib/last_fm/album.ex | 5 +++++ lib/last_fm/api_behaviour.ex | 2 +- lib/last_fm/artist.ex | 5 +++++ lib/last_fm/feed.ex | 6 ++++++ lib/last_fm/refresh.ex | 11 +++++++++++ lib/last_fm/track.ex | 10 ++++++++++ 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/last_fm/album.ex b/lib/last_fm/album.ex index d21ba5a7..a7ed33e7 100644 --- a/lib/last_fm/album.ex +++ b/lib/last_fm/album.ex @@ -1,3 +1,8 @@ defmodule LastFm.Album do defstruct [:musicbrainz_id, :title] + + @type t :: %__MODULE__{ + musicbrainz_id: String.t(), + title: String.t() + } end diff --git a/lib/last_fm/api_behaviour.ex b/lib/last_fm/api_behaviour.ex index fe343b26..d5d75974 100644 --- a/lib/last_fm/api_behaviour.ex +++ b/lib/last_fm/api_behaviour.ex @@ -3,5 +3,5 @@ defmodule LastFm.APIBehaviour do @type user :: String.t() @type api_key :: String.t() - @callback get_recent_tracks(user, api_key) :: {:ok, [%Track{}]} | {:error, String.t()} + @callback get_recent_tracks(user, api_key) :: {:ok, [Track.t()]} | {:error, String.t()} end diff --git a/lib/last_fm/artist.ex b/lib/last_fm/artist.ex index f88bd12b..22765670 100644 --- a/lib/last_fm/artist.ex +++ b/lib/last_fm/artist.ex @@ -1,3 +1,8 @@ defmodule LastFm.Artist do defstruct [:musicbrainz_id, :name] + + @type t :: %__MODULE__{ + musicbrainz_id: String.t(), + name: String.t() + } end diff --git a/lib/last_fm/feed.ex b/lib/last_fm/feed.ex index f3c5a67e..95295853 100644 --- a/lib/last_fm/feed.ex +++ b/lib/last_fm/feed.ex @@ -6,11 +6,14 @@ defmodule LastFm.Feed do is technically prone to collision, it's very unlikely for that to happen due to the nature of the data. """ + + @spec create_table!() :: :ok | no_return def create_table! do __MODULE__ = :ets.new(__MODULE__, [:ordered_set, :named_table, :public]) :ok end + @spec update([LastFm.Track.t()]) :: :ok | no_return def update(tracks) do data = Enum.map(tracks, fn t -> {t.scrobbled_at_uts, t} end) @@ -20,6 +23,7 @@ defmodule LastFm.Feed do Phoenix.PubSub.broadcast(LastFm.PubSub, "feed:update", %{tracks: tracks}) end + @spec all() :: [LastFm.Track.t()] def all do m = [ { @@ -29,9 +33,11 @@ defmodule LastFm.Feed do } ] + # reversing to get tracks in DESC order :ets.select_reverse(__MODULE__, m) end + @spec subscribe() :: :ok def subscribe do Phoenix.PubSub.subscribe(LastFm.PubSub, "feed:update") end diff --git a/lib/last_fm/refresh.ex b/lib/last_fm/refresh.ex index c8897990..e9741976 100644 --- a/lib/last_fm/refresh.ex +++ b/lib/last_fm/refresh.ex @@ -5,11 +5,20 @@ defmodule LastFm.Refresh do alias LastFm.Feed + @type config :: %{ + api: module(), + api_key: String.t(), + user: String.t(), + refresh_interval: pos_integer() + } + + @spec start_link(config) :: GenServer.on_start() def start_link(config) do GenServer.start_link(__MODULE__, config, name: __MODULE__) end @impl true + @spec init(config) :: {:ok, config, {:continue, :refresh}} | :ignore def init(config) do config = Map.new(config) @@ -21,9 +30,11 @@ defmodule LastFm.Refresh do end @impl true + @spec handle_continue(atom(), config) :: {:noreply, config} def handle_continue(:refresh, config), do: refresh(config) @impl true + @spec handle_info(atom(), config) :: {:noreply, config} def handle_info(:refresh, config), do: refresh(config) defp refresh(config) do diff --git a/lib/last_fm/track.ex b/lib/last_fm/track.ex index d5177383..f055bf39 100644 --- a/lib/last_fm/track.ex +++ b/lib/last_fm/track.ex @@ -17,6 +17,16 @@ defmodule LastFm.Track do :scrobbled_at_label ] + @type t :: %__MODULE__{ + musicbrainz_id: String.t(), + title: String.t(), + artist: Artist.t(), + album: Album.t(), + cover_url: String.t(), + scrobbled_at_uts: integer(), + scrobbled_at_label: String.t() + } + def from_api_response(raw_tracks) do Enum.map(raw_tracks, fn t -> album = %Album{