mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
add timestamp to favorite entries
+ convert useBisection into a function
This commit is contained in:
committed by
Mungai Njoroge
parent
fb635ff35f
commit
766eb388b2
+2
-2
@@ -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
@@ -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})
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
@@ -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,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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user