2019-05-14 20:41:12 +01:00
|
|
|
import spotframework.net.const as const
|
2019-06-11 11:59:24 +01:00
|
|
|
from spotframework.net.network import Network
|
2019-09-04 17:45:26 +01:00
|
|
|
from spotframework.net.user import NetworkUser
|
2019-05-14 20:41:12 +01:00
|
|
|
import spotframework.io.json as json
|
2019-06-10 21:46:43 +01:00
|
|
|
import spotframework.util.monthstrings as monthstrings
|
|
|
|
from spotframework.engine.playlistengine import PlaylistEngine
|
2019-09-05 15:51:42 +01:00
|
|
|
from spotframework.engine.processor.shuffle import Shuffle
|
|
|
|
from spotframework.engine.processor.sort import SortReleaseDate
|
|
|
|
from spotframework.engine.processor.deduplicate import DeduplicateByID, DeduplicateByName
|
2019-06-10 21:46:43 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
import os
|
2019-06-10 21:46:43 +01:00
|
|
|
import datetime
|
2019-06-12 15:55:46 +01:00
|
|
|
import sys
|
2019-08-07 15:45:25 +01:00
|
|
|
import logging
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-05-26 20:42:01 +01:00
|
|
|
import requests
|
|
|
|
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-08-07 15:45:25 +01:00
|
|
|
logger = logging.getLogger('spotframework')
|
|
|
|
|
|
|
|
log_format = '%(asctime)s %(levelname)s %(name)s - %(funcName)s - %(message)s'
|
|
|
|
|
|
|
|
file_handler = logging.FileHandler(".spot/generate_playlists.log")
|
|
|
|
formatter = logging.Formatter(log_format)
|
|
|
|
file_handler.setFormatter(formatter)
|
|
|
|
|
|
|
|
logger.addHandler(file_handler)
|
|
|
|
|
2019-09-05 12:20:21 +01:00
|
|
|
stream_log_format = '%(levelname)s %(name)s:%(funcName)s - %(message)s'
|
|
|
|
stream_formatter = logging.Formatter(stream_log_format)
|
|
|
|
|
|
|
|
stream_handler = logging.StreamHandler()
|
|
|
|
stream_handler.setFormatter(stream_formatter)
|
|
|
|
|
|
|
|
logger.addHandler(stream_handler)
|
|
|
|
|
2019-08-07 15:45:25 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
def update_super_playlist(engine, data_dict):
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-08-07 15:45:25 +01:00
|
|
|
logger.info(f"makePlaylist {data_dict['name']}")
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
processors = [DeduplicateByID()]
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
if 'shuffle' in data_dict:
|
|
|
|
if data_dict['shuffle'] is True:
|
|
|
|
processors.append(Shuffle())
|
|
|
|
else:
|
2019-09-05 12:20:21 +01:00
|
|
|
processors.append(SortReleaseDate(reverse=True))
|
2019-06-12 15:55:46 +01:00
|
|
|
else:
|
2019-09-05 12:20:21 +01:00
|
|
|
processors.append(SortReleaseDate(reverse=True))
|
2019-06-10 21:46:43 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
tracks = engine.make_playlist(data_dict['playlists'], processors)
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
engine.execute_playlist(tracks, data_dict['id'])
|
|
|
|
engine.change_description(data_dict['playlists'], data_dict['id'])
|
2019-05-14 20:41:12 +01:00
|
|
|
|
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
def update_recents_playlist(engine, data):
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
recents_id = data['recents']['id']
|
|
|
|
boundary_date = datetime.datetime.now() - datetime.timedelta(days=data['recents']['boundary'])
|
|
|
|
|
|
|
|
recent_parts = []
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
if 'use_marked_playlists' in data['recents']:
|
|
|
|
if data['recents']['use_marked_playlists']:
|
|
|
|
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']]
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
else:
|
|
|
|
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']]
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
if 'playlists' in data['recents']:
|
|
|
|
recent_parts += data['recents']['playlists']
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-28 10:50:59 +01:00
|
|
|
if 'exclude' in data['recents']:
|
|
|
|
for exclusion in data['recents']['exclude']:
|
|
|
|
recent_parts.remove(exclusion)
|
|
|
|
|
2019-09-05 12:20:21 +01:00
|
|
|
processors = [DeduplicateByName(), SortReleaseDate(reverse=True)]
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
recent_tracks = engine.get_recent_playlist(boundary_date, recent_parts, processors)
|
|
|
|
engine.execute_playlist(recent_tracks, recents_id)
|
|
|
|
engine.change_description([monthstrings.get_this_month(), monthstrings.get_last_month()], data['recents']['id'])
|
2019-06-10 22:23:03 +01:00
|
|
|
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
def go():
|
2019-06-10 21:46:43 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
try:
|
2019-06-28 10:50:59 +01:00
|
|
|
if os.path.exists(os.path.join(const.config_path, 'config.json')):
|
2019-06-12 15:55:46 +01:00
|
|
|
|
2019-06-28 10:50:59 +01:00
|
|
|
data = json.load_json(os.path.join(const.config_path, 'config.json'))
|
2019-06-10 21:46:43 +01:00
|
|
|
|
2019-06-12 15:55:46 +01:00
|
|
|
to_execute = []
|
|
|
|
not_found = []
|
|
|
|
|
|
|
|
available_specials = ['recents']
|
|
|
|
specials_to_execute = []
|
|
|
|
|
|
|
|
if len(sys.argv) > 1:
|
|
|
|
for arg in sys.argv[1:]:
|
|
|
|
for playlist in data['playlists']:
|
|
|
|
if arg.lower() == playlist['name'].lower():
|
|
|
|
to_execute.append(playlist)
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
if arg in available_specials:
|
|
|
|
specials_to_execute.append(arg)
|
|
|
|
else:
|
|
|
|
not_found.append(arg)
|
|
|
|
else:
|
|
|
|
to_execute = data['playlists']
|
|
|
|
specials_to_execute = ['recents']
|
|
|
|
|
|
|
|
if len(not_found) > 0:
|
2019-08-07 15:45:25 +01:00
|
|
|
logger.error(f'arg not found {not_found}')
|
2019-06-12 15:55:46 +01:00
|
|
|
|
|
|
|
if len(to_execute) <= 0 and len(specials_to_execute) <= 0:
|
2019-08-07 15:45:25 +01:00
|
|
|
logger.critical('none to execute, terminating')
|
2019-06-12 15:55:46 +01:00
|
|
|
return
|
|
|
|
|
2020-06-22 20:15:22 +01:00
|
|
|
net = Network(NetworkUser(client_id=os.environ['SPOT_CLIENT'],
|
|
|
|
client_secret=os.environ['SPOT_SECRET'],
|
|
|
|
refresh_token=os.environ['SPOT_REFRESH'])).refresh_access_token()
|
2019-06-12 15:55:46 +01:00
|
|
|
|
|
|
|
engine = PlaylistEngine(net)
|
|
|
|
|
|
|
|
for super_playlist in to_execute:
|
|
|
|
update_super_playlist(engine, super_playlist)
|
|
|
|
|
|
|
|
if 'recents' in data and 'recents' in specials_to_execute:
|
|
|
|
update_recents_playlist(engine, data)
|
2019-05-14 20:41:12 +01:00
|
|
|
|
2019-05-14 22:58:15 +01:00
|
|
|
else:
|
2019-08-07 15:45:25 +01:00
|
|
|
logger.critical("config json not found")
|
2019-05-26 20:42:01 +01:00
|
|
|
if 'SLACKHOOK' in os.environ:
|
|
|
|
requests.post(os.environ['SLACKHOOK'], json={"text": "spot playlists: config json not found"})
|
2019-05-14 22:58:15 +01:00
|
|
|
|
2019-07-09 11:01:32 +01:00
|
|
|
except Exception as e:
|
2019-08-07 15:45:25 +01:00
|
|
|
logger.exception("exception occured")
|
2019-06-10 21:46:43 +01:00
|
|
|
if 'SLACKHOOK' in os.environ:
|
2019-07-09 11:01:32 +01:00
|
|
|
requests.post(os.environ['SLACKHOOK'], json={"text": f"spot playlists: exception occured {e}"})
|
2019-06-12 15:55:46 +01:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
go()
|