refactor: update timestamp handling to use timezone-aware datetime

This commit is contained in:
JSC
2025-07-04 19:20:56 +02:00
parent 4375718c2f
commit 1cd43a670d
5 changed files with 94 additions and 58 deletions

View File

@@ -1,11 +1,13 @@
"""Sound played tracking model."""
from datetime import datetime
from zoneinfo import ZoneInfo
from app.database import db
from sqlalchemy import DateTime, ForeignKey, Integer, func, text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.database import db
class SoundPlayed(db.Model):
"""Model to track when users play sounds."""
@@ -16,15 +18,21 @@ class SoundPlayed(db.Model):
# Foreign keys
user_id: Mapped[int] = mapped_column(
Integer, ForeignKey("users.id"), nullable=False,
Integer,
ForeignKey("users.id"),
nullable=False,
)
sound_id: Mapped[int] = mapped_column(
Integer, ForeignKey("sounds.id"), nullable=False,
Integer,
ForeignKey("sounds.id"),
nullable=False,
)
# Timestamp
played_at: Mapped[datetime] = mapped_column(
DateTime, default=datetime.utcnow, nullable=False,
DateTime,
default=lambda: datetime.now(tz=ZoneInfo("UTC")),
nullable=False,
)
# Relationships
@@ -45,17 +53,25 @@ class SoundPlayed(db.Model):
"user_id": self.user_id,
"sound_id": self.sound_id,
"played_at": self.played_at.isoformat(),
"user": {
"id": self.user.id,
"name": self.user.name,
"email": self.user.email,
} if self.user else None,
"sound": {
"id": self.sound.id,
"name": self.sound.name,
"filename": self.sound.filename,
"type": self.sound.type,
} if self.sound else None,
"user": (
{
"id": self.user.id,
"name": self.user.name,
"email": self.user.email,
}
if self.user
else None
),
"sound": (
{
"id": self.sound.id,
"name": self.sound.name,
"filename": self.sound.filename,
"type": self.sound.type,
}
if self.sound
else None
),
}
@classmethod
@@ -79,7 +95,10 @@ class SoundPlayed(db.Model):
@classmethod
def get_user_plays(
cls, user_id: int, limit: int = 50, offset: int = 0,
cls,
user_id: int,
limit: int = 50,
offset: int = 0,
) -> list["SoundPlayed"]:
"""Get recent plays for a specific user."""
return (
@@ -92,7 +111,10 @@ class SoundPlayed(db.Model):
@classmethod
def get_sound_plays(
cls, sound_id: int, limit: int = 50, offset: int = 0,
cls,
sound_id: int,
limit: int = 50,
offset: int = 0,
) -> list["SoundPlayed"]:
"""Get recent plays for a specific sound."""
return (
@@ -105,7 +127,9 @@ class SoundPlayed(db.Model):
@classmethod
def get_recent_plays(
cls, limit: int = 100, offset: int = 0,
cls,
limit: int = 100,
offset: int = 0,
) -> list["SoundPlayed"]:
"""Get recent plays across all users and sounds."""
return (
@@ -127,7 +151,9 @@ class SoundPlayed(db.Model):
@classmethod
def get_popular_sounds(
cls, limit: int = 10, days: int | None = None,
cls,
limit: int = 10,
days: int | None = None,
) -> list[dict]:
"""Get most popular sounds with play counts."""
from app.models.sound import Sound
@@ -144,7 +170,7 @@ class SoundPlayed(db.Model):
if days:
query = query.filter(
cls.played_at >= text(f"datetime('now', '-{days} days')")
cls.played_at >= text(f"datetime('now', '-{days} days')"),
)
results = query.limit(limit).all()
@@ -154,15 +180,17 @@ class SoundPlayed(db.Model):
for result in results:
sound = Sound.query.get(result.sound_id)
if sound:
popular_sounds.append({
"sound": sound.to_dict(),
"play_count": result.play_count,
"last_played": (
result.last_played.isoformat()
if result.last_played
else None
),
})
popular_sounds.append(
{
"sound": sound.to_dict(),
"play_count": result.play_count,
"last_played": (
result.last_played.isoformat()
if result.last_played
else None
),
}
)
return popular_sounds
@@ -193,7 +221,8 @@ class SoundPlayed(db.Model):
# Get favorite sound
favorite_query = (
db.session.query(
cls.sound_id, func.count(cls.id).label("play_count")
cls.sound_id,
func.count(cls.id).label("play_count"),
)
.filter_by(user_id=user_id)
.group_by(cls.sound_id)
@@ -232,4 +261,4 @@ class SoundPlayed(db.Model):
"last_play": (
last_play.played_at.isoformat() if last_play else None
),
}
}