fix(provenance): label torrent/usenet/staging downloads correctly in history
The download history modal was tagging every torrent / usenet album-bundle download as 'Soulseek FLAC 24bit' because: - core/imports/side_effects.py's source_service dict didn't have entries for 'staging', 'torrent', or 'usenet' usernames. The staging matcher in core/downloads/staging.py sets download_tasks[task_id]['username'] = 'staging', which fell through to the dict's default and got recorded as 'soulseek' in the track download provenance row. Same fate for any amazon or other source that wasn't whitelisted. - The album-bundle flow specifically wants to be labeled as 'torrent' or 'usenet' (where the bytes actually came from), not 'staging' (the intermediate). The plugin already stashes the source on the batch state as ``album_bundle_source`` for the Downloads-page status card; provenance recording can read the same field. Fixes: - core/downloads/staging.py: when marking a task post_processing after a staging match, check the batch's album_bundle_source override and use that for username instead of 'staging' when set. Falls back to 'staging' when no override exists (manual file-drop case). - core/imports/side_effects.py: source_service map gets entries for 'staging', 'torrent', 'usenet', and the previously-missing 'amazon' (which was also falling through to 'soulseek'). - webui/static/library.js: the redownload modal's serviceLabels / serviceIcons dicts extended to cover lidarr, amazon, soundcloud, auto_import, staging, torrent, usenet so badges render the correct name instead of either the raw source_service string or no badge at all. - webui/static/wishlist-tools.js: history-source-chip color palette extended for the new source labels (Torrent sky-blue, Usenet violet, Staging / Auto-Import neutral grey). Note: existing tracks in the DB still carry the wrong 'soulseek' label — only NEW downloads after this fix get the right label. A future migration could rewrite historical rows but it's cosmetic and the underlying audio + metadata are correct.
This commit is contained in:
parent
c990ce079d
commit
daaed373e7
4 changed files with 32 additions and 9 deletions
|
|
@ -141,12 +141,24 @@ def try_staging_match(task_id, batch_id, track, deps: StagingDeps):
|
|||
shutil.copy2(best_match['full_path'], dest_path)
|
||||
logger.info(f"[Staging] Copied to transfer: {dest_path}")
|
||||
|
||||
# Mark task as completed with staging context
|
||||
# Mark task as completed with staging context.
|
||||
# If the batch was populated by the torrent / usenet album-bundle
|
||||
# flow, prefer that provenance label over generic 'staging' so the
|
||||
# download history reflects the real source.
|
||||
_provenance_override = None
|
||||
try:
|
||||
from core.runtime_state import download_batches as _db
|
||||
_batch = _db.get(batch_id) if batch_id else None
|
||||
if isinstance(_batch, dict):
|
||||
_provenance_override = _batch.get('album_bundle_source')
|
||||
except Exception:
|
||||
_provenance_override = None
|
||||
_provenance_username = _provenance_override or 'staging'
|
||||
with tasks_lock:
|
||||
if task_id in download_tasks:
|
||||
download_tasks[task_id]['status'] = 'post_processing'
|
||||
download_tasks[task_id]['filename'] = dest_path
|
||||
download_tasks[task_id]['username'] = 'staging'
|
||||
download_tasks[task_id]['username'] = _provenance_username
|
||||
download_tasks[task_id]['staging_match'] = True
|
||||
|
||||
# Run post-processing (tagging, AcoustID verification, path building)
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ def record_download_provenance(context: Dict[str, Any]) -> None:
|
|||
"deezer_dl": "deezer",
|
||||
"lidarr": "lidarr",
|
||||
"soundcloud": "soundcloud",
|
||||
"amazon": "amazon",
|
||||
# Auto-import: surfaced in provenance so the redownload modal
|
||||
# can tell the user "this came from staging on <date>" instead
|
||||
# of falsely listing soulseek as the source. The underlying
|
||||
|
|
@ -283,6 +284,16 @@ def record_download_provenance(context: Dict[str, Any]) -> None:
|
|||
# separately via the source-aware ID columns on the tracks
|
||||
# row itself.
|
||||
"auto_import": "auto_import",
|
||||
# Generic staging-match (user dropped files manually OR a
|
||||
# source we don't have a more specific label for). Better
|
||||
# than defaulting to 'soulseek' which would falsely tag the
|
||||
# provenance.
|
||||
"staging": "staging",
|
||||
# Torrent / usenet album-bundle flow — the staging matcher
|
||||
# overrides 'staging' with the bundle source so the history
|
||||
# shows where the files actually came from.
|
||||
"torrent": "torrent",
|
||||
"usenet": "usenet",
|
||||
}.get(username, "soulseek")
|
||||
|
||||
ti = context.get("track_info") or context.get("search_result") or {}
|
||||
|
|
|
|||
|
|
@ -4595,8 +4595,8 @@ async function showTrackSourceInfo(track, anchorEl) {
|
|||
return;
|
||||
}
|
||||
|
||||
const serviceIcons = { soulseek: '🔍', youtube: '▶️', tidal: '🌊', qobuz: '🎵', hifi: '🎧', deezer: '💜' };
|
||||
const serviceLabels = { soulseek: 'Soulseek', youtube: 'YouTube', tidal: 'Tidal', qobuz: 'Qobuz', hifi: 'HiFi', deezer: 'Deezer' };
|
||||
const serviceIcons = { soulseek: '🔍', youtube: '▶️', tidal: '🌊', qobuz: '🎵', hifi: '🎧', deezer: '💜', lidarr: '📦', amazon: '🛒', soundcloud: '☁️', auto_import: '📥', staging: '📥', torrent: '🧲', usenet: '📰' };
|
||||
const serviceLabels = { soulseek: 'Soulseek', youtube: 'YouTube', tidal: 'Tidal', qobuz: 'Qobuz', hifi: 'HiFi', deezer: 'Deezer', lidarr: 'Lidarr', amazon: 'Amazon Music', soundcloud: 'SoundCloud', auto_import: 'Auto-Import', staging: 'Staging', torrent: 'Torrent', usenet: 'Usenet' };
|
||||
|
||||
const dl = data.downloads[0]; // Most recent download
|
||||
const icon = serviceIcons[dl.source_service] || '📦';
|
||||
|
|
@ -4926,8 +4926,8 @@ async function _streamRedownloadSources(overlay, track, metadata) {
|
|||
const startBtn = document.getElementById('redownload-start-btn');
|
||||
if (!columnsEl) return;
|
||||
|
||||
const serviceIcons = { soulseek: '🔍', youtube: '▶️', tidal: '🌊', qobuz: '🎵', hifi: '🎧', deezer_dl: '💜', hybrid: '⚡' };
|
||||
const serviceLabels = { soulseek: 'Soulseek', youtube: 'YouTube', tidal: 'Tidal', qobuz: 'Qobuz', hifi: 'HiFi', deezer_dl: 'Deezer', hybrid: 'Auto' };
|
||||
const serviceIcons = { soulseek: '🔍', youtube: '▶️', tidal: '🌊', qobuz: '🎵', hifi: '🎧', deezer_dl: '💜', hybrid: '⚡', lidarr: '📦', amazon: '🛒', soundcloud: '☁️', torrent: '🧲', usenet: '📰' };
|
||||
const serviceLabels = { soulseek: 'Soulseek', youtube: 'YouTube', tidal: 'Tidal', qobuz: 'Qobuz', hifi: 'HiFi', deezer_dl: 'Deezer', hybrid: 'Auto', lidarr: 'Lidarr', amazon: 'Amazon Music', soundcloud: 'SoundCloud', torrent: 'Torrent', usenet: 'Usenet' };
|
||||
|
||||
let allCandidates = [];
|
||||
let firstResult = true;
|
||||
|
|
@ -5049,8 +5049,8 @@ async function _streamRedownloadSources(overlay, track, metadata) {
|
|||
|
||||
/* _renderRedownloadStep2 removed — replaced by _streamRedownloadSources above */
|
||||
if (false) {
|
||||
const serviceIcons = { soulseek: '🔍', youtube: '▶️', tidal: '🌊', qobuz: '🎵', hifi: '🎧', deezer_dl: '💜', hybrid: '⚡' };
|
||||
const serviceLabels = { soulseek: 'Soulseek', youtube: 'YouTube', tidal: 'Tidal', qobuz: 'Qobuz', hifi: 'HiFi', deezer_dl: 'Deezer', hybrid: 'Auto' };
|
||||
const serviceIcons = { soulseek: '🔍', youtube: '▶️', tidal: '🌊', qobuz: '🎵', hifi: '🎧', deezer_dl: '💜', hybrid: '⚡', lidarr: '📦', amazon: '🛒', soundcloud: '☁️', torrent: '🧲', usenet: '📰' };
|
||||
const serviceLabels = { soulseek: 'Soulseek', youtube: 'YouTube', tidal: 'Tidal', qobuz: 'Qobuz', hifi: 'HiFi', deezer_dl: 'Deezer', hybrid: 'Auto', lidarr: 'Lidarr', amazon: 'Amazon Music', soundcloud: 'SoundCloud', torrent: 'Torrent', usenet: 'Usenet' };
|
||||
|
||||
// Group candidates by source service
|
||||
const grouped = {};
|
||||
|
|
|
|||
|
|
@ -3406,7 +3406,7 @@ async function loadLibraryHistory() {
|
|||
const sc = data.stats?.source_counts || {};
|
||||
const srcEntries = Object.entries(sc).sort((a, b) => b[1] - a[1]);
|
||||
if (srcEntries.length > 0 && tab === 'download') {
|
||||
const _srcColors = { Soulseek: '#4caf50', Tidal: '#000', YouTube: '#ff0000', Qobuz: '#4285f4', HiFi: '#00bcd4', Deezer: '#a238ff' };
|
||||
const _srcColors = { Soulseek: '#4caf50', Tidal: '#000', YouTube: '#ff0000', Qobuz: '#4285f4', HiFi: '#00bcd4', Deezer: '#a238ff', Lidarr: '#5dade2', Amazon: '#ff9900', SoundCloud: '#ff7700', Torrent: '#5dade2', Usenet: '#a78bfa', Staging: '#888', 'Auto-Import': '#888' };
|
||||
sourceBar.innerHTML = srcEntries.map(([src, cnt]) =>
|
||||
`<span class="history-source-chip" style="border-color:${_srcColors[src] || '#888'};color:${_srcColors[src] || '#888'}">${src}: ${cnt}</span>`
|
||||
).join('');
|
||||
|
|
|
|||
Loading…
Reference in a new issue