add timestamp to favorite entries

+ convert useBisection into a function
This commit is contained in:
mungai-njoroge
2024-03-10 17:21:22 +03:00
committed by Mungai Njoroge
parent fb635ff35f
commit 766eb388b2
9 changed files with 95 additions and 52 deletions
+2 -2
View File
@@ -183,7 +183,7 @@ def get_all_artist_tracks(path: ArtistHashSchema):
"""
tracks = TrackStore.get_tracks_by_artisthash(path.artisthash)
return {"tracks": serialize_tracks(tracks)}
return serialize_tracks(tracks)
@api.get("/<artisthash>/similar")
@@ -208,7 +208,7 @@ def get_similar_artists(path: ArtistHashSchema, query: ArtistLimitSchema):
if len(similar) > limit:
similar = random.sample(similar, limit)
return {"artists": similar[:limit]}
return similar[:limit]
# TODO: Rewrite this file using generators where possible
+22 -12
View File
@@ -1,21 +1,26 @@
from typing import List, TypeVar
from flask import Blueprint, request
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from app.models import FavType
from app.serializers.album import serialize_for_card, serialize_for_card_many
from app.serializers.artist import serialize_for_card as serialize_artist
from app.utils.bisection import use_bisection
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from app.serializers.track import serialize_track, serialize_tracks
from app.utils.bisection import UseBisection
from app.serializers.artist import serialize_for_card as serialize_artist
from app.serializers.album import serialize_for_card, serialize_for_card_many
from app.store.artists import ArtistStore
from app.store.albums import AlbumStore
from app.store.tracks import TrackStore
from app.store.artists import ArtistStore
from app.utils.dates import timestamp_to_time_passed
api = Blueprint("favorite", __name__, url_prefix="/")
def remove_none(items: list):
T = TypeVar("T")
def remove_none(items: List[T]) -> List[T]:
return [i for i in items if i is not None]
@@ -76,7 +81,7 @@ def get_favorite_albums():
src_albums = sorted(AlbumStore.albums, key=lambda x: x.albumhash)
fav_albums = UseBisection(src_albums, "albumhash", albumhashes)()
fav_albums = use_bisection(src_albums, "albumhash", albumhashes)
fav_albums = remove_none(fav_albums)
if limit == 0:
@@ -99,7 +104,7 @@ def get_favorite_tracks():
trackhashes.reverse()
src_tracks = sorted(TrackStore.tracks, key=lambda x: x.trackhash)
tracks = UseBisection(src_tracks, "trackhash", trackhashes)()
tracks = use_bisection(src_tracks, "trackhash", trackhashes)
tracks = remove_none(tracks)
if limit == 0:
@@ -123,7 +128,7 @@ def get_favorite_artists():
src_artists = sorted(ArtistStore.artists, key=lambda x: x.artisthash)
artists = UseBisection(src_artists, "artisthash", artisthashes)()
artists = use_bisection(src_artists, "artisthash", artisthashes)
artists = remove_none(artists)
if limit == 0:
@@ -169,6 +174,7 @@ def get_all_favorites():
artist_master_hash = set(a.artisthash for a in ArtistStore.artists)
for fav in favs:
# INFO: hash is [1], type is [2], timestamp is [3]
hash = fav[1]
if fav[2] == FavType.track:
tracks.append(hash) if hash in track_master_hash else None
@@ -189,9 +195,9 @@ def get_all_favorites():
src_albums = sorted(AlbumStore.albums, key=lambda x: x.albumhash)
src_artists = sorted(ArtistStore.artists, key=lambda x: x.artisthash)
tracks = UseBisection(src_tracks, "trackhash", tracks, limit=track_limit)()
albums = UseBisection(src_albums, "albumhash", albums, limit=album_limit)()
artists = UseBisection(src_artists, "artisthash", artists, limit=artist_limit)()
tracks = use_bisection(src_tracks, "trackhash", tracks, limit=track_limit)
albums = use_bisection(src_albums, "albumhash", albums, limit=album_limit)
artists = use_bisection(src_artists, "artisthash", artists, limit=artist_limit)
tracks = remove_none(tracks)
albums = remove_none(albums)
@@ -201,6 +207,7 @@ def get_all_favorites():
# first_n = favs
for fav in favs:
# INFO: hash is [1], type is [2], timestamp is [3]
if len(recents) >= largest:
break
@@ -212,6 +219,7 @@ def get_all_favorites():
album = serialize_for_card(album)
album["help_text"] = "album"
album["time"] = timestamp_to_time_passed(fav[3])
recents.append(
{
@@ -228,6 +236,7 @@ def get_all_favorites():
artist = serialize_artist(artist)
artist["help_text"] = "artist"
artist["time"] = timestamp_to_time_passed(fav[3])
recents.append(
{
@@ -244,6 +253,7 @@ def get_all_favorites():
track = serialize_track(track)
track["help_text"] = "track"
track["time"] = timestamp_to_time_passed(fav[3])
recents.append({"type": "track", "item": track})
+4 -2
View File
@@ -1,3 +1,4 @@
from datetime import datetime
from app.models import FavType
from .utils import SQLiteManager
@@ -26,9 +27,10 @@ class SQLiteFavoriteMethods:
if cls.check_is_favorite(fav_hash, fav_type):
return
sql = """INSERT INTO favorites(type, hash) VALUES(?,?)"""
sql = """INSERT INTO favorites(type, hash, timestamp) VALUES(?,?,?)"""
current_timestamp = datetime.now().timestamp()
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql, (fav_type, fav_hash))
cur.execute(sql, (fav_type, fav_hash, current_timestamp))
cur.close()
@classmethod
+2 -1
View File
@@ -15,7 +15,8 @@ CREATE TABLE IF NOT EXISTS playlists (
CREATE TABLE IF NOT EXISTS favorites (
id integer PRIMARY KEY,
hash text not null,
type text not null
type text not null,
timestamp integer not null default 0
);
CREATE TABLE IF NOT EXISTS settings (
+4 -1
View File
@@ -13,7 +13,7 @@ PS: Fuck that! Do what you want.
from app.db.sqlite.migrations import MigrationManager
from app.logger import log
from app.migrations import v1_3_0
from app.migrations import v1_3_0, v1_4_9
from app.migrations.base import Migration
migrations: list[list[Migration]] = [
@@ -26,6 +26,9 @@ migrations: list[list[Migration]] = [
v1_3_0.MovePlaylistsAndFavoritesTo10BitHashes,
v1_3_0.RemoveAllTracks,
v1_3_0.UpdateAppSettingsTable,
],
[
v1_4_9.AddTimestampToFavoritesTable
]
]
+34
View File
@@ -0,0 +1,34 @@
from app.db.sqlite.utils import SQLiteManager
from app.migrations.base import Migration
class AddTimestampToFavoritesTable(Migration):
"""
Adds a timestamp column to the favorites table.
"""
@staticmethod
def migrate():
# INFO: add timestamp column with automatic current timestamp
sql = f"ALTER TABLE favorites ADD COLUMN timestamp INTEGER NOT NULL DEFAULT 0"
# INFO: execute the sql
with SQLiteManager(userdata_db=True) as cur:
cur.execute(sql)
# INFO: Update the timestamp column with the current timestamp
cur.execute("UPDATE favorites SET timestamp = strftime('%s', 'now')")
cur.close()
class MoveHashesToSha1(Migration):
"""
Moves the 10 bit item hashes from sha256 to sha1 which is
faster and more lenient on less powerful devices.
Thanks to [@tcsenpai](https:github.com/tcsenpai) for the contribution.
"""
pass
# INFO: Apparentlly, every single table is affected by this migration.
# NOTE: Use generators to avoid memory issues.
+3 -3
View File
@@ -3,7 +3,7 @@ import json
from app.db.sqlite.artistcolors import SQLiteArtistMethods as ardb
from app.lib.artistlib import get_all_artists
from app.models import Artist
from app.utils.bisection import UseBisection
from app.utils.bisection import use_bisection
from app.utils.customlist import CustomList
from app.utils.progressbar import tqdm
@@ -72,7 +72,7 @@ class ArtistStore:
"""
artists = sorted(cls.artists, key=lambda x: x.artisthash)
try:
artist = UseBisection(artists, "artisthash", [artisthash])()[0]
artist = use_bisection(artists, "artisthash", [artisthash])[0]
return artist
except IndexError:
return None
@@ -83,7 +83,7 @@ class ArtistStore:
Returns artists by their hashes.
"""
artists = sorted(cls.artists, key=lambda x: x.artisthash)
artists = UseBisection(artists, "artisthash", artisthashes)()
artists = use_bisection(artists, "artisthash", artisthashes)
return [a for a in artists if a is not None]
@classmethod
+2 -2
View File
@@ -3,7 +3,7 @@
from app.db.sqlite.favorite import SQLiteFavoriteMethods as favdb
from app.db.sqlite.tracks import SQLiteTrackMethods as tdb
from app.models import Track
from app.utils.bisection import UseBisection
from app.utils.bisection import use_bisection
from app.utils.customlist import CustomList
from app.utils.remove_duplicates import remove_duplicates
@@ -153,7 +153,7 @@ class TrackStore:
Returns all tracks matching the given paths.
"""
tracks = sorted(cls.tracks, key=lambda x: x.filepath)
tracks = UseBisection(tracks, "filepath", paths)()
tracks = use_bisection(tracks, "filepath", paths)
return [track for track in tracks if track is not None]
@classmethod
+16 -23
View File
@@ -1,52 +1,45 @@
from app.models.track import Track
from typing import List, Optional, TypeVar
T = TypeVar("T")
class UseBisection:
def use_bisection(
source: List[T], key: str, queries: List[str], limit: int = -1
) -> List[Optional[T]]:
"""
Uses bisection to find a list of items in another list.
returns a list of found items with `None` items being not found
items.
Returns a list of found items with `None` items being not found items.
"""
def __init__(
self, source: list, search_from: str, queries: list[str], limit=-1
) -> None:
self.source_list = source
self.queries_list = queries
self.attr = search_from
self.limit = limit
def find(self, query: str):
def find(query: str):
left = 0
right = len(self.source_list) - 1
right = len(source) - 1
while left <= right:
mid = (left + right) // 2
if self.source_list[mid].__getattribute__(self.attr) == query:
return self.source_list[mid]
elif self.source_list[mid].__getattribute__(self.attr) > query:
if source[mid].__getattribute__(key) == query:
return source[mid]
elif source[mid].__getattribute__(key) > query:
right = mid - 1
else:
left = mid + 1
return None
def __call__(self):
if len(self.source_list) == 0:
if len(source) == 0:
return []
results: list[Track] = []
results = []
for query in self.queries_list:
res = self.find(query)
for query in queries:
res = find(query)
if res is None:
continue
results.append(res)
if self.limit != -1 and len(results) >= self.limit:
if limit != -1 and len(results) >= limit:
break
return results