Files
sdb2-backend/app/repositories/sound.py
JSC 36949a1f1c feat: add SoundRepository and SoundScannerService for audio file management
- Implemented SoundRepository for database operations related to sounds, including methods for retrieving, creating, updating, and deleting sound records.
- Developed SoundScannerService to scan directories for audio files, calculate their metadata, and synchronize with the database.
- Added support for various audio file formats and integrated ffmpeg for audio duration extraction.
- Created comprehensive tests for sound API endpoints and sound scanner service to ensure functionality and error handling.
- Updated dependencies to include ffmpeg-python for audio processing.
2025-07-27 23:34:17 +02:00

129 lines
4.3 KiB
Python

"""Sound repository for database operations."""
from typing import Any
from sqlalchemy import desc, func
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
from app.core.logging import get_logger
from app.models.sound import Sound
logger = get_logger(__name__)
class SoundRepository:
"""Repository for sound operations."""
def __init__(self, session: AsyncSession) -> None:
"""Initialize the sound repository."""
self.session = session
async def get_by_id(self, sound_id: int) -> Sound | None:
"""Get a sound by ID."""
try:
statement = select(Sound).where(Sound.id == sound_id)
result = await self.session.exec(statement)
return result.first()
except Exception:
logger.exception("Failed to get sound by ID: %s", sound_id)
raise
async def get_by_filename(self, filename: str) -> Sound | None:
"""Get a sound by filename."""
try:
statement = select(Sound).where(Sound.filename == filename)
result = await self.session.exec(statement)
return result.first()
except Exception:
logger.exception("Failed to get sound by filename: %s", filename)
raise
async def get_by_hash(self, hash_value: str) -> Sound | None:
"""Get a sound by hash."""
try:
statement = select(Sound).where(Sound.hash == hash_value)
result = await self.session.exec(statement)
return result.first()
except Exception:
logger.exception("Failed to get sound by hash")
raise
async def get_by_type(self, sound_type: str) -> list[Sound]:
"""Get all sounds by type."""
try:
statement = select(Sound).where(Sound.type == sound_type)
result = await self.session.exec(statement)
return list(result.all())
except Exception:
logger.exception("Failed to get sounds by type: %s", sound_type)
raise
async def create(self, sound_data: dict[str, Any]) -> Sound:
"""Create a new sound."""
try:
sound = Sound(**sound_data)
self.session.add(sound)
await self.session.commit()
await self.session.refresh(sound)
except Exception:
await self.session.rollback()
logger.exception("Failed to create sound")
raise
else:
logger.info("Created new sound: %s", sound.name)
return sound
async def update(self, sound: Sound, update_data: dict[str, Any]) -> Sound:
"""Update a sound."""
try:
for field, value in update_data.items():
setattr(sound, field, value)
await self.session.commit()
await self.session.refresh(sound)
except Exception:
await self.session.rollback()
logger.exception("Failed to update sound")
raise
else:
logger.info("Updated sound: %s", sound.name)
return sound
async def delete(self, sound: Sound) -> None:
"""Delete a sound."""
try:
await self.session.delete(sound)
await self.session.commit()
logger.info("Deleted sound: %s", sound.name)
except Exception:
await self.session.rollback()
logger.exception("Failed to delete sound")
raise
async def search_by_name(self, query: str) -> list[Sound]:
"""Search sounds by name (case-insensitive)."""
try:
statement = select(Sound).where(
func.lower(Sound.name).like(f"%{query.lower()}%"),
)
result = await self.session.exec(statement)
return list(result.all())
except Exception:
logger.exception("Failed to search sounds by name: %s", query)
raise
async def get_popular_sounds(self, limit: int = 10) -> list[Sound]:
"""Get the most played sounds."""
try:
statement = (
select(Sound)
.order_by(desc(Sound.play_count))
.limit(limit)
)
result = await self.session.exec(statement)
return list(result.all())
except Exception:
logger.exception("Failed to get popular sounds")
raise