Skip to content

Commit

Permalink
Merge branch 'master' into config-docs-update
Browse files Browse the repository at this point in the history
  • Loading branch information
granth23 authored Jan 15, 2025
2 parents 42be7ab + f40c908 commit 8be1996
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 16 deletions.
11 changes: 6 additions & 5 deletions docs/general/data-update-intervals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ Expected schedule:
System Update schedule
=============================================== =========================================
Receiving listens, updating listen counts Immediate [#f1]_
Deleting listens Removed at the top of the next hour (UTC)
Deleting listens Removed at the top of the next hour (UTC)
Updating statistics for new listens Daily [#f2]_
Removing deleted listens from stats On the 2nd and 16th of each month
Full dumps 1st and 15th of each month
Incremental dumps Daily
Weekly playlists Monday morning, based on the users timezone setting
Daily playlists [#f3]_ Every morning, based on the users timezone setting
Full dumps 1st and 15th of each month
Incremental dumps Daily
Link listens Monday morning at 2AM (UTC)
Weekly playlists Monday morning, based on the user's timezone setting
Daily playlists [#f3]_ Every morning, based on the user's timezone setting
=============================================== =========================================

Situations will occasionally arise where these take longer. If you have been a very patient user, and
Expand Down
33 changes: 22 additions & 11 deletions frontend/js/src/settings/link-listens/LinkListens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Helmet } from "react-helmet";

import NiceModal from "@ebay/nice-modal-react";

import { groupBy, isNil, isNull, pick, size, sortBy } from "lodash";
import { groupBy, isNil, isNull, isString, pick, size, sortBy } from "lodash";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useQuery } from "@tanstack/react-query";
import ReactTooltip from "react-tooltip";
Expand Down Expand Up @@ -86,6 +86,15 @@ export default function LinkListensPage() {
const [searchParams, setSearchParams] = useSearchParams();
const pageSearchParam = searchParams.get("page");

const lastUpdatedHumanReadable = isString(lastUpdated)
? new Date(lastUpdated).toLocaleString(undefined, {
day: "2-digit",
month: "short",
hour: "numeric",
minute: "numeric",
hour12: true,
})
: "—";
// State
const [deletedListens, setDeletedListens] = React.useState<Array<string>>([]);
const [unlinkedListens, setUnlinkedListens] = React.useState<
Expand Down Expand Up @@ -249,28 +258,30 @@ export default function LinkListensPage() {
first.
</ReactTooltip>
<p>
You will find below your top 1000 listens (grouped by album) that
have&nbsp;
Your top 1,000 listens (grouped by album) that have&nbsp;
<u
className="link-listens-tooltip"
data-tip
data-for="matching-tooltip"
>
not been automatically linked
</u>
&nbsp; to a MusicBrainz recording. Link them below or&nbsp;
<a href="https://wiki.musicbrainz.org/How_to_Contribute">
submit new data to MusicBrainz
</a>
.
&nbsp;to a MusicBrainz recording.
</p>
<p className="small">
<a href="https://musicbrainz.org/">MusicBrainz</a> is the open-source
music encyclopedia that ListenBrainz uses to display more information
about your music.
music encyclopedia that ListenBrainz uses to display information about
your music.&nbsp;
<a href="https://wiki.musicbrainz.org/How_to_Contribute">
Submit missing data to MusicBrainz
</a>
.
</p>
{!isNil(lastUpdated) && (
<p>Last updated {new Date(lastUpdated).toLocaleDateString()}</p>
<p className="small">
Updates every Monday at 2AM (UTC). Last updated{" "}
{lastUpdatedHumanReadable}
</p>
)}
<br />
<div>
Expand Down
4 changes: 4 additions & 0 deletions listenbrainz/background/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def export_listens_for_time_range(ts_conn, file_path, user_id: int, start_time:
query = """
WITH selected_listens AS (
SELECT l.listened_at
, l.created as inserted_at
, l.data
, l.recording_msid
, COALESCE((data->'additional_info'->>'recording_mbid')::uuid, user_mm.recording_mbid, mm.recording_mbid, other_mm.recording_mbid) AS recording_mbid
Expand All @@ -97,6 +98,8 @@ def export_listens_for_time_range(ts_conn, file_path, user_id: int, start_time:
SELECT jsonb_build_object(
'listened_at'
, extract(epoch from listened_at)
, 'inserted_at'
, extract(epoch from inserted_at)
, 'track_metadata'
, jsonb_set(
jsonb_set(data, '{recording_msid}'::text[], to_jsonb(recording_msid::text)),
Expand Down Expand Up @@ -140,6 +143,7 @@ def export_listens_for_time_range(ts_conn, file_path, user_id: int, start_time:
LEFT JOIN LATERAL jsonb_array_elements(artist_data->'artists') WITH ORDINALITY artists(artist, position)
ON TRUE
GROUP BY sl.listened_at
, sl.inserted_at
, sl.recording_msid
, sl.data
, mbc.recording_mbid
Expand Down
4 changes: 4 additions & 0 deletions listenbrainz/tests/integration/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ def test_export(self):
self.assertEqual(expected["track_metadata"]["artist_name"], received["track_metadata"]["artist_name"])
self.assertEqual(expected["track_metadata"]["release_name"], received["track_metadata"]["release_name"])
self.assertEqual(expected["listened_at"], received["listened_at"])
# The test data used in send_listens cannot have an inserted_at prop as that is not a valid listen format
self.assertNotIn("inserted_at", expected)
# However inserted_at should be part of the exported listen data
self.assertIn("inserted_at", received)
if received["track_metadata"]["track_name"] == "Sister":
self.assertEqual({
"caa_id": self.recording["release_data"]["caa_id"],
Expand Down

0 comments on commit 8be1996

Please sign in to comment.