import configparser import icalendar import datetime import requests import urllib import glob import pytz import json import os def read_config(): config = configparser.ConfigParser() config.read('config.ini') return config config = read_config() current_year = datetime.datetime.now().year # request locations supportet by the endpoint # https://nuernberg-abfallapp.regioit.de/abfall-app-nuernberg/rest/orte # Returns: # [{"id":2049161,"name":"Nürnberg"}] req = requests.get("https://nuernberg-abfallapp.regioit.de/abfall-app-nuernberg/rest/orte") locations = req.json() for location in locations: if location.get("name") == config["address"]["city"]: nbg_id = location.get("id") # request all known streets for a given location id (can be obtained by previous request) req = requests.get("https://nuernberg-abfallapp.regioit.de/abfall-app-nuernberg/rest/orte/{location_id}/strassen".format(location_id=nbg_id)) streets = req.json() for street in streets: if street.get("name") == config["address"]["street"]: street_id = street.get("id") # request all known house numbers for a given street id (can be obtained by previous request) req = requests.get("https://nuernberg-abfallapp.regioit.de/abfall-app-nuernberg/rest/strassen/{street_id}".format(street_id=street_id)) housenumbers = req.json().get("hausNrList", []) for number in housenumbers: if number.get("nr") == config["address"]["house_number"]: housenumber_id = number.get("id") # request trash types picked up at that location req = requests.get("https://nuernberg-abfallapp.regioit.de/abfall-app-nuernberg/rest/hausnummern/{housenumber_id}/fraktionen".format(housenumber_id=housenumber_id)) trash_types = req.json() for trash_type in trash_types: print(trash_type.get("name")) #requested_trash_types = list(map(lambda x: str(x.get("id")), trash_types)) query = { "format": ["ics"], "jahr": [current_year], "ort": ["Nürnberg"], "strasse": [street_id], "hnr": [housenumber_id], "fraktion": [] } radicale_props = { "C:supported-calendar-component-set": "VEVENT", "D:displayname": None, "ICAL:calendar-color": "#000000ff", "tag": "VCALENDAR" } target_path = config.get("calendar", "target", fallback=os.path.join(".", "calendars")) if not os.path.exists(target_path): os.makedirs(target_path) for trash_type in trash_types: radicale_props["D:displayname"] = trash_type.get("name") radicale_props["ICAL:calendar-color"] = "#{}ff".format(trash_type.get("farbeRgb", "000000")) folder_name = trash_type.get("name").replace("/", "_") trash_type_folder = os.path.join(target_path, folder_name) if not os.path.exists(trash_type_folder): os.makedirs(trash_type_folder) for f in os.listdir(trash_type_folder): ical_path = os.path.join(trash_type_folder, f) if os.path.isfile(ical_path): with open(ical_path, "rb") as fh: try: cal = icalendar.Calendar.from_ical(fh.read()) except ValueError: print("{} is not an parsable ical file".format(ical_path)) continue if cal.walk()[1]["DTSTART"].dt > datetime.datetime.now(pytz.utc): os.remove(ical_path) radicale_prop_file = os.path.join(trash_type_folder, ".Radicale.props") with open(radicale_prop_file, "w") as f: f.write(json.dumps(radicale_props)) query["fraktion"] = [str(trash_type["id"])] query_string = urllib.parse.urlencode(query, doseq=True) query_url = urllib.parse.urlunparse(("https", "abfallkalender.regioit.de", "/kalender-nuernberg/downloadfile.jsp", "", query_string, "")) req = requests.get(query_url) ical = req.text cal = icalendar.Calendar.from_ical(ical) for event in cal.walk(): if isinstance(event, icalendar.cal.Event): uid = event.get("UID") new_cal = icalendar.Calendar() new_cal.add('prodid', 'Trash dates') new_cal.add('version', '2.0') new_cal.add_component(event) ical_name = "{}_{}.ical".format(current_year, uid) ical_path = os.path.join(trash_type_folder, ical_name) with open(ical_path, "wb") as single_file: single_file.write(new_cal.to_ical()) else: pass