mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-05 04:53:01 +00:00
add because you listened to artist artists
+ add artists you might like
This commit is contained in:
@@ -18,9 +18,9 @@ def start_cron_jobs():
|
|||||||
RecentlyAdded()
|
RecentlyAdded()
|
||||||
|
|
||||||
# Initialized CRON jobs
|
# Initialized CRON jobs
|
||||||
Mixes()
|
|
||||||
TopArtists()
|
TopArtists()
|
||||||
TopArtists(duration="week")
|
TopArtists(duration="week")
|
||||||
|
Mixes()
|
||||||
|
|
||||||
# Trigger all CRON jobs when the app is started.
|
# Trigger all CRON jobs when the app is started.
|
||||||
schedule.run_all()
|
schedule.run_all()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from app.crons.cron import CronJob
|
from app.crons.cron import CronJob
|
||||||
from app.lib.recipes.artistmixes import ArtistMixes
|
from app.lib.recipes.artistmixes import ArtistMixes
|
||||||
|
from app.lib.recipes.because import BecauseYouListened
|
||||||
|
|
||||||
|
|
||||||
class Mixes(CronJob):
|
class Mixes(CronJob):
|
||||||
@@ -19,3 +20,7 @@ class Mixes(CronJob):
|
|||||||
"""
|
"""
|
||||||
print("⭐⭐⭐⭐ Mixes cron job running")
|
print("⭐⭐⭐⭐ Mixes cron job running")
|
||||||
ArtistMixes()
|
ArtistMixes()
|
||||||
|
|
||||||
|
# INFO: Because you listened to artist items are generated using
|
||||||
|
# the artist mixes, so run them after the artist mixes are created.
|
||||||
|
BecauseYouListened()
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ def get_recently_played(
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
def recover_recently_played_items(items: list[dict]):
|
def recover_items(items: list[dict]):
|
||||||
custom_playlists = [
|
custom_playlists = [
|
||||||
{"name": "recentlyadded", "handler": get_recently_added_playlist},
|
{"name": "recentlyadded", "handler": get_recently_added_playlist},
|
||||||
{"name": "recentlyplayed", "handler": get_recently_played_playlist},
|
{"name": "recentlyplayed", "handler": get_recently_played_playlist},
|
||||||
@@ -235,7 +235,7 @@ def recover_recently_played_items(items: list[dict]):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
elif item["type"] == "playlist":
|
elif item["type"] == "playlist":
|
||||||
if item["is_custom"]:
|
if item.get("is_custom"):
|
||||||
playlist, _ = next(
|
playlist, _ = next(
|
||||||
i["handler"]()
|
i["handler"]()
|
||||||
for i in custom_playlists
|
for i in custom_playlists
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
from pprint import pprint
|
||||||
|
from app.db.userdata import UserTable
|
||||||
|
from app.lib.recipes import HomepageRoutine
|
||||||
|
from app.lib.recipes.artistmixes import ArtistMixes
|
||||||
|
from app.models.mix import Mix
|
||||||
|
from app.plugins.mixes import MixesPlugin
|
||||||
|
from app.store.homepage import HomepageStore
|
||||||
|
|
||||||
|
|
||||||
|
class BecauseYouListened(HomepageRoutine):
|
||||||
|
store_keys = ["because_you_listened_to_artist", "artists_you_might_like"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_valid(self):
|
||||||
|
return MixesPlugin().enabled
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
users = UserTable.get_all()
|
||||||
|
|
||||||
|
for user in users:
|
||||||
|
entry: dict[str, Mix] = HomepageStore.entries.get(
|
||||||
|
ArtistMixes.store_key
|
||||||
|
).items.get(user.id) # type: ignore
|
||||||
|
|
||||||
|
if not entry:
|
||||||
|
continue
|
||||||
|
|
||||||
|
because_you_listened_to_artist, artists_you_might_like = (
|
||||||
|
MixesPlugin().get_because_items(list(entry.values()))
|
||||||
|
)
|
||||||
|
|
||||||
|
HomepageStore.entries[self.store_keys[0]].items[
|
||||||
|
user.id
|
||||||
|
] = because_you_listened_to_artist
|
||||||
|
HomepageStore.entries[self.store_keys[1]].items[
|
||||||
|
user.id
|
||||||
|
] = artists_you_might_like
|
||||||
+60
-1
@@ -1,4 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
from gettext import ngettext
|
||||||
import json
|
import json
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import random
|
import random
|
||||||
@@ -136,7 +137,7 @@ class MixesPlugin(Plugin):
|
|||||||
|
|
||||||
# try to balance the mix
|
# try to balance the mix
|
||||||
trackmatches = balance_mix(trackmatches)
|
trackmatches = balance_mix(trackmatches)
|
||||||
return trackmatches, results["albums"], results["albums"]
|
return trackmatches, results["albums"], results["artists"]
|
||||||
|
|
||||||
@plugin_method
|
@plugin_method
|
||||||
def get_artist_mix(self, artisthash: str):
|
def get_artist_mix(self, artisthash: str):
|
||||||
@@ -419,3 +420,61 @@ class MixesPlugin(Plugin):
|
|||||||
TODO: Implement this!
|
TODO: Implement this!
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_because_items(self, mixes: list[Mix]):
|
||||||
|
"""
|
||||||
|
Given a list of mixes, returns a list of artists that are similar to the
|
||||||
|
artists in the mixes.
|
||||||
|
"""
|
||||||
|
artists: dict[str, list[dict[str, str | int]]] = {}
|
||||||
|
|
||||||
|
for mix in mixes:
|
||||||
|
mix_artisthash = mix.extra["artisthash"]
|
||||||
|
artists.setdefault(mix_artisthash, [])
|
||||||
|
|
||||||
|
for artisthash in mix.extra["artists"]:
|
||||||
|
artist = ArtistStore.artistmap.get(artisthash)
|
||||||
|
|
||||||
|
if not artist:
|
||||||
|
continue
|
||||||
|
|
||||||
|
artists[mix_artisthash].append(
|
||||||
|
{
|
||||||
|
"type": "artist",
|
||||||
|
"trackcount": artist.artist.trackcount,
|
||||||
|
"hash": artisthash,
|
||||||
|
"help_text": str(artist.artist.trackcount)
|
||||||
|
+ ngettext(" track", " tracks", artist.artist.trackcount),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# INFO: Sort artists by trackcount
|
||||||
|
artists[mix_artisthash] = sorted(
|
||||||
|
artists[mix_artisthash],
|
||||||
|
key=lambda x: x["trackcount"],
|
||||||
|
reverse=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
artisthash = mixes[0].extra["artisthash"]
|
||||||
|
because_you_listened_to_artist = {
|
||||||
|
"title": "Because you listened to "
|
||||||
|
+ ArtistStore.artistmap[artisthash].artist.name,
|
||||||
|
"items": artists[artisthash][:15],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Flatten list of artists and remove duplicates by artisthash
|
||||||
|
all_artists = []
|
||||||
|
seen = set()
|
||||||
|
|
||||||
|
for artist_list in artists.values():
|
||||||
|
for artist in artist_list:
|
||||||
|
if artist["hash"] not in seen:
|
||||||
|
all_artists.append(artist)
|
||||||
|
seen.add(artist["hash"])
|
||||||
|
|
||||||
|
artists_you_might_like = {
|
||||||
|
"title": "Artists you might like",
|
||||||
|
"items": random.sample(all_artists, k=min(15, len(all_artists))),
|
||||||
|
}
|
||||||
|
|
||||||
|
return because_you_listened_to_artist, artists_you_might_like
|
||||||
|
|||||||
+33
-5
@@ -1,7 +1,8 @@
|
|||||||
from abc import ABC
|
from abc import ABC
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
import pprint
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from app.lib.home.recentlyplayed import recover_recently_played_items
|
from app.lib.home.recentlyplayed import recover_items
|
||||||
from app.models.mix import Mix
|
from app.models.mix import Mix
|
||||||
from app.utils.auth import get_current_userid
|
from app.utils.auth import get_current_userid
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ class RecentlyPlayedHomepageEntry(HomepageEntry):
|
|||||||
return {
|
return {
|
||||||
"title": self.title,
|
"title": self.title,
|
||||||
"description": self.description,
|
"description": self.description,
|
||||||
"items": recover_recently_played_items(items),
|
"items": recover_items(items),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ class RecentlyAddedHomepageEntry(RecentlyPlayedHomepageEntry):
|
|||||||
return super().get_items(0, limit)
|
return super().get_items(0, limit)
|
||||||
|
|
||||||
|
|
||||||
class TopStreamedHomepageEntry(RecentlyPlayedHomepageEntry):
|
class GenericRecoverableEntry(RecentlyPlayedHomepageEntry):
|
||||||
"""
|
"""
|
||||||
A homepage entry for top streamed.
|
A homepage entry for top streamed.
|
||||||
"""
|
"""
|
||||||
@@ -101,6 +102,25 @@ class TopStreamedHomepageEntry(RecentlyPlayedHomepageEntry):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BecauseYouListenedToArtistHomepageEntry(RecentlyPlayedHomepageEntry):
|
||||||
|
"""
|
||||||
|
A homepage entry for because you listened to artist.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# SHAPE: {userid: {title: str, items: list[RecoverableItem]}}
|
||||||
|
items: dict[int, dict[str, Any]]
|
||||||
|
|
||||||
|
def get_items(self, userid: int, limit: int | None = None):
|
||||||
|
pprint.pprint(self.items)
|
||||||
|
title = self.items.get(userid, {}).get("title")
|
||||||
|
items = self.items.get(userid, {}).get("items", [])[:limit]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"title": title,
|
||||||
|
"items": recover_items(items),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class HomepageStore:
|
class HomepageStore:
|
||||||
"""
|
"""
|
||||||
Stores the homepage items.
|
Stores the homepage items.
|
||||||
@@ -114,14 +134,22 @@ class HomepageStore:
|
|||||||
title="Artist mixes for you",
|
title="Artist mixes for you",
|
||||||
description="Based on artists you have been listening to",
|
description="Based on artists you have been listening to",
|
||||||
),
|
),
|
||||||
"top_streamed_weekly_artists": TopStreamedHomepageEntry(
|
"top_streamed_weekly_artists": GenericRecoverableEntry(
|
||||||
title="Top artists this week",
|
title="Top artists this week",
|
||||||
description="Your most played artists since Monday",
|
description="Your most played artists since Monday",
|
||||||
),
|
),
|
||||||
"top_streamed_monthly_artists": TopStreamedHomepageEntry(
|
"top_streamed_monthly_artists": GenericRecoverableEntry(
|
||||||
title="Top artists this month",
|
title="Top artists this month",
|
||||||
description="Your most played artists since the start of the month",
|
description="Your most played artists since the start of the month",
|
||||||
),
|
),
|
||||||
|
"because_you_listened_to_artist": BecauseYouListenedToArtistHomepageEntry(
|
||||||
|
title="",
|
||||||
|
description="Artists similar to the artist you listened to",
|
||||||
|
),
|
||||||
|
"artists_you_might_like": BecauseYouListenedToArtistHomepageEntry(
|
||||||
|
title="Artists you might like",
|
||||||
|
description="Artists similar to the artists you have listened to",
|
||||||
|
),
|
||||||
"recently_added": RecentlyAddedHomepageEntry(
|
"recently_added": RecentlyAddedHomepageEntry(
|
||||||
title="Recently added",
|
title="Recently added",
|
||||||
description="New music added to your library",
|
description="New music added to your library",
|
||||||
|
|||||||
Reference in New Issue
Block a user