feat: Enhance favorites functionality; add favorites filtering to playlists and sounds, and improve favorite indicators in responses
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user