-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathauto_generated_playlist.py
99 lines (81 loc) · 4.15 KB
/
auto_generated_playlist.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from typing import Dict, List, Iterable
from collections import defaultdict
import utils
from data import Playlist, Track
from copy import deepcopy
import itertools
import re
def get_playlist_name_from_tags(tags: Dict[str, str], tag_keys_order: List[str]) -> str:
"""
Example: { "genre": "Acid", "rating": "4" } => "ge=Acid ra=4"
"""
name = ""
for k in tag_keys_order:
name += "%s=%s " % (k, tags[k].replace(" ", "_"))
return name.strip()
def tags_from_playlist_name(playlist_name: str, tag_models: Dict[str, List[str]]):
matches = re.findall(r'([a-zA-Z0-9_-]+)=([a-zA-Z0-9_-]+)', playlist_name)
tags = dict()
for match in matches:
identified_tag_key = utils.identify_value_from_prefix(match[0], list(tag_models.keys()))
if identified_tag_key:
tag_value = match[1].replace("_", " ")
if tag_value in tag_models[identified_tag_key]:
tags[identified_tag_key] = tag_value
return tags
class AutoGeneratedPlaylistManager:
def __init__(self, tag_models: Dict[str, List[str]], playlists_to_generate: List[List[str]]):
self._tag_models = tag_models
self._playlists_to_generate = playlists_to_generate
def tagged_tracks_from_playlists(self, playlists: List[Playlist]) -> Dict[str, List[Track]]:
tracks = defaultdict(list)
for p in playlists:
playlist_tags = tags_from_playlist_name(p.name, self._tag_models)
playlist_tags.pop("rating", None)
for t in p.tracks:
t_copy = deepcopy(t)
t_copy.tags = playlist_tags
tracks[str(t.path)].append(t_copy)
return dict(tracks)
def playlists_from_tagged_tracks(self, tracks: Dict[str, Track]) -> List[Playlist]:
playlists = []
for tag_keys_index, tag_keys_to_generate_playlist in enumerate(self._playlists_to_generate):
for tag_values in itertools.product(
*[self._tag_models[tag_key] for tag_key in tag_keys_to_generate_playlist]):
playlist_tags = {tag_keys_to_generate_playlist[i]: tag_values[i] for i, _ in enumerate(tag_values)}
track_list = []
for t in tracks.values():
if t.tags.items() >= playlist_tags.items():
track_list.append(t)
if not track_list and len(tag_keys_to_generate_playlist) > 1:
# Do not create empty playlists if multiple tags: avoid noise
continue
playlists.append(Playlist(
get_playlist_name_from_tags(playlist_tags, tag_keys_to_generate_playlist),
track_list,
tag_keys_to_generate_playlist,
tag_keys_index + 1
))
return playlists
def merge_playlists(tracks_that_should_not_be_merged: Dict[str, Track],
generated_playlists: Iterable[Playlist],
previous_playlists: Iterable[Playlist]) -> List[Playlist]:
result = {p.name: deepcopy(p) for p in generated_playlists}
for p in previous_playlists:
if p.name in result:
existing_playlist = result[p.name]
for t in p.tracks:
if not existing_playlist.contains_track(t.path) and \
str(t.path) not in tracks_that_should_not_be_merged:
existing_playlist.tracks.append(deepcopy(t))
return list(result.values())
if __name__ == "__main__":
assert get_playlist_name_from_tags({ "genre": "Acid", "rating": "4" }) == "ge=Acid ra=4"
assert get_playlist_name_from_tags({ "rating": "4", "genre": "Acid" }) == "ge=Acid ra=4"
assert get_playlist_name_from_tags({ "rating": "4", "genre": "Deep House" }) == "ge=Deep_House ra=4"
from constants import *
import json
with open(SCANNER_TAGS_FILE) as json_file:
TAGS_MODEL = json.load(json_file)
assert json.dumps(tags_from_playlist_name("02_RaGe ge=Acid ra=4", TAGS_MODEL)) == json.dumps({'genre2': 'Acid', 'rating': '4'})
assert json.dumps(tags_from_playlist_name("02_RaGe ge=Deep_House ra=4", TAGS_MODEL)) == json.dumps({'genre2': 'Deep House', 'rating': '4'})