add recently played playlist

This commit is contained in:
cwilvx
2024-05-23 12:42:36 +03:00
parent 30768dd5d6
commit bbcacf81bd
10 changed files with 142 additions and 62 deletions
+4
View File
@@ -3,4 +3,8 @@
<!-- TODO: ELABORATE --> <!-- TODO: ELABORATE -->
- Auth - Auth
## Improvements
- The context menu now doesn't take forever to open up
- Merged "Save as Playlist" with "Add to Playlist" > "New Playlist"
## Development ## Development
+2 -1
View File
@@ -1,11 +1,12 @@
# TODO # TODO
- Migrations: - Migrations:
1. Move userdata to new hashing algorithm 1. Move userdata to new hashing algorithm
- Store on the correct user account: - Store (and read) from the correct user account:
1. Playlists 1. Playlists
2. Favorites 2. Favorites
- Package jsoni and publish on PyPi - Package jsoni and publish on PyPi
# DONE # DONE
- Add recently played playlist
- Move user track logs to user zero - Move user track logs to user zero
- Move future logs to appropriate user id - Move future logs to appropriate user id
+2 -2
View File
@@ -2,7 +2,7 @@ from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
from app.api.apischemas import GenericLimitSchema from app.api.apischemas import GenericLimitSchema
from app.lib.home.recentlyadded import get_recent_items from app.lib.home.recentlyadded import get_recently_added_items
from app.lib.home.recentlyplayed import get_recently_played from app.lib.home.recentlyplayed import get_recently_played
bp_tag = Tag(name="Home", description="Homepage items") bp_tag = Tag(name="Home", description="Homepage items")
@@ -14,7 +14,7 @@ def get_recently_added(query: GenericLimitSchema):
""" """
Get recently added Get recently added
""" """
return {"items": get_recent_items(query.limit)} return {"items": get_recently_added_items(query.limit)}
@api.get("/recents/played") @api.get("/recents/played")
+26 -12
View File
@@ -15,6 +15,8 @@ from app import models
from app.db.sqlite.playlists import SQLitePlaylistMethods from app.db.sqlite.playlists import SQLitePlaylistMethods
from app.lib import playlistlib from app.lib import playlistlib
from app.lib.albumslib import sort_by_track_no from app.lib.albumslib import sort_by_track_no
from app.lib.home.recentlyadded import get_recently_added_playlist
from app.lib.home.recentlyplayed import get_recently_played_playlist
from app.serializers.playlist import serialize_for_card from app.serializers.playlist import serialize_for_card
from app.store.tracks import TrackStore from app.store.tracks import TrackStore
from app.utils.dates import create_new_date, date_string_to_time_passed from app.utils.dates import create_new_date, date_string_to_time_passed
@@ -174,6 +176,18 @@ class GetPlaylistQuery(BaseModel):
no_tracks: bool = Field(False, description="Whether to include tracks") no_tracks: bool = Field(False, description="Whether to include tracks")
def format_custom_playlist(playlist: models.Playlist, tracks: list[models.Track]):
duration = sum(t.duration for t in tracks)
playlist.set_duration(duration)
playlist = serialize_for_card(playlist)
return {
"info": playlist,
"tracks": tracks,
}
@api.get("/<playlistid>") @api.get("/<playlistid>")
def get_playlist(path: PlaylistIDPath, query: GetPlaylistQuery): def get_playlist(path: PlaylistIDPath, query: GetPlaylistQuery):
""" """
@@ -182,18 +196,18 @@ def get_playlist(path: PlaylistIDPath, query: GetPlaylistQuery):
no_tracks = query.no_tracks no_tracks = query.no_tracks
playlistid = path.playlistid playlistid = path.playlistid
is_recently_added = playlistid == "recentlyadded" custom_playlists = [
{"name": "recentlyadded", "handler": get_recently_added_playlist},
{"name": "recentlyplayed", "handler": get_recently_played_playlist},
]
is_custom = playlistid in {p["name"] for p in custom_playlists}
if is_recently_added: if is_custom:
playlist, tracks = playlistlib.get_recently_added_playlist() handler = next(
p["handler"] for p in custom_playlists if p["name"] == playlistid
tracks = remove_duplicates(tracks) )
duration = sum(t.duration for t in tracks) playlist, tracks = handler()
return format_custom_playlist(playlist, tracks)
playlist.set_duration(duration)
playlist = serialize_for_card(playlist)
return {"info": playlist, "tracks": tracks}
playlist = PL.get_playlist_by_id(int(playlistid)) playlist = PL.get_playlist_by_id(int(playlistid))
@@ -247,7 +261,7 @@ def update_playlist_info(path: PlaylistIDPath, form: UpdatePlaylistForm):
settings["has_gif"] = False settings["has_gif"] = False
playlist = { playlist = {
"id": playlistid, "id": int(playlistid),
"image": db_playlist.image, "image": db_playlist.image,
"last_updated": create_new_date(), "last_updated": create_new_date(),
"name": str(form.name).strip(), "name": str(form.name).strip(),
+17 -2
View File
@@ -1,11 +1,12 @@
from app.db.sqlite.utils import SQLiteManager from app.db.sqlite.utils import SQLiteManager
from app.models.logger import TrackLog as TrackLog
class SQLiteTrackLogger: class SQLiteTrackLogger:
@classmethod @classmethod
def insert_track(cls, trackhash: str, duration: int, source: str, timestamp: int, userid: int): def insert_track(cls, trackhash: str, duration: int, source: str, timestamp: int, userid: int):
""" """
Inserts a track into the database Inserts a track play record into the database
""" """
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
@@ -26,7 +27,7 @@ class SQLiteTrackLogger:
@classmethod @classmethod
def get_all(cls): def get_all(cls):
""" """
Returns all tracks from the database Returns all track play records from the database
""" """
with SQLiteManager(userdata_db=True) as cur: with SQLiteManager(userdata_db=True) as cur:
@@ -36,3 +37,17 @@ class SQLiteTrackLogger:
rows = cur.fetchall() rows = cur.fetchall()
return rows return rows
@classmethod
def get_recently_played(cls, start: int = 0, limit: int = 100):
"""
Returns a list of recently played tracks
"""
with SQLiteManager(userdata_db=True) as cur:
sql = """SELECT * FROM track_logger ORDER BY timestamp DESC LIMIT ?,?"""
cur.execute(sql, (start, limit))
rows = cur.fetchall()
return [TrackLog(*row) for row in rows]
+33 -5
View File
@@ -1,6 +1,7 @@
import os from datetime import datetime
from flask import g from app.lib.playlistlib import get_first_4_images
from app.models.playlist import Playlist
from app.models.track import Track from app.models.track import Track
from app.store.tracks import TrackStore from app.store.tracks import TrackStore
from app.store.albums import AlbumStore from app.store.albums import AlbumStore
@@ -12,7 +13,7 @@ from app.serializers.artist import serialize_for_card
from itertools import groupby from itertools import groupby
from app.utils.dates import timestamp_to_time_passed from app.utils.dates import create_new_date, date_string_to_time_passed, timestamp_to_time_passed
older_albums = set() older_albums = set()
older_artists = set() older_artists = set()
@@ -191,7 +192,7 @@ def group_track_by_folders(tracks: Track):
return sorted(groups, key=lambda group: group["time"], reverse=True) return sorted(groups, key=lambda group: group["time"], reverse=True)
def get_recent_items(limit: int = 7): def get_recently_added_items(limit: int = 7):
tracks = sorted(TrackStore.tracks, key=lambda t: t.created_date) tracks = sorted(TrackStore.tracks, key=lambda t: t.created_date)
groups = group_track_by_folders(tracks) groups = group_track_by_folders(tracks)
@@ -216,6 +217,33 @@ def get_recent_items(limit: int = 7):
return recent_items return recent_items
def get_recent_tracks(limit: int):
def get_recently_added_playlist(limit: int = 100):
playlist = Playlist(
id="recentlyadded",
name="Recently Added",
image=None,
last_updated="Now",
settings={},
trackhashes=[],
)
tracks = get_recently_added_tracks(limit=limit)
try:
# Create date to show as last updated
date = datetime.fromtimestamp(tracks[0].created_date)
except IndexError:
return playlist, []
playlist.last_updated = date_string_to_time_passed(create_new_date(date))
images = get_first_4_images(tracks=tracks)
playlist.images = images
playlist.set_count(len(tracks))
return playlist, tracks
def get_recently_added_tracks(limit: int):
tracks = sorted(TrackStore.tracks, key=lambda t: t.created_date, reverse=True) tracks = sorted(TrackStore.tracks, key=lambda t: t.created_date, reverse=True)
return tracks[:limit] return tracks[:limit]
+47 -6
View File
@@ -1,27 +1,37 @@
from datetime import datetime
import os import os
from app.models.logger import Track as 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.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.utils.dates import timestamp_to_time_passed 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.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.playlistlib import get_first_4_images, 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
entries = db.get_all() entries = db.get_all()
items = [] items = []
added = set() added = set()
custom_playlists = [
{"name": "recentlyadded", "handler": get_recently_added_playlist},
{"name": "recentlyplayed", "handler": get_recently_played_playlist},
]
for entry in entries: for entry in entries:
if len(items) >= limit: if len(items) >= limit:
break break
@@ -112,10 +122,13 @@ def get_recently_played(limit=7):
continue continue
if entry.type == "playlist": if entry.type == "playlist":
is_recently_added = entry.type_src == "recentlyadded" is_custom = entry.type_src in [i["name"] for i in custom_playlists]
# is_recently_added = entry.type_src == "recentlyadded"
if is_recently_added: if is_custom:
playlist, _ = get_recently_added_playlist() playlist, _ = next(
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]
playlist = serialize_playlist( playlist = serialize_playlist(
@@ -186,3 +199,31 @@ def get_recently_played(limit=7):
) )
return items return items
def get_recently_played_tracks(limit: int):
records = db.get_recently_played(start=0, limit=limit)
last_updated = records[0].timestamp
tracks = TrackStore.get_tracks_by_trackhashes([r.trackhash for r in records])
return tracks, last_updated
def get_recently_played_playlist(limit: int = 100):
playlist = Playlist(
id="recentlyplayed",
name="Recently Played",
image=None,
last_updated="Now",
settings={},
trackhashes=[],
)
tracks, timestamp = get_recently_played_tracks(limit)
date = datetime.fromtimestamp(timestamp)
playlist.last_updated = date_string_to_time_passed(create_new_date(date))
images = get_first_4_images(tracks=tracks)
playlist.images = images
playlist.set_count(len(tracks))
return playlist, tracks
-31
View File
@@ -5,18 +5,14 @@ This library contains all the functions related to playlists.
import os import os
import random import random
import string import string
from datetime import datetime
from typing import Any from typing import Any
from PIL import Image, ImageSequence from PIL import Image, ImageSequence
from app import settings from app import settings
from app.lib.home.recentlyadded import get_recent_tracks
from app.models.playlist import Playlist
from app.models.track import Track from app.models.track import Track
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.utils.dates import create_new_date, date_string_to_time_passed
def create_thumbnail(image: Any, img_path: str) -> str: def create_thumbnail(image: Any, img_path: str) -> str:
@@ -133,30 +129,3 @@ def get_first_4_images(
return images return images
return duplicate_images(images) return duplicate_images(images)
def get_recently_added_playlist(limit: int = 100):
playlist = Playlist(
id="recentlyadded",
name="Recently Added",
image=None,
last_updated="Now",
settings={},
trackhashes=[],
)
tracks = get_recent_tracks(limit=limit)
try:
# Create date to show as last updated
date = datetime.fromtimestamp(tracks[0].created_date)
except IndexError:
return playlist, []
playlist.last_updated = date_string_to_time_passed(create_new_date(date))
images = get_first_4_images(tracks=tracks)
playlist.images = images
playlist.set_count(len(tracks))
return playlist, tracks
+1 -1
View File
@@ -3,7 +3,7 @@ from typing import Literal
@dataclass @dataclass
class Track: class TrackLog:
""" """
Track play logger model Track play logger model
""" """
+10 -2
View File
@@ -129,10 +129,18 @@ class TrackStore:
""" """
Returns a list of tracks by their hashes. Returns a list of tracks by their hashes.
""" """
hash_set = set(trackhashes)
set_len = len(hash_set)
trackhashes = " ".join(trackhashes) tracks = []
tracks = [track for track in cls.tracks if track.trackhash in trackhashes] for track in cls.tracks:
if track.trackhash in hash_set:
tracks.append(track)
if len(tracks) == set_len:
break
# sort the tracks in the order of the given trackhashes
tracks.sort(key=lambda t: trackhashes.index(t.trackhash)) tracks.sort(key=lambda t: trackhashes.index(t.trackhash))
return tracks return tracks