0.6: Spotify OAuth connect flow, AzuraCast base URL, fingerprint/buy-url fixes
- Add "Connect Spotify" OAuth flow (/connect/spotify) so newly created Spotify apps can read playlists: Spotify now requires a user token for playlist reads, which client-credentials alone can no longer provide. The stored refresh token is rendered as spotify-refresh into each playlist's sldl .conf -- sldl's own docs confirm supplying it skips its interactive login flow, which is what was causing multi-hour hangs on a stuck sync. Grandfathered apps keep working unchanged if no account is connected. - Fix the connect flow's redirect_uri: request.url_for() reflected the raw connection scheme (http) rather than what the reverse proxy actually served over, which Spotify's exact-match redirect_uri check rejected. Force https rather than trust the unproxied scheme. - Add an AzuraCast base URL credential field alongside the API key, with a keyfile fallback so the scheduled enrich-buy-url.py job can actually reach AzuraCast (previously it had no way to receive a base URL at all when run from the scheduler, so the reprocess call was silently always skipped). - Fix build-fingerprint-index.py exiting non-zero on any single fingerprint failure instead of only when nothing was written. - Guard enrich-buy-url.py's AzuraCast reprocess against an empty --azuracast-base (raised ValueError since PD2 removed the hardcoded base). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -45,8 +45,22 @@
|
||||
<p class="cred-disabled-note">Disabled — its scheduled automation is paused (or, for buy-link sources, its rendered credential file is removed) until you turn this back on. Saved values below are kept.</p>
|
||||
{% endif %}
|
||||
|
||||
{% if scope == "spotify" %}
|
||||
<div class="field wide" style="margin-bottom:1rem;">
|
||||
<label>Account connection</label>
|
||||
<p class="muted" style="margin:0 0 0.5rem;">Newly created Spotify apps can no longer read playlists without this — connecting an account mints a user token that works where the app-only credentials above are blocked. Grandfathered apps keep working without it.</p>
|
||||
{% if "refresh_token" in configured.get(scope, []) %}
|
||||
<span class="badge badge-success">Connected</span>
|
||||
<a href="/connect/spotify" class="btn" style="margin-left:0.5rem;">Reconnect Spotify</a>
|
||||
{% else %}
|
||||
<a href="/connect/spotify" class="btn">Connect Spotify</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/settings/credentials/{{ scope }}">
|
||||
{% for field in fields %}
|
||||
{% if not (scope == "spotify" and field == "refresh_token") %}
|
||||
<div class="field wide">
|
||||
<label for="{{ scope }}_{{ field }}">
|
||||
{{ field }}
|
||||
@@ -60,6 +74,7 @@
|
||||
<input type="text" id="{{ scope }}_{{ field }}" name="{{ field }}" placeholder="leave blank to keep current" autocomplete="off" spellcheck="false">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<button type="submit" class="btn">Save {{ scope }}</button>
|
||||
</form>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<h2>Credential status</h2>
|
||||
<ul class="chip-list auth-chip-list">
|
||||
{% for a in auth_states %}
|
||||
<li title="{{ a.scope }}: {{ 'configured' if a.configured else 'not configured' }}{% if a.days_left is defined %}, cookie expires in {{ a.days_left }}d{% endif %}"><span class="status-dot {{ 'status-dot-success' if a.configured else 'status-dot-muted' }}{% if a.days_left is defined and a.days_left < 14 %} status-dot-warning{% endif %}"></span>{{ a.scope }}{% if a.days_left is defined %}<span class="muted"> {{ a.days_left }}d</span>{% endif %}</li>
|
||||
<li title="{{ a.scope }}: {{ 'configured' if a.configured else 'not configured' }}{% if a.days_left is defined %}, cookie expires in {{ a.days_left }}d{% endif %}{% if a.spotify_connected is defined %}, {{ 'OAuth connected' if a.spotify_connected else 'app-only (client-credentials)' }}{% endif %}"><span class="status-dot {{ 'status-dot-success' if a.configured else 'status-dot-muted' }}{% if a.days_left is defined and a.days_left < 14 %} status-dot-warning{% endif %}"></span>{{ a.scope }}{% if a.days_left is defined %}<span class="muted"> {{ a.days_left }}d</span>{% endif %}{% if a.spotify_connected %}<span class="muted"> (OAuth)</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<p><a href="/settings/credentials">Manage credentials →</a></p>
|
||||
|
||||
Reference in New Issue
Block a user