feat: Enhance sound favorite management; add WebSocket event broadcasting for favoriting and unfavoriting sounds

This commit is contained in:
JSC
2025-08-16 22:19:24 +02:00
parent f906b6d643
commit f56cc8b4cc

View File

@@ -10,6 +10,7 @@ from app.repositories.favorite import FavoriteRepository
from app.repositories.playlist import PlaylistRepository from app.repositories.playlist import PlaylistRepository
from app.repositories.sound import SoundRepository from app.repositories.sound import SoundRepository
from app.repositories.user import UserRepository from app.repositories.user import UserRepository
from app.services.socket import socket_manager
logger = get_logger(__name__) logger = get_logger(__name__)
@@ -55,6 +56,10 @@ class FavoriteService:
if not sound: if not sound:
raise ValueError(f"Sound with ID {sound_id} not found") raise ValueError(f"Sound with ID {sound_id} not found")
# Get data for the event immediately after loading
sound_name = sound.name
user_name = user.name
# Check if already favorited # Check if already favorited
existing = await favorite_repo.get_by_user_and_sound(user_id, sound_id) existing = await favorite_repo.get_by_user_and_sound(user_id, sound_id)
if existing: if existing:
@@ -70,6 +75,27 @@ class FavoriteService:
} }
favorite = await favorite_repo.create(favorite_data) favorite = await favorite_repo.create(favorite_data)
logger.info("User %s favorited sound %s", user_id, sound_id) logger.info("User %s favorited sound %s", user_id, sound_id)
# Get updated favorite count within the same session
favorite_count = await favorite_repo.count_sound_favorites(sound_id)
# Emit sound_favorited event via WebSocket (outside the session)
try:
event_data = {
"sound_id": sound_id,
"sound_name": sound_name,
"user_id": user_id,
"user_name": user_name,
"favorite_count": favorite_count,
}
await socket_manager.broadcast_to_all("sound_favorited", event_data)
logger.info("Broadcasted sound_favorited event for sound %s", sound_id)
except Exception:
logger.exception(
"Failed to broadcast sound_favorited event for sound %s",
sound_id,
)
return favorite return favorite
async def add_playlist_favorite(self, user_id: int, playlist_id: int) -> Favorite: async def add_playlist_favorite(self, user_id: int, playlist_id: int) -> Favorite:
@@ -103,7 +129,8 @@ class FavoriteService:
# Check if already favorited # Check if already favorited
existing = await favorite_repo.get_by_user_and_playlist( existing = await favorite_repo.get_by_user_and_playlist(
user_id, playlist_id, user_id,
playlist_id,
) )
if existing: if existing:
raise ValueError( raise ValueError(
@@ -138,9 +165,41 @@ class FavoriteService:
if not favorite: if not favorite:
raise ValueError(f"Sound {sound_id} is not favorited by user {user_id}") raise ValueError(f"Sound {sound_id} is not favorited by user {user_id}")
# Get user and sound info before deletion for the event
user_repo = UserRepository(session)
sound_repo = SoundRepository(session)
user = await user_repo.get_by_id(user_id)
sound = await sound_repo.get_by_id(sound_id)
# Get data for the event immediately after loading
sound_name = sound.name if sound else "Unknown"
user_name = user.name if user else "Unknown"
await favorite_repo.delete(favorite) await favorite_repo.delete(favorite)
logger.info("User %s removed sound %s from favorites", user_id, sound_id) logger.info("User %s removed sound %s from favorites", user_id, sound_id)
# Get updated favorite count after deletion within the same session
favorite_count = await favorite_repo.count_sound_favorites(sound_id)
# Emit sound_favorited event via WebSocket (outside the session)
try:
event_data = {
"sound_id": sound_id,
"sound_name": sound_name,
"user_id": user_id,
"user_name": user_name,
"favorite_count": favorite_count,
}
await socket_manager.broadcast_to_all("sound_favorited", event_data)
logger.info(
"Broadcasted sound_favorited event for sound %s removal", sound_id
)
except Exception:
logger.exception(
"Failed to broadcast sound_favorited event for sound %s removal",
sound_id,
)
async def remove_playlist_favorite(self, user_id: int, playlist_id: int) -> None: async def remove_playlist_favorite(self, user_id: int, playlist_id: int) -> None:
"""Remove a playlist from user's favorites. """Remove a playlist from user's favorites.
@@ -156,7 +215,8 @@ class FavoriteService:
favorite_repo = FavoriteRepository(session) favorite_repo = FavoriteRepository(session)
favorite = await favorite_repo.get_by_user_and_playlist( favorite = await favorite_repo.get_by_user_and_playlist(
user_id, playlist_id, user_id,
playlist_id,
) )
if not favorite: if not favorite:
raise ValueError( raise ValueError(
@@ -165,7 +225,9 @@ class FavoriteService:
await favorite_repo.delete(favorite) await favorite_repo.delete(favorite)
logger.info( logger.info(
"User %s removed playlist %s from favorites", user_id, playlist_id, "User %s removed playlist %s from favorites",
user_id,
playlist_id,
) )
async def get_user_favorites( async def get_user_favorites(
@@ -230,7 +292,9 @@ class FavoriteService:
async with self.db_session_factory() as session: async with self.db_session_factory() as session:
favorite_repo = FavoriteRepository(session) favorite_repo = FavoriteRepository(session)
return await favorite_repo.get_user_playlist_favorites( return await favorite_repo.get_user_playlist_favorites(
user_id, limit, offset, user_id,
limit,
offset,
) )
async def is_sound_favorited(self, user_id: int, sound_id: int) -> bool: async def is_sound_favorited(self, user_id: int, sound_id: int) -> bool: