# # 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, TypedDict, Union import requests from django.conf import settings from django.utils import timezone if typing.TYPE_CHECKING: from program.models import Host, HostLink, Note, NoteLink, Show, ShowLink class Link(TypedDict): type_id: int url: str def parse_datetime(date_string: str | None) -> datetime | None: """ parse a datetime string and return a timezone aware datetime object. Returns `None` if no datetime string is given. """ if date_string is None: return None 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 | None) -> date | None: """ parse a date string and return a date object. Returns `None` if no date string is given. """ if date_string is None: return None return datetime.strptime(date_string, "%Y-%m-%d").date() def parse_time(date_string: str | None) -> time | None: """ parse a time string and return a time object. Returns `None` if no time string is given. """ if date_string is None: return None 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 update_links( instance: Union["Host", "Note", "Show"], links: list[Link] ) -> Union["Host", "Note", "Show"]: """Update the links associated with the instance""" # delete the links associated with the instance if instance.links.count() > 0: for link in instance.links.all(): link.delete(keep_parents=True) match type(instance): case "Host": for link_data in links: HostLink.objects.create(host=instance, **link_data) case "Note": for link_data in links: NoteLink.objects.create(note=instance, **link_data) case "Show": for link_data in links: ShowLink.objects.create(show=instance, **link_data) return instance