feat: add quality_score field to Track model and update related functionality
Fixes #51
This commit is contained in:
@@ -58,9 +58,12 @@ class Track(db.Model):
|
|||||||
jellyfin_id = db.Column(db.String(120), nullable=True) # Add Jellyfin track ID field
|
jellyfin_id = db.Column(db.String(120), nullable=True) # Add Jellyfin track ID field
|
||||||
download_status = db.Column(db.String(2048), nullable=True)
|
download_status = db.Column(db.String(2048), nullable=True)
|
||||||
provider_id = db.Column(db.String(20))
|
provider_id = db.Column(db.String(20))
|
||||||
|
|
||||||
|
|
||||||
# Many-to-Many relationship with Playlists
|
# Many-to-Many relationship with Playlists
|
||||||
playlists = db.relationship('Playlist', secondary=playlist_tracks, back_populates='tracks')
|
playlists = db.relationship('Playlist', secondary=playlist_tracks, back_populates='tracks')
|
||||||
|
|
||||||
lidarr_processed = db.Column(db.Boolean(), default=False)
|
lidarr_processed = db.Column(db.Boolean(), default=False)
|
||||||
|
quality_score = db.Column(db.Float(), default=0)
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<Track {self.name}:{self.provider_track_id}>'
|
return f'<Track {self.name}:{self.provider_track_id}>'
|
||||||
|
|||||||
18
app/tasks.py
18
app/tasks.py
@@ -418,11 +418,18 @@ def update_jellyfin_id_for_downloaded_tracks(self):
|
|||||||
app.logger.info("Starting Jellyfin ID update for tracks...")
|
app.logger.info("Starting Jellyfin ID update for tracks...")
|
||||||
|
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
downloaded_tracks = Track.query.filter_by(downloaded=True, jellyfin_id=None).all()
|
|
||||||
|
|
||||||
|
downloaded_tracks = Track.query.filter(
|
||||||
|
Track.downloaded == True,
|
||||||
|
Track.jellyfin_id == None,
|
||||||
|
(Track.quality_score < app.config['QUALITY_SCORE_THRESHOLD']) | (Track.quality_score == None)
|
||||||
|
).all()
|
||||||
if task_manager.acquire_lock(full_update_key, expiration=60*60*24):
|
if task_manager.acquire_lock(full_update_key, expiration=60*60*24):
|
||||||
app.logger.info(f"performing full update on jellyfin track ids. (Update tracks and playlists if better quality will be found)")
|
app.logger.info(f"performing full update on jellyfin track ids. (Update tracks and playlists if better quality will be found)")
|
||||||
downloaded_tracks = Track.query.all()
|
app.logger.info(f"\tQUALITY_SCORE_THRESHOLD = {app.config['QUALITY_SCORE_THRESHOLD']}")
|
||||||
|
downloaded_tracks = Track.query.filter(
|
||||||
|
(Track.quality_score < app.config['QUALITY_SCORE_THRESHOLD']) | (Track.quality_score == None)
|
||||||
|
).all()
|
||||||
else:
|
else:
|
||||||
app.logger.debug(f"doing update on tracks with downloaded = True and jellyfin_id = None")
|
app.logger.debug(f"doing update on tracks with downloaded = True and jellyfin_id = None")
|
||||||
total_tracks = len(downloaded_tracks)
|
total_tracks = len(downloaded_tracks)
|
||||||
@@ -436,6 +443,7 @@ def update_jellyfin_id_for_downloaded_tracks(self):
|
|||||||
for track in downloaded_tracks:
|
for track in downloaded_tracks:
|
||||||
try:
|
try:
|
||||||
best_match = find_best_match_from_jellyfin(track)
|
best_match = find_best_match_from_jellyfin(track)
|
||||||
|
|
||||||
if best_match:
|
if best_match:
|
||||||
track.downloaded = True
|
track.downloaded = True
|
||||||
if track.jellyfin_id != best_match['Id']:
|
if track.jellyfin_id != best_match['Id']:
|
||||||
@@ -445,7 +453,7 @@ def update_jellyfin_id_for_downloaded_tracks(self):
|
|||||||
track.filesystem_path = best_match['Path']
|
track.filesystem_path = best_match['Path']
|
||||||
app.logger.info(f"Updated filesystem_path for track: {track.name} ({track.provider_track_id})")
|
app.logger.info(f"Updated filesystem_path for track: {track.name} ({track.provider_track_id})")
|
||||||
|
|
||||||
|
track.quality_score = best_match['quality_score']
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
else:
|
else:
|
||||||
@@ -611,7 +619,9 @@ def find_best_match_from_jellyfin(track: Track):
|
|||||||
if quality_score > best_quality_score:
|
if quality_score > best_quality_score:
|
||||||
best_match = result
|
best_match = result
|
||||||
best_quality_score = quality_score
|
best_quality_score = quality_score
|
||||||
|
# attach the quality_score to the best_match
|
||||||
|
if best_match:
|
||||||
|
best_match['quality_score'] = best_quality_score
|
||||||
return best_match
|
return best_match
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
app.logger.error(f"Error searching Jellyfin for track {track.name}: {str(e)}")
|
app.logger.error(f"Error searching Jellyfin for track {track.name}: {str(e)}")
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class Config:
|
|||||||
CHECK_FOR_UPDATES = os.getenv('CHECK_FOR_UPDATES','true').lower() == 'true'
|
CHECK_FOR_UPDATES = os.getenv('CHECK_FOR_UPDATES','true').lower() == 'true'
|
||||||
SPOTDL_PROXY = os.getenv('SPOTDL_PROXY',None)
|
SPOTDL_PROXY = os.getenv('SPOTDL_PROXY',None)
|
||||||
SPOTDL_OUTPUT_FORMAT = os.getenv('SPOTDL_OUTPUT_FORMAT','__jellyplist/{artist}-{title}.mp3')
|
SPOTDL_OUTPUT_FORMAT = os.getenv('SPOTDL_OUTPUT_FORMAT','__jellyplist/{artist}-{title}.mp3')
|
||||||
|
QUALITY_SCORE_THRESHOLD = float(os.getenv('QUALITY_SCORE_THRESHOLD',1000.0))
|
||||||
# SpotDL specific configuration
|
# SpotDL specific configuration
|
||||||
SPOTDL_CONFIG = {
|
SPOTDL_CONFIG = {
|
||||||
'cookie_file': '/jellyplist/cookies.txt',
|
'cookie_file': '/jellyplist/cookies.txt',
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"""Add quality score to Track
|
||||||
|
|
||||||
|
Revision ID: 2777a1885a6b
|
||||||
|
Revises: 46a65ecc9904
|
||||||
|
Create Date: 2024-12-11 20:02:00.303765
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '2777a1885a6b'
|
||||||
|
down_revision = '46a65ecc9904'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('track', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(sa.Column('quality_score', sa.Float(), nullable=True))
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('track', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('quality_score')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
Reference in New Issue
Block a user