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.sound import SoundRepository
from app.repositories.user import UserRepository
from app.services.socket import socket_manager
logger = get_logger(__name__)
@@ -55,6 +56,10 @@ class FavoriteService:
if not sound:
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
existing = await favorite_repo.get_by_user_and_sound(user_id, sound_id)
if existing:
@@ -70,6 +75,27 @@ class FavoriteService:
}
favorite = await favorite_repo.create(favorite_data)
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
async def add_playlist_favorite(self, user_id: int, playlist_id: int) -> Favorite:
@@ -103,7 +129,8 @@ class FavoriteService:
# Check if already favorited
existing = await favorite_repo.get_by_user_and_playlist(
user_id, playlist_id,
user_id,
playlist_id,
)
if existing:
raise ValueError(
@@ -138,9 +165,41 @@ class FavoriteService:
if not favorite:
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)
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:
"""Remove a playlist from user's favorites.
@@ -156,7 +215,8 @@ class FavoriteService:
favorite_repo = FavoriteRepository(session)
favorite = await favorite_repo.get_by_user_and_playlist(
user_id, playlist_id,
user_id,
playlist_id,
)
if not favorite:
raise ValueError(
@@ -165,7 +225,9 @@ class FavoriteService:
await favorite_repo.delete(favorite)
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(
@@ -230,7 +292,9 @@ class FavoriteService:
async with self.db_session_factory() as session:
favorite_repo = FavoriteRepository(session)
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: