Add top artist and top albums of all time

Executed by Claude
This commit is contained in:
Claudio Ortolina
2025-06-19 17:17:51 +03:00
parent ccaf44be64
commit f3425d8cb9
5 changed files with 81 additions and 8 deletions
+2 -1
View File
@@ -2,7 +2,8 @@
"permissions": { "permissions": {
"allow": [ "allow": [
"mcp__tidewave__get_ecto_schemas", "mcp__tidewave__get_ecto_schemas",
"Bash(mix test:*)" "Bash(mix test:*)",
"mcp__tidewave__get_source_location"
] ]
}, },
"enableAllProjectMcpServers": false "enableAllProjectMcpServers": false
+60 -5
View File
@@ -240,6 +240,57 @@ defmodule MusicLibrary.ScrobbleActivity do
Repo.all(query) Repo.all(query)
end end
@doc """
Gets the top albums by scrobble count across all time.
Returns a list of maps with album information and play counts.
"""
def get_top_albums(opts) do
limit = Keyword.get(opts, :limit, 10)
query =
from t in Track,
group_by: [
fragment("json_extract(album, '$.title')"),
fragment("json_extract(artist, '$.name')")
],
select: %{
album_title: fragment("json_extract(album, '$.title')"),
artist_name: fragment("json_extract(artist, '$.name')"),
artist_musicbrainz_id: fragment("json_extract(artist, '$.musicbrainz_id')"),
play_count: count(t.scrobbled_at_uts),
cover_url: fragment("max(?)", t.cover_url),
album_musicbrainz_id: fragment("json_extract(album, '$.musicbrainz_id')")
},
order_by: [desc: count(t.scrobbled_at_uts)],
limit: ^limit
Repo.all(query)
end
@doc """
Gets the top artists by scrobble count across all time.
Returns a list of maps with artist information and play counts.
"""
def get_top_artists(opts) do
limit = Keyword.get(opts, :limit, 10)
query =
from t in Track,
group_by: [
fragment("json_extract(artist, '$.name')"),
fragment("json_extract(artist, '$.musicbrainz_id')")
],
select: %{
artist_name: fragment("json_extract(artist, '$.name')"),
artist_musicbrainz_id: fragment("json_extract(artist, '$.musicbrainz_id')"),
play_count: count(t.scrobbled_at_uts)
},
order_by: [desc: count(t.scrobbled_at_uts)],
limit: ^limit
Repo.all(query)
end
@doc """ @doc """
Gets the top artists by scrobble count for the given number of days. Gets the top artists by scrobble count for the given number of days.
Returns a list of maps with artist information and play counts. Returns a list of maps with artist information and play counts.
@@ -275,7 +326,7 @@ defmodule MusicLibrary.ScrobbleActivity do
end end
@doc """ @doc """
Gets top albums for multiple time periods (30, 90, 365 days). Gets top albums for multiple time periods (30, 90, 365 days) and all time.
Returns a map with the results for each period, along with collected and Returns a map with the results for each period, along with collected and
wishlisted releases. wishlisted releases.
""" """
@@ -283,9 +334,10 @@ defmodule MusicLibrary.ScrobbleActivity do
last_30_days = get_top_albums_by_days(30, opts) last_30_days = get_top_albums_by_days(30, opts)
last_90_days = get_top_albums_by_days(90, opts) last_90_days = get_top_albums_by_days(90, opts)
last_365_days = get_top_albums_by_days(365, opts) last_365_days = get_top_albums_by_days(365, opts)
all_time = get_top_albums(opts)
all_album_ids = all_album_ids =
(last_30_days ++ last_90_days ++ last_365_days) (last_30_days ++ last_90_days ++ last_365_days ++ all_time)
|> Enum.map(fn t -> t.album_musicbrainz_id end) |> Enum.map(fn t -> t.album_musicbrainz_id end)
|> Enum.uniq() |> Enum.uniq()
|> Enum.reject(fn musicbrainz_id -> musicbrainz_id == "" end) |> Enum.reject(fn musicbrainz_id -> musicbrainz_id == "" end)
@@ -298,23 +350,26 @@ defmodule MusicLibrary.ScrobbleActivity do
wishlisted_releases: wishlisted_releases, wishlisted_releases: wishlisted_releases,
last_30_days: last_30_days, last_30_days: last_30_days,
last_90_days: last_90_days, last_90_days: last_90_days,
last_365_days: last_365_days last_365_days: last_365_days,
all_time: all_time
} }
end end
@doc """ @doc """
Gets top artists for multiple time periods (30, 90, 365 days). Gets top artists for multiple time periods (30, 90, 365 days) and all time.
Returns a map with the results for each period. Returns a map with the results for each period.
""" """
def get_top_artists_by_periods(opts) do def get_top_artists_by_periods(opts) do
last_30_days = get_top_artists_by_days(30, opts) last_30_days = get_top_artists_by_days(30, opts)
last_90_days = get_top_artists_by_days(90, opts) last_90_days = get_top_artists_by_days(90, opts)
last_365_days = get_top_artists_by_days(365, opts) last_365_days = get_top_artists_by_days(365, opts)
all_time = get_top_artists(opts)
%{ %{
last_30_days: last_30_days, last_30_days: last_30_days,
last_90_days: last_90_days, last_90_days: last_90_days,
last_365_days: last_365_days last_365_days: last_365_days,
all_time: all_time
} }
end end
@@ -76,7 +76,7 @@
<.refresh_lastfm_feed_button /> <.refresh_lastfm_feed_button />
</div> </div>
<div class="mt-5 grid grid-cols-1 lg:grid-cols-3 gap-5"> <div class="mt-5 grid grid-cols-1 lg:grid-cols-4 gap-5">
<.top_albums_by_period <.top_albums_by_period
albums={@top_albums.last_30_days} albums={@top_albums.last_30_days}
title={gettext("Last 30 days")} title={gettext("Last 30 days")}
@@ -95,6 +95,12 @@
collected_releases={@top_albums.collected_releases} collected_releases={@top_albums.collected_releases}
wishlisted_releases={@top_albums.wishlisted_releases} wishlisted_releases={@top_albums.wishlisted_releases}
/> />
<.top_albums_by_period
albums={@top_albums.all_time}
title={gettext("All time")}
collected_releases={@top_albums.collected_releases}
wishlisted_releases={@top_albums.wishlisted_releases}
/>
</div> </div>
</div> </div>
@@ -106,10 +112,11 @@
<.refresh_lastfm_feed_button /> <.refresh_lastfm_feed_button />
</div> </div>
<div class="mt-5 grid grid-cols-1 lg:grid-cols-3 gap-5"> <div class="mt-5 grid grid-cols-1 lg:grid-cols-4 gap-5">
<.top_artists_by_period artists={@top_artists.last_30_days} title={gettext("Last 30 days")} /> <.top_artists_by_period artists={@top_artists.last_30_days} title={gettext("Last 30 days")} />
<.top_artists_by_period artists={@top_artists.last_90_days} title={gettext("Last 90 days")} /> <.top_artists_by_period artists={@top_artists.last_90_days} title={gettext("Last 90 days")} />
<.top_artists_by_period artists={@top_artists.last_365_days} title={gettext("Last year")} /> <.top_artists_by_period artists={@top_artists.last_365_days} title={gettext("Last year")} />
<.top_artists_by_period artists={@top_artists.all_time} title={gettext("All time")} />
</div> </div>
</div> </div>
+5
View File
@@ -913,3 +913,8 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Top Artists" msgid "Top Artists"
msgstr "" msgstr ""
#: lib/music_library_web/live/stats_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "All time"
msgstr ""
+5
View File
@@ -913,3 +913,8 @@ msgstr ""
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy
msgid "Top Artists" msgid "Top Artists"
msgstr "" msgstr ""
#: lib/music_library_web/live/stats_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "All time"
msgstr ""