feat: Enhance favorites functionality; add favorites filtering to playlists and sounds, and improve favorite indicators in responses

This commit is contained in:
JSC
2025-08-16 21:41:50 +02:00
parent 78508c84eb
commit f906b6d643
10 changed files with 97 additions and 52 deletions

View File

@@ -105,7 +105,7 @@ class FavoriteRepository(BaseRepository[Favorite]):
statement = (
select(Favorite)
.where(
and_(Favorite.user_id == user_id, Favorite.playlist_id.isnot(None))
and_(Favorite.user_id == user_id, Favorite.playlist_id.isnot(None)),
)
.limit(limit)
.offset(offset)
@@ -118,7 +118,7 @@ class FavoriteRepository(BaseRepository[Favorite]):
raise
async def get_by_user_and_sound(
self, user_id: int, sound_id: int
self, user_id: int, sound_id: int,
) -> Favorite | None:
"""Get a favorite by user and sound.
@@ -132,18 +132,18 @@ class FavoriteRepository(BaseRepository[Favorite]):
"""
try:
statement = select(Favorite).where(
and_(Favorite.user_id == user_id, Favorite.sound_id == sound_id)
and_(Favorite.user_id == user_id, Favorite.sound_id == sound_id),
)
result = await self.session.exec(statement)
return result.first()
except Exception:
logger.exception(
"Failed to get favorite for user %s and sound %s", user_id, sound_id
"Failed to get favorite for user %s and sound %s", user_id, sound_id,
)
raise
async def get_by_user_and_playlist(
self, user_id: int, playlist_id: int
self, user_id: int, playlist_id: int,
) -> Favorite | None:
"""Get a favorite by user and playlist.
@@ -157,7 +157,7 @@ class FavoriteRepository(BaseRepository[Favorite]):
"""
try:
statement = select(Favorite).where(
and_(Favorite.user_id == user_id, Favorite.playlist_id == playlist_id)
and_(Favorite.user_id == user_id, Favorite.playlist_id == playlist_id),
)
result = await self.session.exec(statement)
return result.first()

View File

@@ -9,6 +9,7 @@ from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
from app.core.logging import get_logger
from app.models.favorite import Favorite
from app.models.playlist import Playlist
from app.models.playlist_sound import PlaylistSound
from app.models.sound import Sound
@@ -340,6 +341,8 @@ class PlaylistRepository(BaseRepository[Playlist]):
include_stats: bool = False, # noqa: FBT001, FBT002
limit: int | None = None,
offset: int = 0,
favorites_only: bool = False,
current_user_id: int | None = None,
) -> list[dict]:
"""Search and sort playlists with optional statistics."""
try:
@@ -387,6 +390,15 @@ class PlaylistRepository(BaseRepository[Playlist]):
if user_id is not None:
subquery = subquery.where(Playlist.user_id == user_id)
# Apply favorites filter
if favorites_only and current_user_id is not None:
# Use EXISTS subquery to avoid JOIN conflicts with GROUP BY
favorites_subquery = select(1).select_from(Favorite).where(
Favorite.user_id == current_user_id,
Favorite.playlist_id == Playlist.id,
)
subquery = subquery.where(favorites_subquery.exists())
# Apply sorting
if sort_by == PlaylistSortField.SOUND_COUNT:
if sort_order == SortOrder.DESC:
@@ -449,6 +461,15 @@ class PlaylistRepository(BaseRepository[Playlist]):
if user_id is not None:
subquery = subquery.where(Playlist.user_id == user_id)
# Apply favorites filter
if favorites_only and current_user_id is not None:
# Use EXISTS subquery to avoid JOIN conflicts with GROUP BY
favorites_subquery = select(1).select_from(Favorite).where(
Favorite.user_id == current_user_id,
Favorite.playlist_id == Playlist.id,
)
subquery = subquery.where(favorites_subquery.exists())
# Apply sorting
if sort_by:
if sort_by == PlaylistSortField.NAME: