# # steering, Programme/schedule management for AURA # # Copyright (C) 2011-2017, 2020, Ernesto Rico Schmidt # Copyright (C) 2017-2019, Ingo Leindecker # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU Affero General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more # details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # import json import typing from datetime import date, datetime, time from typing import Dict, Optional, Tuple, Union import requests from rest_framework import exceptions from django.conf import settings from django.utils import timezone if typing.TYPE_CHECKING: from program.models import Host, Note, Show def parse_datetime(date_string: str) -> datetime: """ parse a datetime string and return a timezone aware datetime object """ try: parsed_datetime = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S") except ValueError: parsed_datetime = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S%z") return ( timezone.make_aware(parsed_datetime) if timezone.is_naive(parsed_datetime) else parsed_datetime ) def parse_date(date_string: str) -> date: """ parse a date string and return a date object """ return datetime.strptime(date_string, "%Y-%m-%d").date() def parse_time(date_string: str) -> time: """ parse a time string and return a time object """ if len(date_string) == 5: return datetime.strptime(date_string, "%H:%M").time() else: return datetime.strptime(date_string, "%H:%M:%S").time() def get_audio_url(cba_id: Optional[int]) -> str: """ Retrieve the direct URL to the mp3 in CBA In order to retrieve the URL, stations need - to be whitelisted by CBA - an API Key For these contact cba@fro.at """ if not cba_id or settings.CBA_API_KEY == "": return "" else: if settings.DEBUG: url = ( "https://cba.fro.at/wp-content/plugins/cba/ajax/cba-get-filename.php?post_id=" + str(cba_id) + "&c=Ml3fASkfwR8" ) else: url = ( settings.CBA_AJAX_URL + "?action=cba_ajax_get_filename&post_id=" + str(cba_id) + "&api_key=" + settings.CBA_API_KEY ) try: return requests.get(url).json() except (requests.RequestException, json.JSONDecodeError): # TODO: we might want to add some logging return "" def get_values( kwargs: Dict[str, str], *keys: str ) -> Union[Tuple[Union[int, str, None], ...], int, str, None]: """Get the values of the keys from the kwargs.""" def int_if_digit(value: Optional[str]) -> Optional[Union[int, str]]: return int(value) if value and value.isdigit() else value values = [kwargs.get(key) for key in keys] if len(values) > 1: return tuple(int_if_digit(value) for value in values) else: return int_if_digit(values[0]) def delete_links(instance: Union["Host", "Note", "Show"]) -> Union["Host", "Note", "Show"]: """Delete the links associated with the instance.""" if instance.links.count() > 0: for link in instance.links.all(): link.delete(keep_parents=True) return instance class NestedObjectFinderMixin: ROUTE_FILTER_LOOKUPS = {} def _get_route_filters(self) -> Dict[str, int]: filter_kwargs = {} for key, value in self.kwargs.items(): if key in self.ROUTE_FILTER_LOOKUPS: try: filter_kwargs[self.ROUTE_FILTER_LOOKUPS[key]] = int(value) except ValueError: raise exceptions.ValidationError( detail=f"{key} must map to an integer value.", code="invalid-pk" ) return filter_kwargs def get_queryset(self): return super().get_queryset().filter(**self._get_route_filters())