prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  data.umweltprofis.at: iCal service retired
  I had to change the interval in my data.umweltprofis.at waste schedule when I noticed that the server throws an error when requesting a new iCal link at https://data.umweltprofis.at/opendata/AppointmentService/index.aspx
  
  I contacted their support and they told me that this service is not going to be fixed because they are currently working on (another?) app.
  
  Should this integration be marked as broken for the time being? Existing iCal URLs continue to work, at least for the time being.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py`
  Content:
  ```
  1 import logging
  2 import requests
  3 from waste_collection_schedule import Collection  # type: ignore[attr-defined]
  4 from waste_collection_schedule.service.ICS import ICS
  5 
  6 TITLE = "UMWELTPROFIS"
  7 DESCRIPTION = "Source for Umweltprofis"
  8 URL = "https://www.umweltprofis.at"
  9 TEST_CASES = {
  10     "Ebensee": {"url": "https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1"},
  11 }
  12 
  13 _LOGGER = logging.getLogger(__name__)
  14 
  15 
  16 class Source:
  17     def __init__(self, url):
  18         self._url = url
  19         self._ics = ICS()
  20 
  21     def fetch(self):
  22         r = requests.get(self._url)
  23         if r.status_code != 200:
  24             _LOGGER.error("Error querying calendar data")
  25             return []
  26 
  27         fixed_text = r.text.replace("REFRESH - INTERVAL; VALUE = ", "REFRESH-INTERVAL;VALUE=")
  28 
  29         dates = self._ics.convert(fixed_text)
  30 
  31         entries = []
  32         for d in dates:
  33             entries.append(Collection(d[0], d[1]))
  34         return entries
  35
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
  --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
  +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py
  @@ -1,5 +1,7 @@
   import logging
   import requests
  +from datetime import datetime
  +from xml.dom.minidom import parseString
   from waste_collection_schedule import Collection  # type: ignore[attr-defined]
   from waste_collection_schedule.service.ICS import ICS
   
  @@ -8,17 +10,33 @@
   URL = "https://www.umweltprofis.at"
   TEST_CASES = {
       "Ebensee": {"url": "https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1"},
  +    "Rohrbach": {"xmlurl": "https://data.umweltprofis.at/opendata/AppointmentService/AppointmentService.asmx/GetTermineForLocationSecured?Key=TEMPKeyabvvMKVCic0cMcmsTEMPKey&StreetNr=118213&HouseNr=Alle&intervall=Alle"},
   }
   
   _LOGGER = logging.getLogger(__name__)
   
  +def getText(element):
  +    s = ""
  +    for e in element.childNodes:
  +        if e.nodeType == e.TEXT_NODE:
  +            s += e.nodeValue
  +    return s
   
   class Source:
  -    def __init__(self, url):
  +    def __init__(self, url=None, xmlurl=None):
           self._url = url
  +        self._xmlurl = xmlurl
           self._ics = ICS()
  +        if url is None and xmlurl is None:
  +            raise Exception("either url or xmlurl needs to be specified")
   
       def fetch(self):
  +        if self._url is not None:
  +            return self.fetch_ics()
  +        elif self._xmlurl is not None:
  +            return self.fetch_xml()
  +
  +    def fetch_ics(self):
           r = requests.get(self._url)
           if r.status_code != 200:
               _LOGGER.error("Error querying calendar data")
  @@ -32,3 +50,18 @@
           for d in dates:
               entries.append(Collection(d[0], d[1]))
           return entries
  +
  +    def fetch_xml(self):
  +        r = requests.get(self._xmlurl)
  +        r.raise_for_status()
  +
  +        doc = parseString(r.text)
  +        appointments = doc.getElementsByTagName("AppointmentEntry")
  +
  +        entries = []
  +        for a in appointments:
  +            date_string = getText(a.getElementsByTagName("Datum")[0])
  +            date = datetime.fromisoformat(date_string).date()
  +            waste_type = getText(a.getElementsByTagName("WasteType")[0])
  +            entries.append(Collection(date, waste_type))
  +        return entries
  
