Add new sound files and update dependencies
- Added various sound files to the soundboard, including insults, quotes, and sound effects. - Introduced new dependencies: ffmpeg-python (version 0.2.0) and pydub (version 0.25.1) for audio processing. - Updated the lock file to reflect the new packages and their respective versions. - Added .gitignore files in the sounds/stream and sounds/temp directories to exclude unnecessary files.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
"""Database models."""
|
||||
|
||||
from .plan import Plan
|
||||
from .sound import Sound
|
||||
from .user import User
|
||||
from .user_oauth import UserOAuth
|
||||
|
||||
__all__ = ["Plan", "User", "UserOAuth"]
|
||||
__all__ = ["Plan", "Sound", "User", "UserOAuth"]
|
||||
|
||||
225
app/models/sound.py
Normal file
225
app/models/sound.py
Normal file
@@ -0,0 +1,225 @@
|
||||
"""Sound model for storing sound file information."""
|
||||
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
from app.database import db
|
||||
from sqlalchemy import Boolean, DateTime, Integer, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
|
||||
class SoundType(Enum):
|
||||
"""Sound type enumeration."""
|
||||
|
||||
SDB = "SDB" # Soundboard sound
|
||||
SAY = "SAY" # Text-to-speech
|
||||
STR = "STR" # Stream sound
|
||||
|
||||
|
||||
class Sound(db.Model):
|
||||
"""Sound model for storing sound file information."""
|
||||
|
||||
__tablename__ = "sounds"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
|
||||
# Sound type (SDB, SAY, or STR)
|
||||
type: Mapped[str] = mapped_column(String(3), nullable=False)
|
||||
|
||||
# Basic sound information
|
||||
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
filename: Mapped[str] = mapped_column(String(500), nullable=False)
|
||||
duration: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
size: Mapped[int] = mapped_column(Integer, nullable=False) # Size in bytes
|
||||
hash: Mapped[str] = mapped_column(String(64), nullable=False) # SHA256 hash
|
||||
|
||||
# Normalized sound information
|
||||
normalized_filename: Mapped[str | None] = mapped_column(
|
||||
String(500),
|
||||
nullable=True,
|
||||
)
|
||||
normalized_duration: Mapped[int | None] = mapped_column(
|
||||
Integer,
|
||||
nullable=True,
|
||||
)
|
||||
normalized_size: Mapped[int | None] = mapped_column(
|
||||
Integer,
|
||||
nullable=True,
|
||||
)
|
||||
normalized_hash: Mapped[str | None] = mapped_column(
|
||||
String(64),
|
||||
nullable=True,
|
||||
)
|
||||
|
||||
# Sound properties
|
||||
is_normalized: Mapped[bool] = mapped_column(
|
||||
Boolean,
|
||||
nullable=False,
|
||||
default=False,
|
||||
)
|
||||
is_music: Mapped[bool] = mapped_column(
|
||||
Boolean,
|
||||
nullable=False,
|
||||
default=False,
|
||||
)
|
||||
is_deletable: Mapped[bool] = mapped_column(
|
||||
Boolean,
|
||||
nullable=False,
|
||||
default=True,
|
||||
)
|
||||
|
||||
# Usage tracking
|
||||
play_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||||
|
||||
# Timestamps
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime,
|
||||
default=datetime.utcnow,
|
||||
nullable=False,
|
||||
)
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime,
|
||||
default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow,
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""String representation of Sound."""
|
||||
return f"<Sound {self.name} ({self.type}) - {self.play_count} plays>"
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""Convert sound to dictionary."""
|
||||
return {
|
||||
"id": self.id,
|
||||
"type": self.type,
|
||||
"name": self.name,
|
||||
"filename": self.filename,
|
||||
"duration": self.duration,
|
||||
"size": self.size,
|
||||
"hash": self.hash,
|
||||
"normalized_filename": self.normalized_filename,
|
||||
"normalized_duration": self.normalized_duration,
|
||||
"normalized_size": self.normalized_size,
|
||||
"normalized_hash": self.normalized_hash,
|
||||
"is_normalized": self.is_normalized,
|
||||
"is_music": self.is_music,
|
||||
"is_deletable": self.is_deletable,
|
||||
"play_count": self.play_count,
|
||||
"created_at": self.created_at.isoformat(),
|
||||
"updated_at": self.updated_at.isoformat(),
|
||||
}
|
||||
|
||||
def increment_play_count(self) -> None:
|
||||
"""Increment the play count for this sound."""
|
||||
self.play_count += 1
|
||||
self.updated_at = datetime.utcnow()
|
||||
db.session.commit()
|
||||
|
||||
def set_normalized_info(
|
||||
self,
|
||||
normalized_filename: str,
|
||||
normalized_duration: float,
|
||||
normalized_size: int,
|
||||
normalized_hash: str,
|
||||
) -> None:
|
||||
"""Set normalized sound information."""
|
||||
self.normalized_filename = normalized_filename
|
||||
self.normalized_duration = normalized_duration
|
||||
self.normalized_size = normalized_size
|
||||
self.normalized_hash = normalized_hash
|
||||
self.is_normalized = True
|
||||
self.updated_at = datetime.utcnow()
|
||||
|
||||
def clear_normalized_info(self) -> None:
|
||||
"""Clear normalized sound information."""
|
||||
self.normalized_filename = None
|
||||
self.normalized_duration = None
|
||||
self.normalized_hash = None
|
||||
self.normalized_size = None
|
||||
self.is_normalized = False
|
||||
self.updated_at = datetime.utcnow()
|
||||
|
||||
def update_file_info(
|
||||
self,
|
||||
filename: str,
|
||||
duration: float,
|
||||
size: int,
|
||||
hash_value: str,
|
||||
) -> None:
|
||||
"""Update file information for existing sound."""
|
||||
self.filename = filename
|
||||
self.duration = duration
|
||||
self.size = size
|
||||
self.hash = hash_value
|
||||
self.updated_at = datetime.utcnow()
|
||||
|
||||
@classmethod
|
||||
def find_by_hash(cls, hash_value: str) -> Optional["Sound"]:
|
||||
"""Find sound by hash."""
|
||||
return cls.query.filter_by(hash=hash_value).first()
|
||||
|
||||
@classmethod
|
||||
def find_by_name(cls, name: str) -> Optional["Sound"]:
|
||||
"""Find sound by name."""
|
||||
return cls.query.filter_by(name=name).first()
|
||||
|
||||
@classmethod
|
||||
def find_by_filename(cls, filename: str) -> Optional["Sound"]:
|
||||
"""Find sound by filename."""
|
||||
return cls.query.filter_by(filename=filename).first()
|
||||
|
||||
@classmethod
|
||||
def find_by_type(cls, sound_type: str) -> list["Sound"]:
|
||||
"""Find all sounds by type."""
|
||||
return cls.query.filter_by(type=sound_type).all()
|
||||
|
||||
@classmethod
|
||||
def get_most_played(cls, limit: int = 10) -> list["Sound"]:
|
||||
"""Get the most played sounds."""
|
||||
return cls.query.order_by(cls.play_count.desc()).limit(limit).all()
|
||||
|
||||
@classmethod
|
||||
def get_music_sounds(cls) -> list["Sound"]:
|
||||
"""Get all music sounds."""
|
||||
return cls.query.filter_by(is_music=True).all()
|
||||
|
||||
@classmethod
|
||||
def get_deletable_sounds(cls) -> list["Sound"]:
|
||||
"""Get all deletable sounds."""
|
||||
return cls.query.filter_by(is_deletable=True).all()
|
||||
|
||||
@classmethod
|
||||
def create_sound(
|
||||
cls,
|
||||
sound_type: str,
|
||||
name: str,
|
||||
filename: str,
|
||||
duration: float,
|
||||
size: int,
|
||||
hash_value: str,
|
||||
is_music: bool = False,
|
||||
is_deletable: bool = True,
|
||||
commit: bool = True,
|
||||
) -> "Sound":
|
||||
"""Create a new sound."""
|
||||
# Validate sound type
|
||||
if sound_type not in [t.value for t in SoundType]:
|
||||
raise ValueError(f"Invalid sound type: {sound_type}")
|
||||
|
||||
sound = cls(
|
||||
type=sound_type,
|
||||
name=name,
|
||||
filename=filename,
|
||||
duration=duration,
|
||||
size=size,
|
||||
hash=hash_value,
|
||||
is_music=is_music,
|
||||
is_deletable=is_deletable,
|
||||
)
|
||||
|
||||
db.session.add(sound)
|
||||
if commit:
|
||||
db.session.commit()
|
||||
return sound
|
||||
Reference in New Issue
Block a user