port: recent items for homepage

This commit is contained in:
cwilvx
2024-06-30 23:11:33 +03:00
parent 5759521de0
commit a3c4558d52
9 changed files with 92 additions and 37 deletions
+1
View File
@@ -47,3 +47,4 @@
- Remove duplicates on artist page (test with Hanson) - Remove duplicates on artist page (test with Hanson)
- Test foreign keys on delete - Test foreign keys on delete
- Map scrobble info on app start - Map scrobble info on app start
- Make home page recent items faster!
+5
View File
@@ -3,6 +3,7 @@ from typing import Any
from sqlalchemy import ( from sqlalchemy import (
create_engine, create_engine,
delete, delete,
func,
insert, insert,
select, select,
) )
@@ -81,6 +82,10 @@ class Base(MappedAsDataclass, DeclarativeBase):
def all(cls): def all(cls):
return cls.execute(select(cls)) return cls.execute(select(cls))
@classmethod
def count(cls):
return cls.execute(select(func.count()).select_from(cls)).scalar()
def create_all(): def create_all():
Base().metadata.create_all(engine) Base().metadata.create_all(engine)
+11 -3
View File
@@ -35,9 +35,13 @@ class Base(MasterBase, DeclarativeBase):
if cls.__tablename__ == "track": if cls.__tablename__ == "track":
stmt = select(TrackTable.trackhash).where(cls.last_mod < create_date) stmt = select(TrackTable.trackhash).where(cls.last_mod < create_date)
elif cls.__tablename__ == "album": elif cls.__tablename__ == "album":
stmt = select(AlbumTable.albumhash).where(cls.created_date < create_date) stmt = select(AlbumTable.albumhash).where(
cls.created_date < create_date
)
elif cls.__tablename__ == "artist": elif cls.__tablename__ == "artist":
stmt = select(ArtistTable.artisthash).where(cls.created_date < create_date) stmt = select(ArtistTable.artisthash).where(
cls.created_date < create_date
)
result = conn.execute(stmt) result = conn.execute(stmt)
return {row[0] for row in result.fetchall()} return {row[0] for row in result.fetchall()}
@@ -206,6 +210,11 @@ class TrackTable(Base):
return tracks_to_dataclasses(result.fetchall()) return tracks_to_dataclasses(result.fetchall())
@classmethod
def get_recently_played(cls, limit: int):
result = cls.execute(select(cls).order_by(cls.lastplayed.desc()).limit(limit))
return tracks_to_dataclasses(result.fetchall())
@classmethod @classmethod
def remove_tracks_by_filepaths(cls, filepaths: set[str]): def remove_tracks_by_filepaths(cls, filepaths: set[str]):
with DbManager(commit=True) as conn: with DbManager(commit=True) as conn:
@@ -250,7 +259,6 @@ class AlbumTable(Base):
all = result.fetchall() all = result.fetchall()
return albums_to_dataclasses(all) return albums_to_dataclasses(all)
@classmethod @classmethod
def get_album_by_albumhash(cls, hash: str): def get_album_by_albumhash(cls, hash: str):
with DbManager() as conn: with DbManager() as conn:
+15
View File
@@ -25,6 +25,8 @@ from app.db.utils import (
plugin_to_dataclasses, plugin_to_dataclasses,
similar_artist_to_dataclass, similar_artist_to_dataclass,
similar_artists_to_dataclass, similar_artists_to_dataclass,
tracklog_to_dataclass,
tracklog_to_dataclasses,
tracks_to_dataclasses, tracks_to_dataclasses,
user_to_dataclass, user_to_dataclass,
user_to_dataclasses, user_to_dataclasses,
@@ -166,6 +168,7 @@ class FavoritesTable(Base):
JSON(), nullable=True, default_factory=dict JSON(), nullable=True, default_factory=dict
) )
@classmethod @classmethod
def get_all(cls): def get_all(cls):
with DbManager() as conn: with DbManager() as conn:
@@ -259,3 +262,15 @@ class ScrobbleTable(Base):
def add(cls, item: dict[str, Any]): def add(cls, item: dict[str, Any]):
item["userid"] = get_current_userid() item["userid"] = get_current_userid()
return cls.insert_one(item) return cls.insert_one(item)
@classmethod
def get_all(cls, start: int, limit: int):
result = cls.execute(
select(cls)
.where(cls.userid == get_current_userid())
.order_by(cls.timestamp.desc())
.offset(start)
.limit(limit)
)
return tracklog_to_dataclasses(result.fetchall())
+8
View File
@@ -3,6 +3,7 @@ from typing import Any
from app.models import Album as AlbumModel, Artist as ArtistModel, Track as TrackModel from app.models import Album as AlbumModel, Artist as ArtistModel, Track as TrackModel
from app.models.favorite import Favorite from app.models.favorite import Favorite
from app.models.lastfm import SimilarArtist from app.models.lastfm import SimilarArtist
from app.models.logger import TrackLog
from app.models.plugins import Plugin from app.models.plugins import Plugin
from app.models.user import User from app.models.user import User
@@ -73,3 +74,10 @@ def plugin_to_dataclass(entry: Any):
def plugin_to_dataclasses(entries: Any): def plugin_to_dataclasses(entries: Any):
return [plugin_to_dataclass(entry) for entry in entries] return [plugin_to_dataclass(entry) for entry in entries]
def tracklog_to_dataclass(entry: Any):
entry_dict = entry._asdict()
return TrackLog(**entry_dict)
def tracklog_to_dataclasses(entries: Any):
return [tracklog_to_dataclass(entry) for entry in entries]
+42 -27
View File
@@ -1,29 +1,36 @@
from datetime import datetime from datetime import datetime
import os import os
from app.db.libdata import AlbumTable, ArtistTable, TrackTable
from app.db.userdata import FavoritesTable, ScrobbleTable
from app.models.logger import TrackLog from app.models.logger import TrackLog
from app.db.sqlite.logger.tracks import SQLiteTrackLogger as db # from app.db.sqlite.logger.tracks import SQLiteTrackLogger as db
from app.db.sqlite.playlists import SQLitePlaylistMethods as pdb # from app.db.sqlite.playlists import SQLitePlaylistMethods as pdb
from app.db.sqlite.favorite import SQLiteFavoriteMethods as fdb # from app.db.sqlite.favorite import SQLiteFavoriteMethods as fdb
from app.models.playlist import Playlist from app.models.playlist import Playlist
from app.serializers.track import serialize_track from app.serializers.track import serialize_track
from app.serializers.album import album_serializer from app.serializers.album import album_serializer
from app.lib.playlistlib import get_first_4_images from app.lib.playlistlib import get_first_4_images
from app.utils.dates import create_new_date, date_string_to_time_passed, timestamp_to_time_passed from app.store.folder import FolderStore
from app.utils.dates import (
create_new_date,
date_string_to_time_passed,
timestamp_to_time_passed,
)
from app.serializers.artist import serialize_for_card from app.serializers.artist import serialize_for_card
from app.serializers.playlist import serialize_for_card as serialize_playlist from app.serializers.playlist import serialize_for_card as serialize_playlist
from app.lib.home.recentlyadded import get_recently_added_playlist from app.lib.home.recentlyadded import get_recently_added_playlist
from app.store.albums import AlbumStore # from app.store.albums import AlbumStore
from app.store.tracks import TrackStore # from app.store.tracks import TrackStore
from app.store.artists import ArtistStore # from app.store.artists import ArtistStore
def get_recently_played(limit=7): def get_recently_played(limit=7):
# TODO: Paginate this # TODO: Paginate this
entries = db.get_all() # entries = db.get_all()
entries = ScrobbleTable.get_all(0, 200)
items = [] items = []
added = set() added = set()
@@ -36,7 +43,7 @@ def get_recently_played(limit=7):
if len(items) >= limit: if len(items) >= limit:
break break
entry = TrackLog(*entry) # entry = TrackLog(*entry)
if entry.source in added: if entry.source in added:
continue continue
@@ -44,7 +51,8 @@ def get_recently_played(limit=7):
added.add(entry.source) added.add(entry.source)
if entry.type == "album": if entry.type == "album":
album = AlbumStore.get_album_by_hash(entry.type_src) # album = AlbumStore.get_album_by_hash(entry.type_src)
album = AlbumTable.get_album_by_albumhash(entry.type_src)
if album is None: if album is None:
continue continue
@@ -72,7 +80,8 @@ def get_recently_played(limit=7):
continue continue
if entry.type == "artist": if entry.type == "artist":
artist = ArtistStore.get_artist_by_hash(entry.type_src) # artist = ArtistStore.get_artist_by_hash(entry.type_src)
artist = ArtistTable.get_artist_by_hash(entry.type_src)
if artist is None: if artist is None:
continue continue
@@ -107,13 +116,14 @@ def get_recently_played(limit=7):
# print(folder) # print(folder)
# folder = os.path.join("/", folder, "") # folder = os.path.join("/", folder, "")
# print(folder) # print(folder)
count = len([t for t in TrackStore.tracks if t.folder == folder]) # count = len([t for t in TrackStore.tracks if t.folder == folder])
count = FolderStore.count_tracks_containing_paths([folder])
items.append( items.append(
{ {
"type": "folder", "type": "folder",
"item": { "item": {
"path": folder, "path": folder,
"count": count, "count": count[0]["trackcount"],
"help_text": "folder", "help_text": "folder",
"time": timestamp_to_time_passed(entry.timestamp), "time": timestamp_to_time_passed(entry.timestamp),
}, },
@@ -122,12 +132,15 @@ def get_recently_played(limit=7):
continue continue
if entry.type == "playlist": if entry.type == "playlist":
continue
is_custom = entry.type_src in [i["name"] for i in custom_playlists] is_custom = entry.type_src in [i["name"] for i in custom_playlists]
# is_recently_added = entry.type_src == "recentlyadded" # is_recently_added = entry.type_src == "recentlyadded"
if is_custom: if is_custom:
playlist, _ = next( playlist, _ = next(
i["handler"]() for i in custom_playlists if i["name"] == entry.type_src i["handler"]()
for i in custom_playlists
if i["name"] == entry.type_src
) )
playlist.images = [i["image"] for i in playlist.images] playlist.images = [i["image"] for i in playlist.images]
@@ -175,16 +188,17 @@ def get_recently_played(limit=7):
"type": "favorite_tracks", "type": "favorite_tracks",
"item": { "item": {
"help_text": "playlist", "help_text": "playlist",
"count": fdb.get_track_count(), "count": FavoritesTable.count(),
"time": timestamp_to_time_passed(entry.timestamp), "time": timestamp_to_time_passed(entry.timestamp),
}, },
} }
) )
continue continue
try: # track = TrackStore.get_tracks_by_trackhashes([entry.trackhash])[0]
track = TrackStore.get_tracks_by_trackhashes([entry.trackhash])[0] track = TrackTable.get_track_by_trackhash(entry.trackhash)
except IndexError:
if track is None:
continue continue
track = serialize_track(track) track = serialize_track(track)
@@ -202,10 +216,12 @@ def get_recently_played(limit=7):
def get_recently_played_tracks(limit: int): def get_recently_played_tracks(limit: int):
records = db.get_recently_played(start=0, limit=limit) # records = db.get_recently_played(start=0, limit=limit)
last_updated = records[0].timestamp # last_updated = records[0].timestamp
tracks = TrackStore.get_tracks_by_trackhashes([r.trackhash for r in records]) # tracks = TrackStore.get_tracks_by_trackhashes([r.trackhash for r in records])
return tracks, last_updated # return tracks, last_updated
return TrackTable.get_recently_played(limit)
def get_recently_played_playlist(limit: int = 100): def get_recently_played_playlist(limit: int = 100):
playlist = Playlist( playlist = Playlist(
@@ -217,13 +233,12 @@ def get_recently_played_playlist(limit: int = 100):
trackhashes=[], trackhashes=[],
) )
tracks, timestamp = get_recently_played_tracks(limit) tracks = get_recently_played_tracks(limit)
date = datetime.fromtimestamp(tracks[0].lastplayed)
date = datetime.fromtimestamp(timestamp)
playlist.last_updated = date_string_to_time_passed(create_new_date(date)) playlist.last_updated = date_string_to_time_passed(create_new_date(date))
images = get_first_4_images(tracks=tracks) images = get_first_4_images(tracks=tracks)
playlist.images = images playlist.images = images
playlist.set_count(len(tracks)) playlist.set_count(len(tracks))
return playlist, tracks return playlist, tracks
+6 -6
View File
@@ -10,10 +10,8 @@ from typing import Any
from PIL import Image, ImageSequence from PIL import Image, ImageSequence
from app import settings from app import settings
from app.db.libdata import AlbumTable, TrackTable
from app.models.track import Track from app.models.track import Track
from app.store.albums import AlbumStore
from app.store.tracks import TrackStore
def create_thumbnail(image: Any, img_path: str) -> str: def create_thumbnail(image: Any, img_path: str) -> str:
""" """
@@ -105,7 +103,8 @@ def get_first_4_images(
tracks: list[Track] = [], trackhashes: list[str] = [] tracks: list[Track] = [], trackhashes: list[str] = []
) -> list[dict["str", str]]: ) -> list[dict["str", str]]:
if len(trackhashes) > 0: if len(trackhashes) > 0:
tracks = TrackStore.get_tracks_by_trackhashes(trackhashes) # tracks = TrackStore.get_tracks_by_trackhashes(trackhashes)
tracks = TrackTable.get_tracks_by_trackhashes(trackhashes)
albums = [] albums = []
@@ -116,11 +115,12 @@ def get_first_4_images(
if len(albums) == 4: if len(albums) == 4:
break break
albums = AlbumStore.get_albums_by_hashes(albums) # albums = AlbumStore.get_albums_by_hashes(albums)
albums = AlbumTable.get_albums_by_albumhashes(albums)
images = [ images = [
{ {
"image": album.image, "image": album.image,
"color": "".join(album.colors), "color": album.color,
} }
for album in albums for album in albums
] ]
+2
View File
@@ -1,3 +1,4 @@
import gc
import os import os
from pprint import pprint from pprint import pprint
from time import time from time import time
@@ -280,6 +281,7 @@ class IndexEverything:
# pass # pass
CordinateMedia(instance_key=str(time())) CordinateMedia(instance_key=str(time()))
gc.collect()
@background @background
+2 -1
View File
@@ -1,5 +1,5 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Literal from typing import Any, Literal
@dataclass @dataclass
@@ -14,6 +14,7 @@ class TrackLog:
timestamp: int timestamp: int
source: str source: str
userid: int userid: int
extra: dict[str, Any]
type = "track" type = "track"
type_src = None type_src = None