store playcount and duration on the track table

+ allow sorting all items with those two
+ add methods to update scrobble info
This commit is contained in:
cwilvx
2024-06-30 19:33:13 +03:00
parent 4a9f804e70
commit b9ad07441a
15 changed files with 161 additions and 45 deletions
+1 -1
View File
@@ -48,7 +48,7 @@ class DbManager:
if self.commit:
self.conn.commit()
self.conn.close()
# self.conn.close()
class Base(MappedAsDataclass, DeclarativeBase):
+60 -4
View File
@@ -73,6 +73,21 @@ class Base(MasterBase, DeclarativeBase):
conn.execute(stmt)
@classmethod
def increment_scrobblecount(
cls, table: Any, field: Any, hash: str, duration: int, timestamp: int
):
cls.execute(
update(table)
.where(field == hash)
.values(
playcount=table.playcount + 1,
playduration=table.playduration + duration,
lastplayed=timestamp,
),
commit=True,
)
class TrackTable(Base):
__tablename__ = "track"
@@ -99,8 +114,12 @@ class TrackTable(Base):
track: Mapped[int] = mapped_column(Integer())
trackhash: Mapped[str] = mapped_column(String(), index=True)
is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
playcount: Mapped[int] = mapped_column(Integer())
extra: Mapped[Optional[dict[str, Any]]] = mapped_column(JSON())
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
playcount: Mapped[int] = mapped_column(Integer(), default=0)
playduration: Mapped[int] = mapped_column(Integer(), default=0)
extra: Mapped[Optional[dict[str, Any]]] = mapped_column(
JSON(), default_factory=dict
)
@classmethod
def get_all(cls):
@@ -180,6 +199,12 @@ class TrackTable(Base):
with DbManager(commit=True) as conn:
conn.execute(delete(TrackTable).where(TrackTable.filepath.in_(filepaths)))
@classmethod
def increment_playcount(cls, trackhash: str, duration: int, timestamp: int):
cls.increment_scrobblecount(
TrackTable, TrackTable.trackhash, trackhash, duration, timestamp
)
class AlbumTable(Base):
__tablename__ = "album"
@@ -199,7 +224,12 @@ class AlbumTable(Base):
title: Mapped[str] = mapped_column(String())
trackcount: Mapped[int] = mapped_column(Integer())
is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
extra: Mapped[Optional[dict[str, Any]]] = mapped_column(JSON())
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
playcount: Mapped[int] = mapped_column(Integer(), default=0)
playduration: Mapped[int] = mapped_column(Integer(), default=0)
extra: Mapped[Optional[dict[str, Any]]] = mapped_column(
JSON(), default_factory=dict
)
@classmethod
def get_all(cls):
@@ -257,6 +287,12 @@ class AlbumTable(Base):
)
return albums_to_dataclasses(result.all())
@classmethod
def increment_playcount(cls, albumhash: str, duration: int, timestamp: int):
return cls.increment_scrobblecount(
AlbumTable, AlbumTable.albumhash, albumhash, duration, timestamp
)
class ArtistTable(Base):
__tablename__ = "artist"
@@ -272,7 +308,12 @@ class ArtistTable(Base):
name: Mapped[str] = mapped_column(String(), index=True)
trackcount: Mapped[int] = mapped_column(Integer())
is_favorite: Mapped[Optional[bool]] = mapped_column(Boolean())
extra: Mapped[Optional[dict[str, Any]]] = mapped_column(JSON())
lastplayed: Mapped[int] = mapped_column(Integer(), default=0)
playcount: Mapped[int] = mapped_column(Integer(), default=0)
playduration: Mapped[int] = mapped_column(Integer(), default=0)
extra: Mapped[Optional[dict[str, Any]]] = mapped_column(
JSON(), default_factory=dict
)
@classmethod
def get_all(cls):
@@ -310,3 +351,18 @@ class ArtistTable(Base):
.limit(limit)
)
return artists_to_dataclasses(result.fetchall())
@classmethod
def increment_playcount(
cls, artisthashes: list[str], duration: int, timestamp: int
):
cls.execute(
update(cls)
.where(ArtistTable.artisthash.in_(artisthashes))
.values(
playcount=ArtistTable.playcount + 1,
playduration=ArtistTable.playduration + duration,
lastplayed=timestamp,
),
commit=True,
)
+25 -4
View File
@@ -31,7 +31,7 @@ from app.db.utils import (
)
from app.db import Base, DbManager
from app.utils.auth import hash_password
from app.utils.auth import get_current_userid, hash_password
class UserTable(Base):
@@ -160,7 +160,7 @@ class FavoritesTable(Base):
type: Mapped[str] = mapped_column(String(), index=True)
timestamp: Mapped[int] = mapped_column(Integer(), index=True)
userid: Mapped[int] = mapped_column(
Integer(), ForeignKey("user.id"), default=1, index=True
Integer(), ForeignKey("user.id", ondelete="cascade"), default=1, index=True
)
extra: Mapped[dict[str, Any]] = mapped_column(
JSON(), nullable=True, default_factory=dict
@@ -175,7 +175,7 @@ class FavoritesTable(Base):
@classmethod
def insert_item(cls, item: dict[str, Any]):
item["timestamp"] = int(datetime.datetime.now().timestamp())
item["userid"] = current_user["id"]
item["userid"] = get_current_userid()
with DbManager(commit=True) as conn:
conn.execute(insert(cls).values(item))
@@ -199,7 +199,7 @@ class FavoritesTable(Base):
result = cls.execute(
select(table)
.select_from(join(table, cls, field == cls.hash))
.where(and_(cls.type == type, cls.userid == current_user["id"]))
.where(and_(cls.type == type, cls.userid == get_current_userid()))
.offset(start)
# INFO: If start is 0, fetch all so we can get the total count
.limit(limit if start != 0 else None)
@@ -238,3 +238,24 @@ class FavoritesTable(Base):
ArtistTable, ArtistTable.artisthash, "artist", start, limit
)
return artists_to_dataclasses(result), total
class ScrobbleTable(Base):
__tablename__ = "scrobble"
id: Mapped[int] = mapped_column(primary_key=True)
trackhash: Mapped[str] = mapped_column(String(), index=True)
duration: Mapped[int] = mapped_column(Integer())
timestamp: Mapped[int] = mapped_column(Integer())
source: Mapped[str] = mapped_column(String())
userid: Mapped[int] = mapped_column(
Integer(), ForeignKey("user.id", ondelete="cascade"), index=True
)
extra: Mapped[dict[str, Any]] = mapped_column(
JSON(), nullable=True, default_factory=dict
)
@classmethod
def add(cls, item: dict[str, Any]):
item["userid"] = get_current_userid()
return cls.insert_one(item)