Files
swingmusic-extended/app/lib/home/recentlyadded.py
T
2024-11-17 20:06:08 +01:00

214 lines
5.8 KiB
Python

from datetime import datetime
from app.lib.playlistlib import get_first_4_images
from app.models.playlist import Playlist
from app.models.track import Track
from app.store.tracks import TrackStore
from app.store.albums import AlbumStore
from app.store.artists import ArtistStore
from itertools import groupby
from app.utils import flatten
from app.utils.dates import (
create_new_date,
date_string_to_time_passed,
)
older_albums = set()
older_artists = set()
def calc_based_on_percent(items: list[str], total: int):
"""
Checks if items is more than 85% of total items. Returns a boolean and the most common item.
"""
most_common = max(items, key=items.count)
most_common_count = items.count(most_common)
return most_common_count / total >= 0.7, most_common, most_common_count
def check_is_album_folder(tracks: list[Track]):
albumhashes = [t.albumhash for t in tracks]
return calc_based_on_percent(albumhashes, len(tracks))
def check_is_artist_folder(tracks: list[Track]):
# INFO: flatten artist hashes using "-" as a separator
artisthashes = flatten([t.artisthashes for t in tracks])
return calc_based_on_percent(artisthashes, len(tracks))
def check_is_track_folder(tracks: list[Track]):
# INFO: is more of a playlist
if len(tracks) >= 3:
return False
return [create_track(t) for t in tracks]
def create_track(t: Track):
"""
Creates a recently added track entry.
"""
return {
"type": "track",
"hash": t.trackhash,
"timestamp": t.last_mod,
"help_text": "NEW TRACK",
}
# INFO: Keys: folder, tracks, time (timestamp)
# group_type = dict[str, str | list[Track] | float]
def check_folder_type(group_: dict):
# check if all tracks in group have the same albumhash
# if so, return "album"
key: str = group_["folder"]
tracks: list[Track] = group_["tracks"]
time: float = group_["time"]
existing_artist_hashes: set[str] = set(ArtistStore.artistmap.keys())
existing_album_hashes: set[str] = set(AlbumStore.albummap.keys())
if len(tracks) == 1:
entry = create_track(tracks[0])
entry["timestamp"] = time
return entry
is_album, albumhash, _ = check_is_album_folder(tracks)
if is_album:
# album = AlbumTable.get_album_by_albumhash(albumhash)
entry = AlbumStore.albummap.get(albumhash)
if entry is None:
return None
return {
"type": "album",
"hash": albumhash,
"timestamp": time,
"help_text": (
"NEW ALBUM" if albumhash in existing_album_hashes else "NEW TRACKS"
),
}
is_artist, artisthash, trackcount = check_is_artist_folder(tracks)
if is_artist:
entry = ArtistStore.artistmap.get(artisthash)
if entry is None:
return None
return {
"type": "artist",
"hash": artisthash,
"timestamp": time,
"help_text": (
"NEW ARTIST" if artisthash not in existing_artist_hashes else "NEW MUSIC"
),
}
is_track_folder = check_is_track_folder(tracks)
return (
is_track_folder
if is_track_folder
else {
"type": "folder",
"hash": key,
"timestamp": time,
"help_text": "NEW MUSIC",
}
)
def group_track_by_folders(tracks: list[Track], groups: dict[str, list[Track]]):
"""
Groups tracks by folder and returns a list of groups sorted by last modified date.
Uses generator expressions to avoid creating intermediate lists.
"""
# INFO: sort tracks by folder name, then group by folder name
tracks = sorted(tracks, key=lambda t: t.folder)
thisgroup = groupby(tracks, lambda t: t.folder)
for folder, thistracks in thisgroup:
groups.setdefault(folder, []).extend(thistracks)
return groups
def get_recently_added_items(limit: int = 7):
tracks = get_recently_added_tracks(start=0, limit=None)
groups = group_track_by_folders(tracks, {})
grouplist = []
# INFO: sort tracks by last modified date in descending order to get the most recent last modified date
for folder, trackgroup in groups.items():
trackgroup.sort(key=lambda t: t.last_mod, reverse=True)
grouplist.append(
{
"folder": folder,
"len": len(trackgroup),
"tracks": trackgroup,
"time": trackgroup[0].last_mod,
}
)
# sort groups by last modified date
grouplist = sorted(grouplist, key=lambda group: group["time"], reverse=True)
recent_items = []
for group in grouplist:
item = check_folder_type(group)
if item not in recent_items:
if not item:
continue
(
recent_items.append(item)
if type(item) == dict
else recent_items.extend(item)
)
if len(recent_items) >= limit:
break
return recent_items
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].last_mod)
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.duration = sum(t.duration for t in tracks)
playlist.count = len(tracks)
return playlist, tracks
def get_recently_added_tracks(start: int = 0, limit: int | None = 100):
return TrackStore.get_recently_added(start, limit)