From f33bba162d7465a0a8ccfe9867fe5d54f23b5aaa Mon Sep 17 00:00:00 2001 From: David Trattnig <david.trattnig@gmail.com> Date: Thu, 24 Oct 2019 13:34:08 +0200 Subject: [PATCH] Refactored calendar fetcher to work with latest Steering and Tank API. --- configuration/engine.ini | 10 +++-- modules/scheduling/calender_fetcher.py | 58 ++++++++++++++++++++------ 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/configuration/engine.ini b/configuration/engine.ini index 1a82de62..59bd9f78 100644 --- a/configuration/engine.ini +++ b/configuration/engine.ini @@ -29,10 +29,12 @@ from_mail="monitor@aura.py" mailsubject_prefix="[AURA]" [dataurls] -# the url of pv/steering +# The URL to get the Calendar via PV/Steering calendarurl="http://localhost:8000/api/v1/playout" -# the url of tank -importerurl="http://localhost:8040/api/v1/groups/_public/playlists/" +# The URL to get show details via PV/Steering +api_show_url="http://localhost:8000/api/v1/shows/${ID}/" +# The URL to get playlist details via Tank +importerurl="http://localhost:8040/api/v1/shows/${SLUG}/playlists" # how often should the calendar be fetched in seconds (This determines the time of the last change before a specific show) fetching_frequency=3600 @@ -55,7 +57,7 @@ daemongroup="gg" daemonuser="gg" [socket] -socketdir="/home/gg/PycharmProjects/engine/modules/liquidsoap" +socketdir="~/code/aura/aura-engine/modules/liquidsoap" [logging] logdir="/var/log/aura" diff --git a/modules/scheduling/calender_fetcher.py b/modules/scheduling/calender_fetcher.py index 42978ece..d5a4316d 100644 --- a/modules/scheduling/calender_fetcher.py +++ b/modules/scheduling/calender_fetcher.py @@ -21,11 +21,12 @@ class CalendarFetcher: self.logger = logging.getLogger("AuraEngine") self.__set_url__("calendar") self.__set_url__("importer") + self.__set_url__("api_show_") def fetch(self): # fetch upcoming schedules from STEERING self.logger.debug("Fetching schedules from STEERING") - self.__fetch_schedule_data__() + self.fetched_schedule_data = self.__fetch_schedule_data__() # fetch playlist and fallbacks to the schedules from TANK self.logger.debug("Fetching playlists from TANK") self.__fetch_schedule_entry_data__() @@ -61,6 +62,7 @@ class CalendarFetcher: # fetch data from steering html_response = self.__fetch_data__(servicetype) + # FIXME move hardcoded test-data to separate testing logic. # use testdata if response fails or is empty if not html_response or html_response == b"[]": self.logger.debug("Got no response: Using testdata") @@ -76,7 +78,7 @@ class CalendarFetcher: # check data self.logger.critical("Hardcoded Response && no JSON data checks. I believe what i get here") - return self.remove_unnecessary_data(self.fetched_schedule_data) + return self.remove_unnecessary_data(schedule_from_pv) # ------------------------------------------------------------------------------------------ # def __fetch_schedule_entry_data__(self): @@ -85,6 +87,9 @@ class CalendarFetcher: try: for schedule in self.fetched_schedule_data: + + # Enhance schedule with details of show (e.g. slug) + schedule = self.__fetch_show_details__(schedule) # retrieve playlist and the fallbacks for every schedule # if a playlist (like station_fallback) is already fetched, it is not fetched again but reused schedule["playlist"] = self.__fetch_schedule_entries__(schedule, "playlist_id", fetched_entries) @@ -95,15 +100,32 @@ class CalendarFetcher: self.logger.info(str(schedule)) except Exception as e: - self.logger.error(str(e)) + self.logger.error("Error: "+str(e)) + + # ------------------------------------------------------------------------------------------ # + def __fetch_show_details__(self, schedule): + servicetype = "api_show_" + + json_response = self.__fetch_data__(servicetype, "${ID}", str(schedule["show_id"])) + show_details = simplejson.loads(json_response) + + # Augment "schedules" with details of "show" + schedule["show_slug"] = show_details["slug"] + ### ... add more properties here, if needed ... ### + + return schedule # ------------------------------------------------------------------------------------------ # def __fetch_schedule_entries__(self, schedule, id_name, fetched_schedule_entries): servicetype = "importer" use_testdata = False - # fetch data from importer - json_response = self.__fetch_data__(servicetype) + # fetch playlists from TANK + if not "show_slug" in schedule: + raise ValueError("Missing 'show_slug' for schedule", schedule) + + slug = str(schedule["show_slug"]) + json_response = self.__fetch_data__(servicetype, "${SLUG}", slug) if not json_response: use_testdata = True @@ -113,6 +135,7 @@ class CalendarFetcher: self.logger.debug("playlist #" + str(schedule[id_name]) + " already fetched") return entry + # FIXME move hardcoded test-data to separate testing logic. # generate testdata if use_testdata: json_response = self.create_test_data(id_name, schedule) @@ -136,31 +159,39 @@ class CalendarFetcher: return schedule_entries # ------------------------------------------------------------------------------------------ # - def __fetch_data__(self, type): - # init html_response + def __fetch_data__(self, type, placeholder=None, value=None): + # Init html_response html_response = "" + url = self.__build_url__(type, placeholder, value) - # open an url and read the data + # Send request to the API and read the data try: if type not in self.data: if self.url[type] == "": return False - request = urllib.request.Request(self.url[type]) + request = urllib.request.Request(url) else: - request = urllib.request.Request(self.url[type], self.data[type]) + request = urllib.request.Request(url, self.data[type]) response = urllib.request.urlopen(request) html_response = response.read() except (urllib.error.URLError, IOError, ValueError) as e: - self.logger.error("Cannot connect to " + self.url[type] + "! reason: " + str(e.reason)) + self.logger.error("Cannot connect to " + self.url[type] + + " (type: " + type + ")! Reason: " + str(e.reason)) if not self.has_already_fetched: # first fetch self.logger.critical("exiting fetch data thread..") sys.exit() self.has_already_fetched = True return html_response - + # ------------------------------------------------------------------------------------------ # + def __build_url__(self, type, placeholder=None, value=None): + url = self.url[type] + if placeholder: + url = url.replace(placeholder, value) + # print("built URL: "+url) + return url # ------------------------------------------------------------------------------------------ # def remove_unnecessary_data(self, schedule): return self.remove_data_more_than_24h_in_the_future(self.remove_data_in_the_past(schedule)) @@ -208,6 +239,7 @@ class CalendarFetcher: self.used_random_playlist_ids.append(rand_id) + # FIXME move hardcoded test-data to separate testing logic. # HARDCODED Testdata if id_name != "playlist_id": # FALLBACK TESTDATA @@ -252,4 +284,4 @@ class CalendarFetcher: self.logger.info("Using 'randomized' playlist: " + json_response + " for " + id_name[:-3] + " for show " + schedule["show_name"] + " starting @ " + schedule["start"]) - return json_response \ No newline at end of file + return json_response -- GitLab