Better Errorhandling in case of spotify api errors

Addresses issue #20
This commit is contained in:
Kamil
2024-11-27 17:20:47 +00:00
parent c6eb95112e
commit b60a882dab
6 changed files with 109 additions and 59 deletions

View File

@@ -5,6 +5,8 @@ from functools import wraps
from celery.result import AsyncResult from celery.result import AsyncResult
from app.tasks import download_missing_tracks,check_for_playlist_updates, update_all_playlists_track_status, update_jellyfin_id_for_downloaded_tracks from app.tasks import download_missing_tracks,check_for_playlist_updates, update_all_playlists_track_status, update_jellyfin_id_for_downloaded_tracks
from jellyfin.objects import PlaylistMetadata from jellyfin.objects import PlaylistMetadata
from spotipy.exceptions import SpotifyException
import re import re
TASK_STATUS = { TASK_STATUS = {
@@ -129,12 +131,9 @@ def get_cached_spotify_playlist(playlist_id):
:param playlist_id: The Spotify playlist ID. :param playlist_id: The Spotify playlist ID.
:return: Playlist data as a dictionary, or None if an error occurs. :return: Playlist data as a dictionary, or None if an error occurs.
""" """
try:
playlist_data = sp.playlist(playlist_id) # Fetch data from Spotify API playlist_data = sp.playlist(playlist_id) # Fetch data from Spotify API
return playlist_data return playlist_data
except Exception as e:
app.logger.error(f"Error fetching playlist {playlist_id} from Spotify: {str(e)}")
return None
@cache.memoize(timeout=3600*24*10) @cache.memoize(timeout=3600*24*10)
def get_cached_spotify_track(track_id): def get_cached_spotify_track(track_id):
""" """
@@ -180,15 +179,21 @@ def prepArtistData(data):
def getFeaturedPlaylists(country,offset): def getFeaturedPlaylists(country: str, offset: int):
try:
playlists_data = sp.featured_playlists(country=country, limit=16, offset=offset) playlists_data = sp.featured_playlists(country=country, limit=16, offset=offset)
return prepPlaylistData(playlists_data), playlists_data['playlists']['total'], 'Featured Playlists'
except SpotifyException as e:
app.logger.error(f"Spotify API error in getFeaturedPlaylists: {e}")
return [], e, f'Error: Could not load featured playlists. Please try again later. This is most likely due to an Error in the Spotify API or an rate limit has been reached.'
return prepPlaylistData(playlists_data), playlists_data['playlists']['total'],'Featured Playlists' def getCategoryPlaylists(category: str, offset: int):
try:
def getCategoryPlaylists(category,offset):
playlists_data = sp.category_playlists(category_id=category, limit=16, offset=offset) playlists_data = sp.category_playlists(category_id=category, limit=16, offset=offset)
return prepPlaylistData(playlists_data), playlists_data['playlists']['total'], f"Category {playlists_data['message']}"
return prepPlaylistData(playlists_data), playlists_data['playlists']['total'],f"Category {playlists_data['message']}" except SpotifyException as e:
app.logger.error(f"Spotify API error in getCategoryPlaylists: {e}")
return [], e, 'Error: Could not load category playlists. Please try again later. This is most likely due to an Error in the Spotify API or an rate limit has been reached.'
def getCategories(country,offset): def getCategories(country,offset):
categories_data = sp.categories(limit=16, offset= offset) categories_data = sp.categories(limit=16, offset= offset)

View File

@@ -3,7 +3,7 @@ from flask import Flask, jsonify, render_template, request, redirect, url_for, s
from sqlalchemy import insert from sqlalchemy import insert
from app import app, db, jellyfin, functions, device_id,sp from app import app, db, jellyfin, functions, device_id,sp
from app.models import Playlist,Track, playlist_tracks from app.models import Playlist,Track, playlist_tracks
from spotipy.exceptions import SpotifyException
from jellyfin.objects import PlaylistMetadata from jellyfin.objects import PlaylistMetadata
@@ -38,11 +38,15 @@ def jellyfin_playlists():
prepared_data = functions.prepPlaylistData(spotify_data) prepared_data = functions.prepPlaylistData(spotify_data)
return render_template('jellyfin_playlists.html', playlists=prepared_data) return render_template('jellyfin_playlists.html', playlists=prepared_data)
except SpotifyException as e:
app.logger.error(f"Error fetching monitored playlists: {e}")
error_data, error_message = e, f'Could not retrieve monitored Playlists. Please try again later. This is most likely due to an Error in the Spotify API or an rate limit has been reached.'
return render_template('jellyfin_playlists.html', playlists=functions.prepPlaylistData({'playlists': {'items': []}}), error_message=error_message,error_data = error_data)
except Exception as e: except Exception as e:
app.logger.error(f"Error in /jellyfin_playlists route: {str(e)}") app.logger.error(f"Error in /jellyfin_playlists route: {str(e)}")
flash('An error occurred while fetching playlists.', 'danger') flash('An error occurred while fetching playlists.', 'danger')
return render_template('jellyfin_playlists.html', playlists=functions.prepPlaylistData({'playlists': {'items': []}})) return render_template('jellyfin_playlists.html', playlists=functions.prepPlaylistData({'playlists': {'items': []}}), error_message='An error occurred while fetching playlists.',error_data = e)
@app.route('/addplaylist', methods=['POST']) @app.route('/addplaylist', methods=['POST'])

View File

@@ -3,6 +3,7 @@ from app import app, db, functions, sp, jellyfin, celery, jellyfin_admin_token,
from app.models import JellyfinUser,Playlist,Track from app.models import JellyfinUser,Playlist,Track
from celery.result import AsyncResult from celery.result import AsyncResult
from .version import __version__ from .version import __version__
from spotipy.exceptions import SpotifyException
@app.context_processor @app.context_processor
def add_context(): def add_context():
@@ -140,32 +141,46 @@ def loaditems():
limit = 20 # Define a limit for pagination limit = 20 # Define a limit for pagination
additional_query = '' additional_query = ''
items_subtitle = '' items_subtitle = ''
error_message = None # Placeholder for error messages
error_data = ''
if request.path == '/playlists/monitored': if request.path == '/playlists/monitored':
# Step 1: Query the database for monitored playlists try:
db_playlists = db.session.query(Playlist).offset(offset).limit(limit).all() db_playlists = db.session.query(Playlist).offset(offset).limit(limit).all()
max_items = db.session.query(Playlist).count() max_items = db.session.query(Playlist).count()
# Collect Spotify Playlist IDs from the database
spotify_playlist_ids = [playlist.spotify_playlist_id for playlist in db_playlists] spotify_playlist_ids = [playlist.spotify_playlist_id for playlist in db_playlists]
spotify_data = functions.get_cached_spotify_playlists(tuple(spotify_playlist_ids)) spotify_data = functions.get_cached_spotify_playlists(tuple(spotify_playlist_ids))
# Step 3: Pass the Spotify data to prepPlaylistData for processing
data = functions.prepPlaylistData(spotify_data) data = functions.prepPlaylistData(spotify_data)
items_title = "Monitored Playlists" items_title = "Monitored Playlists"
items_subtitle = "This playlists are already monitored by the Server, if you add one of these to your Jellyfin account, they will be available immediately." items_subtitle = "These playlists are already monitored by the Server. If you add one to your Jellyfin account, they will be available immediately."
except SpotifyException as e:
app.logger.error(f"Error fetching monitored playlists: {e}")
data, max_items, items_title = [], e, f'Could not retrieve monitored Playlists. Please try again later. This is most likely due to an Error in the Spotify API or an rate limit has been reached.'
error_message = items_title
error_data = max_items
elif request.path == '/playlists': elif request.path == '/playlists':
cat = request.args.get('cat', None) cat = request.args.get('cat', None)
if cat is not None: if cat is not None:
data, max_items, items_title = functions.getCategoryPlaylists(category=cat, offset=offset) data, max_items, items_title = functions.getCategoryPlaylists(category=cat, offset=offset)
if not data: # Check if data is empty
error_message = items_title # Set the error message from the function
error_data = max_items
additional_query += f"&cat={cat}" additional_query += f"&cat={cat}"
else: else:
data, max_items, items_title = functions.getFeaturedPlaylists(country=country, offset=offset) data, max_items, items_title = functions.getFeaturedPlaylists(country=country, offset=offset)
if not data: # Check if data is empty
error_message = items_title # Set the error message from the function
error_data = max_items
elif request.path == '/categories': elif request.path == '/categories':
try:
data, max_items, items_title = functions.getCategories(country=country, offset=offset) data, max_items, items_title = functions.getCategories(country=country, offset=offset)
except Exception as e:
app.logger.error(f"Error fetching categories: {e}")
data, max_items, items_title = [], e, f'Error: Could not load categories. Please try again later. '
error_message = items_title
error_data = max_items
next_offset = offset + len(data) next_offset = offset + len(data)
total_items = max_items total_items = max_items
@@ -175,8 +190,10 @@ def loaditems():
'total_items': total_items, 'total_items': total_items,
'endpoint': request.path, 'endpoint': request.path,
'items_title': items_title, 'items_title': items_title,
'items_subtitle' : items_subtitle, 'items_subtitle': items_subtitle,
'additional_query': additional_query 'additional_query': additional_query,
'error_message': error_message, # Pass error message to the template
'error_data': error_data, # Pass error message to the template
} }
if request.headers.get('HX-Request'): # Check if the request is from HTMX if request.headers.get('HX-Request'): # Check if the request is from HTMX

