2020-11-05 23:53:27 +00:00
|
|
|
"""
|
|
|
|
BAPSicle Server
|
|
|
|
Next-gen audio playout server for University Radio York playout,
|
|
|
|
based on WebStudio interface.
|
|
|
|
|
|
|
|
MyRadio API Handler
|
|
|
|
|
2020-11-16 22:49:33 +00:00
|
|
|
In an ideal world, this module gives out and is fed PlanItems.
|
|
|
|
This means it can be swapped for a different backend in the (unlikely) event
|
|
|
|
someone else wants to integrate BAPsicle with something else.
|
|
|
|
|
2020-11-05 23:53:27 +00:00
|
|
|
Authors:
|
|
|
|
Matthew Stratford
|
|
|
|
Michael Grace
|
|
|
|
|
|
|
|
Date:
|
|
|
|
November 2020
|
|
|
|
"""
|
2021-03-21 13:05:33 +00:00
|
|
|
from typing import Optional
|
2020-11-05 23:53:27 +00:00
|
|
|
import requests
|
2021-02-14 00:29:47 +00:00
|
|
|
import json
|
2020-11-05 23:53:27 +00:00
|
|
|
import config
|
2020-11-16 22:49:33 +00:00
|
|
|
from plan import PlanItem
|
2020-11-05 23:53:27 +00:00
|
|
|
from helpers.os_environment import resolve_external_file_path
|
2021-02-14 00:29:47 +00:00
|
|
|
from helpers.logging_manager import LoggingManager
|
|
|
|
from logging import CRITICAL, INFO, DEBUG
|
|
|
|
class MyRadioAPI():
|
|
|
|
logger = None
|
2020-11-05 23:53:27 +00:00
|
|
|
|
2021-02-14 00:29:47 +00:00
|
|
|
def __init__(self, logger: LoggingManager):
|
|
|
|
self.logger = logger
|
2020-11-05 23:53:27 +00:00
|
|
|
|
2021-02-14 00:29:47 +00:00
|
|
|
def get_non_api_call(self, url):
|
|
|
|
|
|
|
|
url = "{}{}".format(config.MYRADIO_BASE_URL, url)
|
|
|
|
|
|
|
|
if "?" in url:
|
|
|
|
url += "&api_key={}".format(config.API_KEY)
|
|
|
|
else:
|
|
|
|
url += "?api_key={}".format(config.API_KEY)
|
|
|
|
|
|
|
|
self._log("Requesting non-API URL: " + url)
|
|
|
|
request = requests.get(url, timeout=10)
|
|
|
|
self._log("Finished request.")
|
|
|
|
|
|
|
|
if request.status_code != 200:
|
|
|
|
self._logException("Failed to get API request. Status code: " + str(request.status_code))
|
|
|
|
self._logException(str(request.content))
|
|
|
|
return None
|
|
|
|
|
|
|
|
return request
|
|
|
|
|
|
|
|
def get_apiv2_call(self, url):
|
|
|
|
|
|
|
|
url = "{}/v2{}".format(config.MYRADIO_API_URL, url)
|
|
|
|
|
|
|
|
if "?" in url:
|
|
|
|
url += "&api_key={}".format(config.API_KEY)
|
|
|
|
else:
|
|
|
|
url += "?api_key={}".format(config.API_KEY)
|
|
|
|
|
|
|
|
self._log("Requesting API V2 URL: " + url)
|
|
|
|
request = requests.get(url, timeout=10)
|
|
|
|
self._log("Finished request.")
|
2020-11-05 23:53:27 +00:00
|
|
|
|
2021-02-14 00:29:47 +00:00
|
|
|
if request.status_code != 200:
|
|
|
|
self._logException("Failed to get API request. Status code: " + str(request.status_code))
|
|
|
|
self._logException(str(request.content))
|
|
|
|
return None
|
|
|
|
|
|
|
|
return request
|
|
|
|
|
2021-03-21 13:05:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Show plans
|
|
|
|
|
|
|
|
|
|
|
|
def get_showplans(self):
|
|
|
|
url = "/timeslot/currentandnext"
|
|
|
|
request = self.get_apiv2_call(url)
|
|
|
|
|
|
|
|
if not request:
|
|
|
|
self._logException("Failed to get list of show plans.")
|
|
|
|
return None
|
|
|
|
|
|
|
|
return json.loads(request.content)["payload"]
|
|
|
|
|
|
|
|
def get_showplan(self, timeslotid: int):
|
|
|
|
|
|
|
|
url = "/timeslot/{}/showplan".format(timeslotid)
|
|
|
|
request = self.get_apiv2_call(url)
|
|
|
|
|
|
|
|
if not request:
|
|
|
|
self._logException("Failed to get show plan.")
|
|
|
|
return None
|
|
|
|
|
|
|
|
return json.loads(request.content)["payload"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Audio Library
|
|
|
|
|
2021-02-14 00:29:47 +00:00
|
|
|
def get_filename(self, item: PlanItem):
|
2020-11-16 22:49:33 +00:00
|
|
|
format = "mp3" # TODO: Maybe we want this customisable?
|
2021-02-14 20:10:32 +00:00
|
|
|
if item.trackid:
|
2020-11-16 22:49:33 +00:00
|
|
|
itemType = "track"
|
2021-02-14 20:10:32 +00:00
|
|
|
id = item.trackid
|
2021-02-14 00:29:47 +00:00
|
|
|
url = "/NIPSWeb/secure_play?trackid={}&{}".format(id, format)
|
2020-11-16 22:49:33 +00:00
|
|
|
|
2021-02-14 20:10:32 +00:00
|
|
|
elif item.managedid:
|
2020-11-16 22:49:33 +00:00
|
|
|
itemType = "managed"
|
2021-02-14 20:10:32 +00:00
|
|
|
id = item.managedid
|
2021-02-14 00:29:47 +00:00
|
|
|
url = "/NIPSWeb/managed_play?managedid={}".format(id)
|
2020-11-05 23:53:27 +00:00
|
|
|
|
2020-11-16 22:49:33 +00:00
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
2020-11-05 23:53:27 +00:00
|
|
|
|
2021-02-14 00:29:47 +00:00
|
|
|
request = self.get_non_api_call(url)
|
|
|
|
|
|
|
|
if not request:
|
2020-11-16 22:49:33 +00:00
|
|
|
return None
|
|
|
|
|
|
|
|
filename: str = resolve_external_file_path("/music-tmp/{}-{}.{}".format(itemType, id, format))
|
2020-11-05 23:53:27 +00:00
|
|
|
|
|
|
|
with open(filename, 'wb') as file:
|
|
|
|
file.write(request.content)
|
|
|
|
|
|
|
|
return filename
|
2021-02-14 00:29:47 +00:00
|
|
|
|
2021-03-21 13:05:33 +00:00
|
|
|
def get_track_search(self, title: Optional[str], artist: Optional[str], limit: int = 100):
|
|
|
|
url = "/track/search?title={}&artist={}&digitised=1&limit={}".format(title if title else "", artist if artist else "", limit)
|
2021-02-14 00:29:47 +00:00
|
|
|
request = self.get_apiv2_call(url)
|
|
|
|
|
|
|
|
if not request:
|
2021-03-21 13:05:33 +00:00
|
|
|
self._logException("Failed to search for track.")
|
2021-02-14 00:29:47 +00:00
|
|
|
return None
|
|
|
|
|
|
|
|
return json.loads(request.content)["payload"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _log(self, text:str, level: int = INFO):
|
|
|
|
self.logger.log.log(level, "MyRadio API: " + text)
|
|
|
|
|
|
|
|
def _logException(self, text:str):
|
|
|
|
self.logger.log.exception("MyRadio API: " + text)
|
|
|
|
|