Merge branch 'master' of github.com:swingmx/swingmusic

This commit is contained in:
cwilvx
2025-06-17 13:10:58 +03:00
5 changed files with 58 additions and 15 deletions
+1 -1
View File
@@ -110,7 +110,7 @@ def run(*args, **kwargs):
def main(): def main():
multiprocessing.freeze_support() multiprocessing.freeze_support()
multiprocessing.set_start_method("spawn") multiprocessing.set_start_method("fork")
run() run()
if __name__ == "__main__": if __name__ == "__main__":
+26 -6
View File
@@ -7,6 +7,7 @@ import shutil
from time import time from time import time
from flask_openapi3 import Tag from flask_openapi3 import Tag
from flask_openapi3 import APIBlueprint from flask_openapi3 import APIBlueprint
import sqlalchemy.exc
from swingmusic.api.auth import admin_required from swingmusic.api.auth import admin_required
from swingmusic.db.userdata import FavoritesTable, PlaylistTable, ScrobbleTable from swingmusic.db.userdata import FavoritesTable, PlaylistTable, ScrobbleTable
@@ -96,6 +97,9 @@ def backup():
class RestoreBackup: class RestoreBackup:
# TODO: BACKUP AND RESTORE COLLECTIONS & MIXES!
# TODO: IMPROVE UX WHEN WAITING FOR RESTORE TO COMPLETE!
def __init__(self, backup_dir: Path): def __init__(self, backup_dir: Path):
self.backup_dir = backup_dir self.backup_dir = backup_dir
self.backup_file = backup_dir / "data.json" self.backup_file = backup_dir / "data.json"
@@ -114,8 +118,12 @@ class RestoreBackup:
existing_hashes = set(fav.hash for fav in existing_favorites) existing_hashes = set(fav.hash for fav in existing_favorites)
new_favorites = [fav for fav in favorites if fav["hash"] not in existing_hashes] new_favorites = [fav for fav in favorites if fav["hash"] not in existing_hashes]
if new_favorites: for fav in new_favorites:
FavoritesTable.insert_many(new_favorites) try:
FavoritesTable.insert_item(fav)
except sqlalchemy.exc.IntegrityError:
print("Integrity error, skipping favorite")
print(fav)
def restore_playlists(self, playlists: list[dict]): def restore_playlists(self, playlists: list[dict]):
existing_playlists = PlaylistTable.get_all() existing_playlists = PlaylistTable.get_all()
@@ -124,8 +132,15 @@ class RestoreBackup:
playlist for playlist in playlists if playlist["name"] not in existing_names playlist for playlist in playlists if playlist["name"] not in existing_names
] ]
if new_playlists: for playlist in new_playlists:
PlaylistTable.insert_many(new_playlists) try:
if playlist.get("_score") is not None:
del playlist["_score"]
PlaylistTable.add_one(playlist)
except sqlalchemy.exc.IntegrityError:
print("Integrity error, skipping playlist:")
print(playlist)
def restore_scrobbles(self, scrobbles: list[dict]): def restore_scrobbles(self, scrobbles: list[dict]):
existing_scrobbles = ScrobbleTable.get_all(0) existing_scrobbles = ScrobbleTable.get_all(0)
@@ -139,8 +154,13 @@ class RestoreBackup:
if f"{scrobble['trackhash']}.{scrobble['timestamp']}" not in existing_hashes if f"{scrobble['trackhash']}.{scrobble['timestamp']}" not in existing_hashes
] ]
if new_scrobbles: for scrobble in new_scrobbles:
ScrobbleTable.insert_many(new_scrobbles) try:
ScrobbleTable.add(scrobble)
except sqlalchemy.exc.IntegrityError:
print("Integrity error, skipping scrobble:")
print(scrobble)
class RestoreBackupBody(BaseModel): class RestoreBackupBody(BaseModel):
+5
View File
@@ -219,7 +219,10 @@ class FavoritesTable(Base):
# guard against hash collisions for different item types # guard against hash collisions for different item types
item["hash"] = f"{item['type']}_{item['hash']}" item["hash"] = f"{item['type']}_{item['hash']}"
if item.get("timestamp") is None:
item["timestamp"] = int(datetime.datetime.now().timestamp()) item["timestamp"] = int(datetime.datetime.now().timestamp())
if item.get("userid") is None:
item["userid"] = get_current_userid() item["userid"] = get_current_userid()
return next(cls.execute(insert(cls).values(item), commit=True)) return next(cls.execute(insert(cls).values(item), commit=True))
@@ -337,7 +340,9 @@ class ScrobbleTable(Base):
@classmethod @classmethod
def add(cls, item: dict[str, Any]): def add(cls, item: dict[str, Any]):
if item.get("userid") is None:
item["userid"] = get_current_userid() item["userid"] = get_current_userid()
return cls.insert_one(item) return cls.insert_one(item)
@classmethod @classmethod
+3
View File
@@ -29,6 +29,9 @@ class BecauseYouListened(HomepageRoutine):
MixesPlugin().get_because_items(list(entry.values())) MixesPlugin().get_because_items(list(entry.values()))
) )
if not because_you_listened_to_artist or not artists_you_might_like:
continue
HomepageStore.entries[self.store_keys[0]].items[ HomepageStore.entries[self.store_keys[0]].items[
user.id user.id
] = because_you_listened_to_artist ] = because_you_listened_to_artist
+20 -5
View File
@@ -531,7 +531,23 @@ class MixesPlugin(Plugin):
artists: dict[str, list[dict[str, str | int]]] = {} artists: dict[str, list[dict[str, str | int]]] = {}
albums: dict[str, list[dict[str, str | int]]] = {} albums: dict[str, list[dict[str, str | int]]] = {}
for mix in mixes: pivot_artist = None
pivot_artist_index = None
# Get pivot artist
for index, mix in enumerate(mixes):
artist = ArtistStore.artistmap.get(mix.extra["artisthash"])
if not artist:
continue
pivot_artist = artist.artist
pivot_artist_index = index
break
if not pivot_artist:
return None, None
for mix in mixes[pivot_artist_index:]:
mix_artisthash = mix.extra["artisthash"] mix_artisthash = mix.extra["artisthash"]
artists.setdefault(mix_artisthash, []) artists.setdefault(mix_artisthash, [])
albums.setdefault(mix_artisthash, []) albums.setdefault(mix_artisthash, [])
@@ -582,11 +598,10 @@ class MixesPlugin(Plugin):
reverse=True, reverse=True,
) )
artisthash = mixes[0].extra["artisthash"]
because_you_listened_to_artist = { because_you_listened_to_artist = {
"title": "Because you listened to " "title": "Because you listened to "
+ ArtistStore.artistmap[artisthash].artist.name, + pivot_artist.name,
"items": albums[artisthash][:15], "items": albums[pivot_artist.artisthash][:15],
} }
# Flatten list of artists and remove duplicates by artisthash # Flatten list of artists and remove duplicates by artisthash
@@ -601,7 +616,7 @@ class MixesPlugin(Plugin):
artists_you_might_like = { artists_you_might_like = {
"title": "Artists you might like", "title": "Artists you might like",
"items": artists[artisthash][:15], "items": artists[pivot_artist.artisthash][:15],
} }
return because_you_listened_to_artist, artists_you_might_like return because_you_listened_to_artist, artists_you_might_like