View File

@@ -128,6 +128,7 @@ def download_missing_tracks(self):
continue continue
# region search with fingerprinting # region search with fingerprinting
if spotify_track:
preview_url = spotify_track.get('preview_url') preview_url = spotify_track.get('preview_url')
if not preview_url: if not preview_url:
app.logger.error(f"Preview URL not found for track {track.name}.") app.logger.error(f"Preview URL not found for track {track.name}.")
@@ -152,6 +153,8 @@ def download_missing_tracks(self):
continue continue
else: else:
app.logger.info(f"No match found in Jellyfin for track {track.name}. Proceeding to download.") app.logger.info(f"No match found in Jellyfin for track {track.name}. Proceeding to download.")
else:
app.logger.warning(f"spotify_track not set, see previous log messages")
#endregion #endregion
#endregion #endregion

View File

@@ -1,6 +1,16 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% if error_message %}
<div class="alert alert-danger mt-5" role="alert">
<h4 class="alert-heading">🚨Something went wrong🚨</h4>
<p>{{ error_message }}</p>
<hr>
<p>Additional Information:</p>
<p>{{error_data}}</p>
</div>
{% else %}
<h1 class="mb-4">{{ items_title }}</h1> <h1 class="mb-4">{{ items_title }}</h1>
<h6 class="mb-4">{{ items_subtitle }}</h6> <h6 class="mb-4">{{ items_subtitle }}</h6>
<div class="row row-cols-1 row-cols-md-4 row-cols-lg-6 g-4" id="items-container"> <div class="row row-cols-1 row-cols-md-4 row-cols-lg-6 g-4" id="items-container">
@@ -8,5 +18,6 @@
</div> </div>
{% endif %}
{% endblock %} {% endblock %}

View File

@@ -1,6 +1,16 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% if error_message %}
<div class="alert alert-danger mt-5" role="alert">
<h4 class="alert-heading">🚨Something went wrong🚨</h4>
<p>{{ error_message }}</p>
<hr>
<p>Additional Information:</p>
<p>{{error_data}}</p>
</div>
{% else %}
<h1 >Your subscribed Jellyfin Playlists</h1> <h1 >Your subscribed Jellyfin Playlists</h1>
<h6 ></h6> <h6 ></h6>
<div class="row row-cols-1 row-cols-md-4 row-cols-lg-6 g-4" id="items-container"> <div class="row row-cols-1 row-cols-md-4 row-cols-lg-6 g-4" id="items-container">
@@ -10,6 +20,6 @@
{% endfor %} {% endfor %}
</div> </div>
{%endif%}
{% endblock %} {% endblock %}