We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Changes to Campbelltown Council URLs and APIs have broken the ability to retrieve waste collection info (campbelltown_nsw_gov_au.py)
Hi there,

I'm absolutely useless with Python or I'd be coding a fix and lodging a pull request, but instead am posting this as an issue at the community's mercy :)

The Campbelltown Council (Australia) API URLs have changed, and I believe that they're now presenting address search data a little differently too - XML instead of JSON.

The overall pattern still appears to be the same:

1. Retrieve the GeolocationID for a given address via the 'address_search' API
2. Plug that GeolocationID into the 'collection' API to retrieve the waste collection info in HTML format, wrapped in JSON

**URLs in existing version of Campbelltown NSW AU Waste Collection Source:**
```
API_URLS = {
    "address_search": "https://www.campbelltown.nsw.gov.au/ocsvc/public/spatial/findaddress?address={}",
    "collection": "https://www.campbelltown.nsw.gov.au/ocsvc/Public/InMyNeighbourhood/WasteServices?GeoLocationId={}",
}
```

**URLs that work now:**
```
API_URLS = {
    "address_search": "https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords={}",
    "collection": "https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid={}&ocsvclang=en-AU",
}
```

I'm not familiar with the old Campbelltown address search API, but looking at the code it appears that it used to return JSON data. It's now returning pure XML. 

**Examples using the new API URLs:**
Address search result: [https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords=10%20Brookfield%20Road%20Minto%20NSW%202566](https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords=10%20Brookfield%20Road%20Minto%20NSW%202566)

Collection API result for the above GeolocationID: [https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid=401ee13b-b04c-4948-82e4-09d274c479a0&ocsvclang=en-AU](https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid=401ee13b-b04c-4948-82e4-09d274c479a0&ocsvclang=en-AU)

--- 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/campbelltown_nsw_gov_au.py`
Content:
```
1 import datetime
2 import json
3 
4 import requests
5 from bs4 import BeautifulSoup
6 from requests.utils import requote_uri
7 from waste_collection_schedule import Collection
8 
9 TITLE = "Campbelltown City Council"
10 DESCRIPTION = "Source for Campbelltown City Council rubbish collection."
11 URL = "https://www.campbelltown.nsw.gov.au/"
12 TEST_CASES = {
13     "Minto Mall": {
14         "post_code": "2566",
15         "suburb": "Minto",
16         "street_name": "Brookfield Road",
17         "street_number": "10",
18     },
19     "Campbelltown Catholic Club": {
20         "post_code": "2560",
21         "suburb": "Campbelltown",
22         "street_name": "Camden Road",
23         "street_number": "20-22",
24     },
25     "Australia Post Ingleburn": {
26         "post_code": "2565",
27         "suburb": "INGLEBURN",
28         "street_name": "Oxford Road",
29         "street_number": "34",
30     },
31 }
32 
33 API_URLS = {
34     "address_search": "https://www.campbelltown.nsw.gov.au/ocsvc/public/spatial/findaddress?address={}",
35     "collection": "https://www.campbelltown.nsw.gov.au/ocsvc/Public/InMyNeighbourhood/WasteServices?GeoLocationId={}",
36 }
37 
38 HEADERS = {"user-agent": "Mozilla/5.0"}
39 
40 ICON_MAP = {
41     "General Waste": "trash-can",
42     "Recycling": "mdi:recycle",
43     "Green Waste": "mdi:leaf",
44 }
45 
46 
47 class Source:
48     def __init__(
49         self, post_code: str, suburb: str, street_name: str, street_number: str
50     ):
51         self.post_code = post_code
52         self.suburb = suburb
53         self.street_name = street_name
54         self.street_number = street_number
55 
56     def fetch(self):
57         locationId = 0
58 
59         address = "{} {} {} NSW {}".format(
60             self.street_number, self.street_name, self.suburb, self.post_code
61         )
62 
63         q = requote_uri(str(API_URLS["address_search"]).format(address))
64 
65         # Retrieve suburbs
66         r = requests.get(q, headers=HEADERS)
67 
68         data = json.loads(r.text)
69 
70         # Find the ID for our suburb
71         for item in data["locations"]:
72             locationId = item["Id"]
73             break
74 
75         if locationId == 0:
76             return []
77 
78         # Retrieve the upcoming collections for our property
79         q = requote_uri(str(API_URLS["collection"]).format(locationId))
80 
81         r = requests.get(q, headers=HEADERS)
82 
83         data = json.loads(r.text)
84 
85         responseContent = data["responseContent"]
86 
87         soup = BeautifulSoup(responseContent, "html.parser")
88         services = soup.find_all("div", attrs={"class": "service-details"})
89 
90         entries = []
91 
92         for item in services:
93             # test if <div> contains a valid date. If not, is is not a collection item.
94             date_text = item.find("span")
95             try:
96                 date = datetime.datetime.strptime(date_text.text, "%A%d %b %Y").date()
97 
98             except ValueError:
99                 continue
100 
101             waste_type = item.contents[0].strip()
102 
103             entries.append(
104                 Collection(
105                     date=date,
106                     t=waste_type,
107                     icon=ICON_MAP.get(waste_type, "mdi:trash-can"),
108                 )
109             )
110 
111         return entries
112
```
--- 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()

```

diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py
--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py
+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py
@@ -31,8 +31,8 @@
 }
 
 API_URLS = {
-    "address_search": "https://www.campbelltown.nsw.gov.au/ocsvc/public/spatial/findaddress?address={}",
-    "collection": "https://www.campbelltown.nsw.gov.au/ocsvc/Public/InMyNeighbourhood/WasteServices?GeoLocationId={}",
+    "address_search": "https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords={}",
+    "collection": "https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid={}&ocsvclang=en-AU",
 }
 
 HEADERS = {"user-agent": "Mozilla/5.0"}
@@ -43,7 +43,6 @@
     "Green Waste": "mdi:leaf",
 }
 
-
 class Source:
     def __init__(
         self, post_code: str, suburb: str, street_name: str, street_number: str
@@ -68,7 +67,7 @@
         data = json.loads(r.text)
 
         # Find the ID for our suburb
-        for item in data["locations"]:
+        for item in data["Items"]:
             locationId = item["Id"]
             break
 
@@ -85,20 +84,28 @@
         responseContent = data["responseContent"]
 
         soup = BeautifulSoup(responseContent, "html.parser")
-        services = soup.find_all("div", attrs={"class": "service-details"})
+        services = soup.find_all("div", attrs={"class": "waste-services-result"})
 
         entries = []
 
         for item in services:
             # test if <div> contains a valid date. If not, is is not a collection item.
-            date_text = item.find("span")
+            date_text = item.find("div", attrs={"class": "next-service"})
+            
+            # The date format currently used on https://www.campbelltown.nsw.gov.au/Services-and-Facilities/Waste-and-Recycling/Check-my-collection-day
+            date_format = '%a %d/%m/%Y'
+
             try:
-                date = datetime.datetime.strptime(date_text.text, "%A%d %b %Y").date()
+                # Strip carriage returns and newlines out of the HTML content
+                cleaned_date_text = date_text.text.replace('\r','').replace('\n','').strip()
+
+                # Parse the date
+                date = datetime.datetime.strptime(cleaned_date_text, date_format).date()
 
             except ValueError:
                 continue
 
-            waste_type = item.contents[0].strip()
+            waste_type = item.find("h3").text.strip()
 
             entries.append(
                 Collection(

{"golden_diff": "diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py\n--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py\n+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py\n@@ -31,8 +31,8 @@\n }\n \n API_URLS = {\n-    \"address_search\": \"https://www.campbelltown.nsw.gov.au/ocsvc/public/spatial/findaddress?address={}\",\n-    \"collection\": \"https://www.campbelltown.nsw.gov.au/ocsvc/Public/InMyNeighbourhood/WasteServices?GeoLocationId={}\",\n+    \"address_search\": \"https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords={}\",\n+    \"collection\": \"https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid={}&ocsvclang=en-AU\",\n }\n \n HEADERS = {\"user-agent\": \"Mozilla/5.0\"}\n@@ -43,7 +43,6 @@\n     \"Green Waste\": \"mdi:leaf\",\n }\n \n-\n class Source:\n     def __init__(\n         self, post_code: str, suburb: str, street_name: str, street_number: str\n@@ -68,7 +67,7 @@\n         data = json.loads(r.text)\n \n         # Find the ID for our suburb\n-        for item in data[\"locations\"]:\n+        for item in data[\"Items\"]:\n             locationId = item[\"Id\"]\n             break\n \n@@ -85,20 +84,28 @@\n         responseContent = data[\"responseContent\"]\n \n         soup = BeautifulSoup(responseContent, \"html.parser\")\n-        services = soup.find_all(\"div\", attrs={\"class\": \"service-details\"})\n+        services = soup.find_all(\"div\", attrs={\"class\": \"waste-services-result\"})\n \n         entries = []\n \n         for item in services:\n             # test if <div> contains a valid date. If not, is is not a collection item.\n-            date_text = item.find(\"span\")\n+            date_text = item.find(\"div\", attrs={\"class\": \"next-service\"})\n+            \n+            # The date format currently used on https://www.campbelltown.nsw.gov.au/Services-and-Facilities/Waste-and-Recycling/Check-my-collection-day\n+            date_format = '%a %d/%m/%Y'\n+\n             try:\n-                date = datetime.datetime.strptime(date_text.text, \"%A%d %b %Y\").date()\n+                # Strip carriage returns and newlines out of the HTML content\n+                cleaned_date_text = date_text.text.replace('\\r','').replace('\\n','').strip()\n+\n+                # Parse the date\n+                date = datetime.datetime.strptime(cleaned_date_text, date_format).date()\n \n             except ValueError:\n                 continue\n \n-            waste_type = item.contents[0].strip()\n+            waste_type = item.find(\"h3\").text.strip()\n \n             entries.append(\n                 Collection(\n", "issue": "Changes to Campbelltown Council URLs and APIs have broken the ability to retrieve waste collection info (campbelltown_nsw_gov_au.py)\nHi there,\r\n\r\nI'm absolutely useless with Python or I'd be coding a fix and lodging a pull request, but instead am posting this as an issue at the community's mercy :)\r\n\r\nThe Campbelltown Council (Australia) API URLs have changed, and I believe that they're now presenting address search data a little differently too - XML instead of JSON.\r\n\r\nThe overall pattern still appears to be the same:\r\n\r\n1. Retrieve the GeolocationID for a given address via the 'address_search' API\r\n2. Plug that GeolocationID into the 'collection' API to retrieve the waste collection info in HTML format, wrapped in JSON\r\n\r\n**URLs in existing version of Campbelltown NSW AU Waste Collection Source:**\r\n```\r\nAPI_URLS = {\r\n    \"address_search\": \"https://www.campbelltown.nsw.gov.au/ocsvc/public/spatial/findaddress?address={}\",\r\n    \"collection\": \"https://www.campbelltown.nsw.gov.au/ocsvc/Public/InMyNeighbourhood/WasteServices?GeoLocationId={}\",\r\n}\r\n```\r\n\r\n**URLs that work now:**\r\n```\r\nAPI_URLS = {\r\n    \"address_search\": \"https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords={}\",\r\n    \"collection\": \"https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid={}&ocsvclang=en-AU\",\r\n}\r\n```\r\n\r\nI'm not familiar with the old Campbelltown address search API, but looking at the code it appears that it used to return JSON data. It's now returning pure XML. \r\n\r\n**Examples using the new API URLs:**\r\nAddress search result: [https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords=10%20Brookfield%20Road%20Minto%20NSW%202566](https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords=10%20Brookfield%20Road%20Minto%20NSW%202566)\r\n\r\nCollection API result for the above GeolocationID: [https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid=401ee13b-b04c-4948-82e4-09d274c479a0&ocsvclang=en-AU](https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid=401ee13b-b04c-4948-82e4-09d274c479a0&ocsvclang=en-AU)\n", "before_files": [{"content": "import datetime\nimport json\n\nimport requests\nfrom bs4 import BeautifulSoup\nfrom requests.utils import requote_uri\nfrom waste_collection_schedule import Collection\n\nTITLE = \"Campbelltown City Council\"\nDESCRIPTION = \"Source for Campbelltown City Council rubbish collection.\"\nURL = \"https://www.campbelltown.nsw.gov.au/\"\nTEST_CASES = {\n    \"Minto Mall\": {\n        \"post_code\": \"2566\",\n        \"suburb\": \"Minto\",\n        \"street_name\": \"Brookfield Road\",\n        \"street_number\": \"10\",\n    },\n    \"Campbelltown Catholic Club\": {\n        \"post_code\": \"2560\",\n        \"suburb\": \"Campbelltown\",\n        \"street_name\": \"Camden Road\",\n        \"street_number\": \"20-22\",\n    },\n    \"Australia Post Ingleburn\": {\n        \"post_code\": \"2565\",\n        \"suburb\": \"INGLEBURN\",\n        \"street_name\": \"Oxford Road\",\n        \"street_number\": \"34\",\n    },\n}\n\nAPI_URLS = {\n    \"address_search\": \"https://www.campbelltown.nsw.gov.au/ocsvc/public/spatial/findaddress?address={}\",\n    \"collection\": \"https://www.campbelltown.nsw.gov.au/ocsvc/Public/InMyNeighbourhood/WasteServices?GeoLocationId={}\",\n}\n\nHEADERS = {\"user-agent\": \"Mozilla/5.0\"}\n\nICON_MAP = {\n    \"General Waste\": \"trash-can\",\n    \"Recycling\": \"mdi:recycle\",\n    \"Green Waste\": \"mdi:leaf\",\n}\n\n\nclass Source:\n    def __init__(\n        self, post_code: str, suburb: str, street_name: str, street_number: str\n    ):\n        self.post_code = post_code\n        self.suburb = suburb\n        self.street_name = street_name\n        self.street_number = street_number\n\n    def fetch(self):\n        locationId = 0\n\n        address = \"{} {} {} NSW {}\".format(\n            self.street_number, self.street_name, self.suburb, self.post_code\n        )\n\n        q = requote_uri(str(API_URLS[\"address_search\"]).format(address))\n\n        # Retrieve suburbs\n        r = requests.get(q, headers=HEADERS)\n\n        data = json.loads(r.text)\n\n        # Find the ID for our suburb\n        for item in data[\"locations\"]:\n            locationId = item[\"Id\"]\n            break\n\n        if locationId == 0:\n            return []\n\n        # Retrieve the upcoming collections for our property\n        q = requote_uri(str(API_URLS[\"collection\"]).format(locationId))\n\n        r = requests.get(q, headers=HEADERS)\n\n        data = json.loads(r.text)\n\n        responseContent = data[\"responseContent\"]\n\n        soup = BeautifulSoup(responseContent, \"html.parser\")\n        services = soup.find_all(\"div\", attrs={\"class\": \"service-details\"})\n\n        entries = []\n\n        for item in services:\n            # test if <div> contains a valid date. If not, is is not a collection item.\n            date_text = item.find(\"span\")\n            try:\n                date = datetime.datetime.strptime(date_text.text, \"%A%d %b %Y\").date()\n\n            except ValueError:\n                continue\n\n            waste_type = item.contents[0].strip()\n\n            entries.append(\n                Collection(\n                    date=date,\n                    t=waste_type,\n                    icon=ICON_MAP.get(waste_type, \"mdi:trash-can\"),\n                )\n            )\n\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py"}], "after_files": [{"content": "import datetime\nimport json\n\nimport requests\nfrom bs4 import BeautifulSoup\nfrom requests.utils import requote_uri\nfrom waste_collection_schedule import Collection\n\nTITLE = \"Campbelltown City Council\"\nDESCRIPTION = \"Source for Campbelltown City Council rubbish collection.\"\nURL = \"https://www.campbelltown.nsw.gov.au/\"\nTEST_CASES = {\n    \"Minto Mall\": {\n        \"post_code\": \"2566\",\n        \"suburb\": \"Minto\",\n        \"street_name\": \"Brookfield Road\",\n        \"street_number\": \"10\",\n    },\n    \"Campbelltown Catholic Club\": {\n        \"post_code\": \"2560\",\n        \"suburb\": \"Campbelltown\",\n        \"street_name\": \"Camden Road\",\n        \"street_number\": \"20-22\",\n    },\n    \"Australia Post Ingleburn\": {\n        \"post_code\": \"2565\",\n        \"suburb\": \"INGLEBURN\",\n        \"street_name\": \"Oxford Road\",\n        \"street_number\": \"34\",\n    },\n}\n\nAPI_URLS = {\n    \"address_search\": \"https://www.campbelltown.nsw.gov.au/api/v1/myarea/search?keywords={}\",\n    \"collection\": \"https://www.campbelltown.nsw.gov.au/ocapi/Public/myarea/wasteservices?geolocationid={}&ocsvclang=en-AU\",\n}\n\nHEADERS = {\"user-agent\": \"Mozilla/5.0\"}\n\nICON_MAP = {\n    \"General Waste\": \"trash-can\",\n    \"Recycling\": \"mdi:recycle\",\n    \"Green Waste\": \"mdi:leaf\",\n}\n\nclass Source:\n    def __init__(\n        self, post_code: str, suburb: str, street_name: str, street_number: str\n    ):\n        self.post_code = post_code\n        self.suburb = suburb\n        self.street_name = street_name\n        self.street_number = street_number\n\n    def fetch(self):\n        locationId = 0\n\n        address = \"{} {} {} NSW {}\".format(\n            self.street_number, self.street_name, self.suburb, self.post_code\n        )\n\n        q = requote_uri(str(API_URLS[\"address_search\"]).format(address))\n\n        # Retrieve suburbs\n        r = requests.get(q, headers=HEADERS)\n\n        data = json.loads(r.text)\n\n        # Find the ID for our suburb\n        for item in data[\"Items\"]:\n            locationId = item[\"Id\"]\n            break\n\n        if locationId == 0:\n            return []\n\n        # Retrieve the upcoming collections for our property\n        q = requote_uri(str(API_URLS[\"collection\"]).format(locationId))\n\n        r = requests.get(q, headers=HEADERS)\n\n        data = json.loads(r.text)\n\n        responseContent = data[\"responseContent\"]\n\n        soup = BeautifulSoup(responseContent, \"html.parser\")\n        services = soup.find_all(\"div\", attrs={\"class\": \"waste-services-result\"})\n\n        entries = []\n\n        for item in services:\n            # test if <div> contains a valid date. If not, is is not a collection item.\n            date_text = item.find(\"div\", attrs={\"class\": \"next-service\"})\n            \n            # The date format currently used on https://www.campbelltown.nsw.gov.au/Services-and-Facilities/Waste-and-Recycling/Check-my-collection-day\n            date_format = '%a %d/%m/%Y'\n\n            try:\n                # Strip carriage returns and newlines out of the HTML content\n                cleaned_date_text = date_text.text.replace('\\r','').replace('\\n','').strip()\n\n                # Parse the date\n                date = datetime.datetime.strptime(cleaned_date_text, date_format).date()\n\n            except ValueError:\n                continue\n\n            waste_type = item.find(\"h3\").text.strip()\n\n            entries.append(\n                Collection(\n                    date=date,\n                    t=waste_type,\n                    icon=ICON_MAP.get(waste_type, \"mdi:trash-can\"),\n                )\n            )\n\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/campbelltown_nsw_gov_au.py"}]}