feat: Lidarr searches for a better copy of a rip that has none (M498 #5447)
release / govulncheck (push) Successful in 18s
release / web (push) Successful in 1m26s
release / go (push) Successful in 1m45s
release / integration (push) Successful in 5m6s
release / android (push) Successful in 5m58s
release / Build signed APK (releases and dev) (push) Successful in 6m17s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 26s
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Successful in 18s
release / web (push) Successful in 1m26s
release / go (push) Successful in 1m45s
release / integration (push) Successful in 5m6s
release / android (push) Successful in 5m58s
release / Build signed APK (releases and dev) (push) Successful in 6m17s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 26s
release / Verify release artifacts (tag releases only) (push) Skipped
The operator chose option 2: an album holding a video rip that is the only copy of its song is searched in Lidarr (AlbumSearch), at most once a week and ten albums a pass. Lidarr grabs only when the quality profile allows an upgrade, so nothing is removed and the rip stays held back either way. - lidarr.Client.SearchAlbums posts the AlbumSearch command. - ListAlbumsWithSoleCopyRips finds the albums: a held-back rip with no present clean copy sharing its song or its pending group, and not searched in the last week (audit action lidarr_rip_search). - Suspect sources shows when Lidarr last searched the track's album. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,8 @@ function track(id: string): AdminSuspectTrack {
|
||||
track_number: null,
|
||||
markers: [],
|
||||
verdict: null,
|
||||
verdict_at: null
|
||||
verdict_at: null,
|
||||
searched_at: null
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -443,6 +443,8 @@ export type AdminSuspectTrack = {
|
||||
// back. null: the resolver hasn't looked yet (M498 #5439).
|
||||
verdict: SuspectVerdict | null;
|
||||
verdict_at: string | null;
|
||||
// When Lidarr was last asked to search the album for a better copy (#5447).
|
||||
searched_at: string | null;
|
||||
};
|
||||
|
||||
export type SuspectVerdict = 'suspect' | 'fine';
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
// The duplicate resolver holds each one back from radio and the mixes, and
|
||||
// merges it away where Lidarr keeps a clean copy (M498 #5439). A marker is a
|
||||
// reason to look, not proof, so each row says what was done and offers the
|
||||
// undo: "This one is fine" lets the track back for good.
|
||||
// undo: "This one is fine" lets the track back for good. A rip that is the
|
||||
// only copy of its song has its album searched in Lidarr (#5447).
|
||||
|
||||
const queryStore = createSuspectSourcesQuery();
|
||||
const query = $derived($queryStore);
|
||||
@@ -101,7 +102,8 @@
|
||||
a video site, and can be the wrong audio: a live take, a music-video edit, or
|
||||
something else entirely. Each one is kept out of radio and the mixes, though it still
|
||||
plays when you choose it, and it is removed where Lidarr keeps a clean copy of the same
|
||||
song. If one is fine, say so and it goes back in.
|
||||
song. Where it is the only copy, Lidarr is asked once a week to search the album for a
|
||||
better release. If one is fine, say so and it goes back in.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
@@ -178,6 +180,11 @@
|
||||
<span class="text-xs text-text-secondary" data-testid="suspect-verdict">
|
||||
Held back{#if t.verdict_at && !changed[t.track_id]} {relativeTime(t.verdict_at)}{/if}
|
||||
</span>
|
||||
{#if t.searched_at}
|
||||
<span class="text-xs text-text-muted" data-testid="suspect-searched">
|
||||
Lidarr searched for a better copy {relativeTime(t.searched_at)}
|
||||
</span>
|
||||
{/if}
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => setVerdict(t, 'fine')}
|
||||
|
||||
@@ -29,7 +29,8 @@ function track(title: string, file: string, markers: string[], disc: number | nu
|
||||
track_number: 4,
|
||||
markers,
|
||||
verdict: 'suspect',
|
||||
verdict_at: new Date(Date.now() - 3_600_000).toISOString()
|
||||
verdict_at: new Date(Date.now() - 3_600_000).toISOString(),
|
||||
searched_at: null
|
||||
};
|
||||
}
|
||||
|
||||
@@ -136,4 +137,14 @@ describe('Suspect sources page', () => {
|
||||
expect(await screen.findByText('Marked fine')).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: 'Hold back again' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// #5447: a rip with no clean copy has its album searched in Lidarr, and the
|
||||
// row says when.
|
||||
test('shows when Lidarr searched for a better copy', () => {
|
||||
const t = track('Strobelite', 'Gorillaz - Strobelite (Official Video).mp3', ['music video']);
|
||||
t.searched_at = new Date(Date.now() - 7_200_000).toISOString();
|
||||
mocked.mockReturnValue(infinite([page(0, 1, [{ directory: HUMANZ, tracks: [t] }])]));
|
||||
render(SuspectSourcesPage);
|
||||
expect(screen.getByTestId('suspect-searched')).toHaveTextContent(/Lidarr searched for a better copy/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user