Fix Navidrome playlist sync truncation, clarify discovery label
Navidrome fix: - createPlaylist and other write operations now use POST instead of GET. Large playlists (161+ tracks) exceeded URL length limits when all songId params were in the query string, causing silent truncation (e.g., only 6 of 161 tracks added). POST sends params as form body with no size limit. - Write operation timeout bumped to 30s (was 10s) - _WRITE_ENDPOINTS set defines which Subsonic endpoints use POST UX fix: - Mirrored playlist cards now show "161/161 discovered on Spotify" instead of just "161/161 discovered" — clarifies that discovery means metadata matching, not library ownership
This commit is contained in:
parent
a98108b3ed
commit
8e41feaade
2 changed files with 20 additions and 3 deletions
|
|
@ -301,8 +301,19 @@ class NavidromeClient:
|
|||
'f': 'json' # Response format
|
||||
}
|
||||
|
||||
# Subsonic endpoints that modify data — use POST to avoid URL length limits
|
||||
_WRITE_ENDPOINTS = frozenset({
|
||||
'createPlaylist', 'updatePlaylist', 'deletePlaylist',
|
||||
'star', 'unstar', 'scrobble', 'setRating',
|
||||
'createShare', 'updateShare', 'deleteShare',
|
||||
'createUser', 'updateUser', 'deleteUser',
|
||||
'createBookmark', 'deleteBookmark',
|
||||
'startScan',
|
||||
})
|
||||
|
||||
def _make_request(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Optional[Dict[str, Any]]:
|
||||
"""Make authenticated request to Navidrome Subsonic API"""
|
||||
"""Make authenticated request to Navidrome Subsonic API.
|
||||
Uses POST for write operations (avoids URL length limits with large playlists)."""
|
||||
if not self.base_url or not self.username:
|
||||
return None
|
||||
|
||||
|
|
@ -314,7 +325,12 @@ class NavidromeClient:
|
|||
auth_params.update(params)
|
||||
|
||||
try:
|
||||
response = requests.get(url, params=auth_params, timeout=10)
|
||||
# Use POST for write operations to avoid URL length limits
|
||||
# (e.g., createPlaylist with 161 songId params would exceed GET URL limits)
|
||||
if endpoint in self._WRITE_ENDPOINTS:
|
||||
response = requests.post(url, data=auth_params, timeout=30)
|
||||
else:
|
||||
response = requests.get(url, params=auth_params, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
|
|
|
|||
|
|
@ -57586,7 +57586,8 @@ function renderMirroredCard(p, container) {
|
|||
let ratioHtml = '';
|
||||
if (disc > 0) {
|
||||
const complete = disc >= tot;
|
||||
ratioHtml = `<span class="discovery-ratio${complete ? ' complete' : ''}">${disc}/${tot} discovered</span>`;
|
||||
const srcName = typeof currentMusicSourceName !== 'undefined' ? currentMusicSourceName : 'metadata';
|
||||
ratioHtml = `<span class="discovery-ratio${complete ? ' complete' : ''}">${disc}/${tot} discovered on ${srcName}</span>`;
|
||||
}
|
||||
|
||||
const card = document.createElement('div');
|
||||
|
|
|
|||
Loading…
Reference in a new issue