@@ -10,7 +10,7 @@ defmodule MusicLibrary.ListeningStats do
|
||||
import Ecto.Query
|
||||
|
||||
alias LastFm.Track
|
||||
alias MusicLibrary.{Artists, Collection, Records.ArtistRecord, Repo, Wishlist}
|
||||
alias MusicLibrary.{Artists, Collection, Records.ArtistRecord, Records.Record, Repo, Wishlist}
|
||||
|
||||
@pagination Application.compile_env!(:music_library, :pagination)
|
||||
|
||||
@@ -247,6 +247,42 @@ defmodule MusicLibrary.ListeningStats do
|
||||
}
|
||||
end
|
||||
|
||||
@spec get_last_listened_track(Record.t()) :: Track.t() | nil
|
||||
def get_last_listened_track(record) do
|
||||
q =
|
||||
from t in scrobbles_for_record_query(record),
|
||||
order_by: [desc: t.scrobbled_at_uts],
|
||||
limit: 1
|
||||
|
||||
Repo.one(q)
|
||||
end
|
||||
|
||||
@spec play_count(Record.t()) :: non_neg_integer()
|
||||
def play_count(record) do
|
||||
record
|
||||
|> scrobbles_for_record_query()
|
||||
|> Repo.aggregate(:count)
|
||||
end
|
||||
|
||||
defp scrobbles_for_record_query(record) do
|
||||
record_id = record.id
|
||||
|
||||
q =
|
||||
from r in fragment("records, json_each(records.release_ids)"),
|
||||
where: fragment("records.id = ?", ^record_id),
|
||||
select: r.value
|
||||
|
||||
release_ids = Repo.all(q)
|
||||
main_artist_name = Record.main_artist(record).name
|
||||
record_title = record.title
|
||||
|
||||
from t in Track,
|
||||
where: fragment("? ->> '$.musicbrainz_id'", t.album) in ^release_ids,
|
||||
or_where:
|
||||
fragment("? ->> '$.title'", t.album) == ^record_title and
|
||||
fragment("? ->> '$.name'", t.artist) == ^main_artist_name
|
||||
end
|
||||
|
||||
defp polyfill_artist(artist, musicbrainz_id) do
|
||||
if is_nil(artist.musicbrainz_id) or artist.musicbrainz_id == "" do
|
||||
%{artist | musicbrainz_id: musicbrainz_id}
|
||||
|
||||
@@ -278,42 +278,6 @@ defmodule MusicLibrary.Records do
|
||||
end
|
||||
end
|
||||
|
||||
@spec get_last_listened_track(Record.t()) :: LastFm.Track.t() | nil
|
||||
def get_last_listened_track(record) do
|
||||
q =
|
||||
from t in scrobbles_for_record_query(record),
|
||||
order_by: [desc: t.scrobbled_at_uts],
|
||||
limit: 1
|
||||
|
||||
Repo.one(q)
|
||||
end
|
||||
|
||||
@spec play_count(Record.t()) :: non_neg_integer()
|
||||
def play_count(record) do
|
||||
record
|
||||
|> scrobbles_for_record_query()
|
||||
|> Repo.aggregate(:count)
|
||||
end
|
||||
|
||||
defp scrobbles_for_record_query(record) do
|
||||
record_id = record.id
|
||||
|
||||
q =
|
||||
from r in fragment("records, json_each(records.release_ids)"),
|
||||
where: fragment("records.id = ?", ^record_id),
|
||||
select: r.value
|
||||
|
||||
release_ids = Repo.all(q)
|
||||
main_artist_name = Record.main_artist(record).name
|
||||
record_title = record.title
|
||||
|
||||
from t in LastFm.Track,
|
||||
where: fragment("? ->> '$.musicbrainz_id'", t.album) in ^release_ids,
|
||||
or_where:
|
||||
fragment("? ->> '$.title'", t.album) == ^record_title and
|
||||
fragment("? ->> '$.name'", t.artist) == ^main_artist_name
|
||||
end
|
||||
|
||||
@spec refresh_cover(Record.t()) :: {:ok, Record.t()} | {:error, term()}
|
||||
def refresh_cover(record) do
|
||||
with {:ok, cover_data} <- MusicBrainz.get_cover_art({:url, record.cover_url}),
|
||||
|
||||
@@ -21,7 +21,7 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
||||
similar_records: 1
|
||||
]
|
||||
|
||||
alias MusicLibrary.{Records, RecordSets, ScrobbleActivity}
|
||||
alias MusicLibrary.{ListeningStats, Records, RecordSets, ScrobbleActivity}
|
||||
alias MusicLibrary.Records.Similarity
|
||||
alias MusicLibraryWeb.ErrorMessages
|
||||
alias Phoenix.LiveView.JS
|
||||
@@ -346,8 +346,8 @@ defmodule MusicLibraryWeb.CollectionLive.Show do
|
||||
@impl true
|
||||
def handle_params(%{"id" => id}, _, socket) do
|
||||
record = Records.get_record!(id)
|
||||
last_listened_track = Records.get_last_listened_track(record)
|
||||
play_count = Records.play_count(record) || 0
|
||||
last_listened_track = ListeningStats.get_last_listened_track(record)
|
||||
play_count = ListeningStats.play_count(record) || 0
|
||||
|
||||
socket =
|
||||
if record.selected_release_id do
|
||||
|
||||
@@ -4,7 +4,9 @@ defmodule MusicLibrary.ListeningStatsTest do
|
||||
import MusicLibrary.ArtistInfoFixtures
|
||||
import MusicLibrary.ScrobbledTracksFixtures
|
||||
|
||||
alias MusicLibrary.Fixtures.Records, as: RecordsFixtures
|
||||
alias MusicLibrary.ListeningStats
|
||||
alias MusicLibrary.Records.Record
|
||||
|
||||
describe "scrobble_count/0" do
|
||||
test "returns correct count" do
|
||||
@@ -94,6 +96,65 @@ defmodule MusicLibrary.ListeningStatsTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_last_listened_track/1" do
|
||||
test "returns the most recent scrobbled track for a record" do
|
||||
record = RecordsFixtures.record()
|
||||
main_artist = Record.main_artist(record)
|
||||
now = System.system_time(:second)
|
||||
|
||||
_older =
|
||||
track_fixture(%{
|
||||
artist_name: main_artist.name,
|
||||
album_title: record.title,
|
||||
title: "Older Track",
|
||||
scrobbled_at_uts: now - 200
|
||||
})
|
||||
|
||||
track_fixture(%{
|
||||
artist_name: main_artist.name,
|
||||
album_title: record.title,
|
||||
title: "Newer Track",
|
||||
scrobbled_at_uts: now - 100
|
||||
})
|
||||
|
||||
result = ListeningStats.get_last_listened_track(record)
|
||||
|
||||
assert result.title == "Newer Track"
|
||||
assert result.scrobbled_at_uts == now - 100
|
||||
end
|
||||
|
||||
test "returns nil when no scrobbles exist for the record" do
|
||||
record = RecordsFixtures.record()
|
||||
|
||||
assert ListeningStats.get_last_listened_track(record) == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "play_count/1" do
|
||||
test "returns the correct scrobble count for a record" do
|
||||
record = RecordsFixtures.record()
|
||||
main_artist = Record.main_artist(record)
|
||||
now = System.system_time(:second)
|
||||
|
||||
for i <- 1..3 do
|
||||
track_fixture(%{
|
||||
artist_name: main_artist.name,
|
||||
album_title: record.title,
|
||||
title: "Track #{i}",
|
||||
scrobbled_at_uts: now - i * 100
|
||||
})
|
||||
end
|
||||
|
||||
assert ListeningStats.play_count(record) == 3
|
||||
end
|
||||
|
||||
test "returns 0 when no scrobbles exist for the record" do
|
||||
record = RecordsFixtures.record()
|
||||
|
||||
assert ListeningStats.play_count(record) == 0
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_top_artists_by_days/2" do
|
||||
test "counts tracks with missing artist_infos records within date range" do
|
||||
artist_info =
|
||||
|
||||
Reference in New Issue
Block a user