added playlist engine and recent playlist
This commit is contained in:
parent
9750ff8b80
commit
89f8c8961b
@ -3,6 +3,14 @@ import spotframework.net.network as network
|
||||
import spotframework.net.user as user
|
||||
import spotframework.log.log as log
|
||||
import spotframework.io.json as json
|
||||
import spotframework.util.monthstrings as monthstrings
|
||||
from spotframework.engine.playlistengine import PlaylistEngine
|
||||
from spotframework.engine.filter.shuffle import Shuffle
|
||||
from spotframework.engine.filter.sortreversereleasedate import SortReverseReleaseDate
|
||||
from spotframework.engine.filter.deduplicatebyid import DeduplicateByID
|
||||
from spotframework.engine.filter.deduplicatebyname import DeduplicateByName
|
||||
|
||||
import datetime
|
||||
|
||||
import requests
|
||||
|
||||
@ -16,47 +24,58 @@ if __name__ == '__main__':
|
||||
data = json.loadJson(os.path.join(const.config_path, 'playlists.json'))
|
||||
|
||||
net = network.network(user.User())
|
||||
playlists = net.getUserPlaylists()
|
||||
|
||||
engine = PlaylistEngine(net)
|
||||
engine.load_user_playlists()
|
||||
|
||||
for tomake in data['playlists']:
|
||||
|
||||
log.log("generatePlaylist", tomake['name'])
|
||||
log.log("makePlaylist", tomake['name'])
|
||||
|
||||
tracks = []
|
||||
|
||||
for part in tomake['playlists']:
|
||||
|
||||
play = next((i for i in playlists if i.name == part), None)
|
||||
|
||||
if play is not None:
|
||||
|
||||
if len(play.tracks) == 0:
|
||||
log.log("pulling tracks for {}".format(play.name))
|
||||
play.tracks = net.getPlaylistTracks(play.playlistid)
|
||||
|
||||
tracks += [i for i in play.tracks if i['track']['uri'] not in [j['track']['uri'] for j in tracks] and i['is_local'] is False]
|
||||
|
||||
else:
|
||||
log.log("requested playlist {} not found".format(part))
|
||||
if 'SLACKHOOK' in os.environ:
|
||||
requests.post(os.environ['SLACKHOOK'], json={"text": "spot playlists: {} not found".format(part)})
|
||||
processors = [DeduplicateByID()]
|
||||
|
||||
if 'shuffle' in tomake:
|
||||
if tomake['shuffle'] is True:
|
||||
import random
|
||||
random.shuffle(tracks)
|
||||
processors.append(Shuffle())
|
||||
else:
|
||||
tracks.sort(key=lambda x: x['track']['album']['release_date'], reverse=True)
|
||||
processors.append(SortReverseReleaseDate())
|
||||
else:
|
||||
tracks.sort(key=lambda x: x['track']['album']['release_date'], reverse=True)
|
||||
processors.append(SortReverseReleaseDate())
|
||||
|
||||
tracks = engine.make_playlist(tomake['playlists'], processors)
|
||||
|
||||
engine.execute_playlist(tracks, tomake['id'])
|
||||
engine.change_description(tomake['playlists'], tomake['id'])
|
||||
|
||||
if 'recents' in data:
|
||||
recents_id = data['recents']['id']
|
||||
boundary_date = datetime.datetime.now() - datetime.timedelta(days=data['recents']['boundary'])
|
||||
|
||||
recent_parts = []
|
||||
|
||||
for playlist in [i for i in data['playlists'] if 'include_in_recents' in i]:
|
||||
if playlist['include_in_recents']:
|
||||
recent_parts += [i for i in playlist['playlists']]
|
||||
|
||||
if 'playlists' in data['recents']:
|
||||
recent_parts += data['recents']['playlists']
|
||||
|
||||
processors = [DeduplicateByName(), SortReverseReleaseDate()]
|
||||
|
||||
recent_tracks = engine.get_recent_playlist(boundary_date, recent_parts, processors)
|
||||
engine.execute_playlist(recent_tracks, data['recents']['id'])
|
||||
engine.change_description([monthstrings.get_this_month(),
|
||||
monthstrings.get_last_month()]
|
||||
, data['recents']['id'])
|
||||
|
||||
net.replacePlaylistTracks(tomake['id'], [i['track']['uri'] for i in tracks])
|
||||
net.changePlaylistDetails(tomake['id'], description=' / '.join(tomake['playlists']))
|
||||
else:
|
||||
log.log("config json not found")
|
||||
if 'SLACKHOOK' in os.environ:
|
||||
requests.post(os.environ['SLACKHOOK'], json={"text": "spot playlists: config json not found"})
|
||||
|
||||
log.dumpLog()
|
||||
except:
|
||||
except Exception:
|
||||
log.log("exception occured")
|
||||
if 'SLACKHOOK' in os.environ:
|
||||
requests.post(os.environ['SLACKHOOK'], json={"text": "spot playlists: exception occured"})
|
||||
log.dumpLog()
|
||||
|
0
spotframework/engine/__init__.py
Normal file
0
spotframework/engine/__init__.py
Normal file
0
spotframework/engine/filter/__init__.py
Normal file
0
spotframework/engine/filter/__init__.py
Normal file
11
spotframework/engine/filter/abstractprocessor.py
Normal file
11
spotframework/engine/filter/abstractprocessor.py
Normal file
@ -0,0 +1,11 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class AbstractProcessor(ABC):
|
||||
|
||||
def __init__(self, names=[]):
|
||||
self.playlist_names = names
|
||||
|
||||
@abstractmethod
|
||||
def process(self, tracks):
|
||||
pass
|
17
spotframework/engine/filter/addedbefore.py
Normal file
17
spotframework/engine/filter/addedbefore.py
Normal file
@ -0,0 +1,17 @@
|
||||
from .abstractprocessor import AbstractProcessor
|
||||
import datetime
|
||||
|
||||
|
||||
class AddedBefore(AbstractProcessor):
|
||||
|
||||
def __init__(self, boundary, names=[]):
|
||||
self.playlist_names = names
|
||||
self.boundary = boundary
|
||||
|
||||
def check_date(self, track):
|
||||
added_at = datetime.datetime.fromisoformat(track['added_at'].replace('T', ' ').replace('Z', ''))
|
||||
|
||||
return added_at < self.boundary
|
||||
|
||||
def process(self, tracks):
|
||||
return [i for i in tracks if self.check_date(i)]
|
17
spotframework/engine/filter/addedsince.py
Normal file
17
spotframework/engine/filter/addedsince.py
Normal file
@ -0,0 +1,17 @@
|
||||
from .abstractprocessor import AbstractProcessor
|
||||
import datetime
|
||||
|
||||
|
||||
class AddedSince(AbstractProcessor):
|
||||
|
||||
def __init__(self, boundary, names=[]):
|
||||
self.playlist_names = names
|
||||
self.boundary = boundary
|
||||
|
||||
def check_date(self, track):
|
||||
added_at = datetime.datetime.fromisoformat(track['added_at'].replace('T', ' ').replace('Z', ''))
|
||||
|
||||
return added_at > self.boundary
|
||||
|
||||
def process(self, tracks):
|
||||
return [i for i in tracks if self.check_date(i)]
|
13
spotframework/engine/filter/deduplicatebyid.py
Normal file
13
spotframework/engine/filter/deduplicatebyid.py
Normal file
@ -0,0 +1,13 @@
|
||||
from .abstractprocessor import AbstractProcessor
|
||||
|
||||
|
||||
class DeduplicateByID(AbstractProcessor):
|
||||
|
||||
def process(self, tracks):
|
||||
return_tracks = []
|
||||
|
||||
for track in tracks:
|
||||
if track['track']['uri'] not in [i['track']['uri'] for i in return_tracks]:
|
||||
return_tracks.append(track)
|
||||
|
||||
return return_tracks
|
19
spotframework/engine/filter/deduplicatebyname.py
Normal file
19
spotframework/engine/filter/deduplicatebyname.py
Normal file
@ -0,0 +1,19 @@
|
||||
from .abstractprocessor import AbstractProcessor
|
||||
|
||||
|
||||
class DeduplicateByName(AbstractProcessor):
|
||||
|
||||
def process(self, tracks):
|
||||
return_tracks = []
|
||||
|
||||
for to_check in tracks:
|
||||
|
||||
for cache_track in return_tracks:
|
||||
if to_check['track']['name'].lower() == cache_track['track']['name'].lower():
|
||||
if to_check['track']['artists'][0]['name'].lower() \
|
||||
== cache_track['track']['artists'][0]['name'].lower():
|
||||
break
|
||||
else:
|
||||
return_tracks.append(to_check)
|
||||
|
||||
return return_tracks
|
9
spotframework/engine/filter/shuffle.py
Normal file
9
spotframework/engine/filter/shuffle.py
Normal file
@ -0,0 +1,9 @@
|
||||
from .abstractprocessor import AbstractProcessor
|
||||
import random
|
||||
|
||||
|
||||
class Shuffle(AbstractProcessor):
|
||||
|
||||
def process(self, tracks):
|
||||
random.shuffle(tracks)
|
||||
return tracks
|
8
spotframework/engine/filter/sortreversereleasedate.py
Normal file
8
spotframework/engine/filter/sortreversereleasedate.py
Normal file
@ -0,0 +1,8 @@
|
||||
from .abstractprocessor import AbstractProcessor
|
||||
|
||||
|
||||
class SortReverseReleaseDate(AbstractProcessor):
|
||||
|
||||
def process(self, tracks):
|
||||
tracks.sort(key=lambda x: x['track']['album']['release_date'], reverse=True)
|
||||
return tracks
|
72
spotframework/engine/playlistengine.py
Normal file
72
spotframework/engine/playlistengine.py
Normal file
@ -0,0 +1,72 @@
|
||||
import spotframework.log.log as log
|
||||
|
||||
import requests
|
||||
import os
|
||||
|
||||
import spotframework.util.monthstrings as monthstrings
|
||||
from spotframework.engine.filter.addedsince import AddedSince
|
||||
|
||||
|
||||
class PlaylistEngine:
|
||||
|
||||
def __init__(self, net):
|
||||
self.playlists = []
|
||||
self.net = net
|
||||
|
||||
def load_user_playlists(self):
|
||||
self.playlists = self.net.getUserPlaylists()
|
||||
|
||||
def append_user_playlists(self):
|
||||
self.playlists += self.net.getUserPlaylists()
|
||||
|
||||
def get_playlist_tracks(self, playlist):
|
||||
log.log("pulling tracks for {}".format(playlist.name))
|
||||
playlist.tracks = self.net.getPlaylistTracks(playlist.playlistid)
|
||||
|
||||
def make_playlist(self, playlist_parts, processors=[]):
|
||||
|
||||
tracks = []
|
||||
|
||||
for part in playlist_parts:
|
||||
|
||||
play = next((i for i in self.playlists if i.name == part), None)
|
||||
|
||||
if play is not None:
|
||||
|
||||
if play.has_tracks() is False:
|
||||
self.get_playlist_tracks(play)
|
||||
|
||||
playlist_tracks = list(play.tracks)
|
||||
|
||||
for processor in [i for i in processors if play.name in [j for j in i.playlist_names]]:
|
||||
playlist_tracks = processor.process(playlist_tracks)
|
||||
|
||||
tracks += [i for i in playlist_tracks if i['is_local'] is False]
|
||||
|
||||
else:
|
||||
log.log("requested playlist {} not found".format(part))
|
||||
if play is not None:
|
||||
if 'SLACKHOOK' in os.environ:
|
||||
requests.post(os.environ['SLACKHOOK'], json={"text": "spot playlists: {} not found".format(part)})
|
||||
|
||||
for processor in [i for i in processors if len(i.playlist_names) <= 0]:
|
||||
tracks = processor.process(tracks)
|
||||
|
||||
# print(tracks)
|
||||
return tracks
|
||||
|
||||
def get_recent_playlist(self, boundary_date, recent_playlist_parts, processors=[]):
|
||||
this_month = monthstrings.get_this_month()
|
||||
last_month = monthstrings.get_last_month()
|
||||
|
||||
datefilter = AddedSince(boundary_date, recent_playlist_parts)
|
||||
|
||||
processors.append(datefilter)
|
||||
|
||||
return self.make_playlist(recent_playlist_parts + [this_month, last_month], processors)
|
||||
|
||||
def execute_playlist(self, tracks, playlist_id):
|
||||
self.net.replacePlaylistTracks(playlist_id, [i['track']['uri'] for i in tracks])
|
||||
|
||||
def change_description(self, playlistparts, playlist_id):
|
||||
self.net.changePlaylistDetails(playlist_id, description=' / '.join(playlistparts))
|
@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
class playlist:
|
||||
class Playlist:
|
||||
|
||||
def __init__(self, playlistid, uri=None, name=None, userid=None):
|
||||
self.tracks = []
|
||||
@ -8,3 +8,9 @@ class playlist:
|
||||
self.playlistid = playlistid
|
||||
self.userid = userid
|
||||
self.uri = uri
|
||||
|
||||
def has_tracks(self):
|
||||
if len(self.tracks) > 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
@ -1,6 +1,6 @@
|
||||
import requests
|
||||
from . import const
|
||||
from spotframework.model.playlist import playlist as playlistclass
|
||||
from spotframework.model.playlist import Playlist as playlistclass
|
||||
import spotframework.log.log as log
|
||||
|
||||
limit = 50
|
||||
|
0
spotframework/util/__init__.py
Normal file
0
spotframework/util/__init__.py
Normal file
14
spotframework/util/monthstrings.py
Normal file
14
spotframework/util/monthstrings.py
Normal file
@ -0,0 +1,14 @@
|
||||
import datetime
|
||||
|
||||
|
||||
def get_this_month():
|
||||
return datetime.date.today().strftime('%B %y').lower()
|
||||
|
||||
|
||||
def get_last_month():
|
||||
month = datetime.date.today().replace(day=1) - datetime.timedelta(days=1)
|
||||
return month.strftime('%B %y').lower()
|
||||
|
||||
|
||||
def get_this_year():
|
||||
return datetime.date.today().strftime('%y')
|
Loading…
Reference in New Issue
Block a user