verification_info: {"golden_diff": "diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py\n--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py\n+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py\n@@ -1,5 +1,7 @@\n import logging\n import requests\n+from datetime import datetime\n+from xml.dom.minidom import parseString\n from waste_collection_schedule import Collection  # type: ignore[attr-defined]\n from waste_collection_schedule.service.ICS import ICS\n \n@@ -8,17 +10,33 @@\n URL = \"https://www.umweltprofis.at\"\n TEST_CASES = {\n     \"Ebensee\": {\"url\": \"https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1\"},\n+    \"Rohrbach\": {\"xmlurl\": \"https://data.umweltprofis.at/opendata/AppointmentService/AppointmentService.asmx/GetTermineForLocationSecured?Key=TEMPKeyabvvMKVCic0cMcmsTEMPKey&StreetNr=118213&HouseNr=Alle&intervall=Alle\"},\n }\n \n _LOGGER = logging.getLogger(__name__)\n \n+def getText(element):\n+    s = \"\"\n+    for e in element.childNodes:\n+        if e.nodeType == e.TEXT_NODE:\n+            s += e.nodeValue\n+    return s\n \n class Source:\n-    def __init__(self, url):\n+    def __init__(self, url=None, xmlurl=None):\n         self._url = url\n+        self._xmlurl = xmlurl\n         self._ics = ICS()\n+        if url is None and xmlurl is None:\n+            raise Exception(\"either url or xmlurl needs to be specified\")\n \n     def fetch(self):\n+        if self._url is not None:\n+            return self.fetch_ics()\n+        elif self._xmlurl is not None:\n+            return self.fetch_xml()\n+\n+    def fetch_ics(self):\n         r = requests.get(self._url)\n         if r.status_code != 200:\n             _LOGGER.error(\"Error querying calendar data\")\n@@ -32,3 +50,18 @@\n         for d in dates:\n             entries.append(Collection(d[0], d[1]))\n         return entries\n+\n+    def fetch_xml(self):\n+        r = requests.get(self._xmlurl)\n+        r.raise_for_status()\n+\n+        doc = parseString(r.text)\n+        appointments = doc.getElementsByTagName(\"AppointmentEntry\")\n+\n+        entries = []\n+        for a in appointments:\n+            date_string = getText(a.getElementsByTagName(\"Datum\")[0])\n+            date = datetime.fromisoformat(date_string).date()\n+            waste_type = getText(a.getElementsByTagName(\"WasteType\")[0])\n+            entries.append(Collection(date, waste_type))\n+        return entries\n", "issue": "data.umweltprofis.at: iCal service retired\nI had to change the interval in my data.umweltprofis.at waste schedule when I noticed that the server throws an error when requesting a new iCal link at https://data.umweltprofis.at/opendata/AppointmentService/index.aspx\r\n\r\nI contacted their support and they told me that this service is not going to be fixed because they are currently working on (another?) app.\r\n\r\nShould this integration be marked as broken for the time being? Existing iCal URLs continue to work, at least for the time being.\n", "before_files": [{"content": "import logging\nimport requests\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\nfrom waste_collection_schedule.service.ICS import ICS\n\nTITLE = \"UMWELTPROFIS\"\nDESCRIPTION = \"Source for Umweltprofis\"\nURL = \"https://www.umweltprofis.at\"\nTEST_CASES = {\n    \"Ebensee\": {\"url\": \"https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1\"},\n}\n\n_LOGGER = logging.getLogger(__name__)\n\n\nclass Source:\n    def __init__(self, url):\n        self._url = url\n        self._ics = ICS()\n\n    def fetch(self):\n        r = requests.get(self._url)\n        if r.status_code != 200:\n            _LOGGER.error(\"Error querying calendar data\")\n            return []\n\n        fixed_text = r.text.replace(\"REFRESH - INTERVAL; VALUE = \", \"REFRESH-INTERVAL;VALUE=\")\n\n        dates = self._ics.convert(fixed_text)\n\n        entries = []\n        for d in dates:\n            entries.append(Collection(d[0], d[1]))\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py"}], "after_files": [{"content": "import logging\nimport requests\nfrom datetime import datetime\nfrom xml.dom.minidom import parseString\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\nfrom waste_collection_schedule.service.ICS import ICS\n\nTITLE = \"UMWELTPROFIS\"\nDESCRIPTION = \"Source for Umweltprofis\"\nURL = \"https://www.umweltprofis.at\"\nTEST_CASES = {\n    \"Ebensee\": {\"url\": \"https://data.umweltprofis.at/OpenData/AppointmentService/AppointmentService.asmx/GetIcalWastePickupCalendar?key=KXX_K0bIXDdk0NrTkk3xWqLM9-bsNgIVBE6FMXDObTqxmp9S39nIqwhf9LTIAX9shrlpfCYU7TG_8pS9NjkAJnM_ruQ1SYm3V9YXVRfLRws1\"},\n    \"Rohrbach\": {\"xmlurl\": \"https://data.umweltprofis.at/opendata/AppointmentService/AppointmentService.asmx/GetTermineForLocationSecured?Key=TEMPKeyabvvMKVCic0cMcmsTEMPKey&StreetNr=118213&HouseNr=Alle&intervall=Alle\"},\n}\n\n_LOGGER = logging.getLogger(__name__)\n\ndef getText(element):\n    s = \"\"\n    for e in element.childNodes:\n        if e.nodeType == e.TEXT_NODE:\n            s += e.nodeValue\n    return s\n\nclass Source:\n    def __init__(self, url=None, xmlurl=None):\n        self._url = url\n        self._xmlurl = xmlurl\n        self._ics = ICS()\n        if url is None and xmlurl is None:\n            raise Exception(\"either url or xmlurl needs to be specified\")\n\n    def fetch(self):\n        if self._url is not None:\n            return self.fetch_ics()\n        elif self._xmlurl is not None:\n            return self.fetch_xml()\n\n    def fetch_ics(self):\n        r = requests.get(self._url)\n        if r.status_code != 200:\n            _LOGGER.error(\"Error querying calendar data\")\n            return []\n\n        fixed_text = r.text.replace(\"REFRESH - INTERVAL; VALUE = \", \"REFRESH-INTERVAL;VALUE=\")\n\n        dates = self._ics.convert(fixed_text)\n\n        entries = []\n        for d in dates:\n            entries.append(Collection(d[0], d[1]))\n        return entries\n\n    def fetch_xml(self):\n        r = requests.get(self._xmlurl)\n        r.raise_for_status()\n\n        doc = parseString(r.text)\n        appointments = doc.getElementsByTagName(\"AppointmentEntry\")\n\n        entries = []\n        for a in appointments:\n            date_string = getText(a.getElementsByTagName(\"Datum\")[0])\n            date = datetime.fromisoformat(date_string).date()\n            waste_type = getText(a.getElementsByTagName(\"WasteType\")[0])\n            entries.append(Collection(date, waste_type))\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/data_umweltprofis_at.py"}]}