We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Bug]: Typo in icon specification: "varient" should be "variant"
### I Have A Problem With:

The integration in general

### What's Your Problem

There is no Material Design Icon with the spelling "varient", it should be "variant".

In the following files:
* `custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py`
* `custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py`

![image](https://github.com/mampfes/hacs_waste_collection_schedule/assets/394687/8290ce4d-3014-4d0e-a75f-1406030fb20d)


### Source (if relevant)

_No response_

### Logs

_No response_

### Relevant Configuration

_No response_

### Checklist Source Error

- [ ] Use the example parameters for your source (often available in the documentation) (don't forget to restart Home Assistant after changing the configuration)
- [ ] Checked that the website of your service provider is still working
- [ ] Tested my attributes on the service provider website (if possible)
- [X] I have tested with the latest version of the integration (master) (for HACS in the 3 dot menu of the integration click on "Redownload" and choose master as version)

### Checklist Sensor Error

- [ ] Checked in the Home Assistant Calendar tab if the event names match the types names (if types argument is used)

### Required

- [X] I have searched past (closed AND opened) issues to see if this bug has already been reported, and it hasn't been.
- [X] I understand that people give their precious time for free, and thus I've done my very best to make this problem as easy as possible to investigate.

--- 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/basildon_gov_uk.py`
Content:
```
1 # Credit where it's due:
2 # This is predominantly a refactoring of the Bristol City Council script from the UKBinCollectionData repo
3 # https://github.com/robbrad/UKBinCollectionData
4 
5 from datetime import datetime
6 
7 import requests
8 from waste_collection_schedule import Collection  # type: ignore[attr-defined]
9 
10 TITLE = "Basildon Council"
11 DESCRIPTION = "Source for basildon.gov.uk services for Basildon Council, UK."
12 URL = "https://basildon.gov.uk"
13 
14 TEST_CASES = {
15     "Test_Addres_001": {"postcode": "CM111BJ", "address": "6, HEADLEY ROAD"},
16     "Test_Addres_002": {"postcode": "SS14 1QU", "address": "25 LONG RIDING"},
17     "Test_UPRN_001": {"uprn": "100090277795"},
18     "Test_UPRN_002": {"uprn": 10024197625},
19     "Test_UPRN_003": {"uprn": "10090455610"},
20 }
21 ICON_MAP = {
22     "green_waste": "mdi:leaf",
23     "general_waste": "mdi:trash-can",
24     "food_waste": "mdi:food",
25     "glass_waste": "mdi:bottle-wine",
26     "papercard_waste": "mdi:package-varient",
27     "plasticcans_waste": "mdi:bottle-soda-classic",
28 }
29 NAME_MAP = {
30     "green_waste": "Garden",
31     "general_waste": "General",
32     "food_waste": "Food",
33     "glass_waste": "Glass",
34     "papercard_waste": "Paper/Cardboard",
35     "plasticcans_waste": "Plastic/Cans",
36 }
37 HEADERS = {
38     "Accept": "*/*",
39     "Accept-Language": "en-GB,en;q=0.9",
40     "Connection": "keep-alive",
41     "Ocp-Apim-Trace": "true",
42     "Origin": "https://mybasildon.powerappsportals.com",
43     "Referer": "https://mybasildon.powerappsportals.com/",
44     "Sec-Fetch-Dest": "empty",
45     "Sec-Fetch-Mode": "cors",
46     "Sec-Fetch-Site": "cross-site",
47     "Sec-GPC": "1",
48     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
49 }
50 
51 
52 class Source:
53     def __init__(self, postcode=None, address=None, uprn=None):
54         if uprn is None and (postcode is None or address is None):
55             raise ValueError("Either uprn or postcode and address must be provided")
56 
57         self._uprn = str(uprn).zfill(12) if uprn is not None else None
58         self._postcode = postcode
59         self._address = address
60 
61     def compare_address(self, address) -> bool:
62         return (
63             self._address.replace(",", "").replace(" ", "").upper()
64             == address.replace(",", "").replace(" ", "").upper()
65         )
66 
67     def get_uprn(self, s):
68         r = s.post(
69             "https://basildonportal.azurewebsites.net/api/listPropertiesByPostcode",
70             headers=HEADERS,
71             json={"postcode": self._postcode},
72         )
73         r.raise_for_status()
74         data = r.json()
75         if data["result"] != "success":
76             raise ValueError("Invalid postcode")
77         for item in data["properties"]:
78             if self.compare_address(item["line1"]):
79                 self._uprn = item["uprn"]
80                 break
81         if self._uprn is None:
82             raise ValueError("Invalid address")
83 
84     def fetch(self):
85         s = requests.Session()
86         if self._uprn is None:
87             self.get_uprn(s)
88 
89         # Retrieve the schedule
90         payload = {"uprn": self._uprn}
91         response = s.post(
92             "https://basildonportal.azurewebsites.net/api/getPropertyRefuseInformation",
93             headers=HEADERS,
94             json=payload,
95         )
96         data = response.json()["refuse"]["available_services"]
97         entries = []
98         for item in ICON_MAP:
99             for collection_date_key in [
100                 "current_collection_",
101                 "next_collection_",
102                 "last_collection_",
103             ]:
104                 if data[item][collection_date_key + "active"]:
105                     date_string = data[item][collection_date_key + "date"]
106                     entries.append(
107                         Collection(
108                             date=datetime.strptime(
109                                 date_string,
110                                 "%Y-%m-%d",
111                             ).date(),
112                             t=NAME_MAP[item],
113                             icon=ICON_MAP.get(item),
114                         )
115                     )
116 
117         return entries
118
```

Path: `custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py`
Content:
```
1 # Credit where it's due:
2 # This is predominantly a refactoring of the Bristol City Council script from the UKBinCollectionData repo
3 # https://github.com/robbrad/UKBinCollectionData
4 
5 from datetime import datetime
6 
7 import requests
8 from waste_collection_schedule import Collection  # type: ignore[attr-defined]
9 
10 TITLE = "Bristol City Council"
11 DESCRIPTION = "Source for bristol.gov.uk services for Bristol City Council, UK."
12 URL = "https://bristol.gov.uk"
13 
14 TEST_CASES = {
15     "Test_001": {"uprn": "107652"},
16     "Test_002": {"uprn": "2987"},
17     "Test_003": {"uprn": 17929},
18 }
19 ICON_MAP = {
20     "90L BLUE SACK": "mdi:recycle",
21     "240L GARDEN WASTE BIN": "mdi:leaf",
22     "180L GENERAL WASTE": "mdi:trash-can",
23     "45L BLACK RECYCLING BOX": "mdi:recycle",
24     "23L FOOD WASTE BIN": "mdi:food",
25     "55L GREEN RECYCLING BOX": "mdi:recycle",
26     "140L FOOD WASTE BIN": "mdi:food",
27     "240L RECYCLING MIXED GLASS": "mdi:bottle-wine",
28     "240L RECYCLING PAPER": "mdi:newspaper",
29     "1100L GENERAL WASTE": "mdi:trash-can",
30     "1100L RECYCLING CARD": "mdi:package-varient",
31     "360L RECYCLING PLASTIC/CANS": "mdi:bottle-soda-classic",
32 }
33 HEADERS = {
34     "Accept": "*/*",
35     "Accept-Language": "en-GB,en;q=0.9",
36     "Connection": "keep-alive",
37     "Ocp-Apim-Subscription-Key": "47ffd667d69c4a858f92fc38dc24b150",
38     "Ocp-Apim-Trace": "true",
39     "Origin": "https://bristolcouncil.powerappsportals.com",
40     "Referer": "https://bristolcouncil.powerappsportals.com/",
41     "Sec-Fetch-Dest": "empty",
42     "Sec-Fetch-Mode": "cors",
43     "Sec-Fetch-Site": "cross-site",
44     "Sec-GPC": "1",
45     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
46 }
47 
48 
49 class Source:
50     def __init__(self, uprn):
51         self._uprn = str(uprn).zfill(12)
52 
53     def fetch(self):
54         s = requests.Session()
55 
56         # Initialise form
57         payload = {"servicetypeid": "7dce896c-b3ba-ea11-a812-000d3a7f1cdc"}
58         response = s.get(
59             "https://bristolcouncil.powerappsportals.com/completedynamicformunauth/",
60             headers=HEADERS,
61             params=payload,
62         )
63 
64         # Set the search criteria
65         payload = {"Uprn": "UPRN" + self._uprn}
66         response = s.post(
67             "https://bcprdapidyna002.azure-api.net/bcprdfundyna001-llpg/DetailedLLPG",
68             headers=HEADERS,
69             json=payload,
70         )
71 
72         # Retrieve the schedule
73         payload = {"uprn": self._uprn}
74         response = s.post(
75             "https://bcprdapidyna002.azure-api.net/bcprdfundyna001-alloy/NextCollectionDates",
76             headers=HEADERS,
77             json=payload,
78         )
79         data = response.json()["data"]
80 
81         entries = []
82         for item in data:
83             for collection in item["collection"]:
84                 for collection_date_key in ["nextCollectionDate", "lastCollectionDate"]:
85                     date_string = collection[collection_date_key].split("T")[0]
86                     entries.append(
87                         Collection(
88                             date=datetime.strptime(
89                                 date_string,
90                                 "%Y-%m-%d",
91                             ).date(),
92                             t=item["containerName"],
93                             icon=ICON_MAP.get(item["containerName"].upper()),
94                         )
95                     )
96 
97         return entries
98
```
--- 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/basildon_gov_uk.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py
--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py
+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py
@@ -23,7 +23,7 @@
     "general_waste": "mdi:trash-can",
     "food_waste": "mdi:food",
     "glass_waste": "mdi:bottle-wine",
-    "papercard_waste": "mdi:package-varient",
+    "papercard_waste": "mdi:package-variant",
     "plasticcans_waste": "mdi:bottle-soda-classic",
 }
 NAME_MAP = {
diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py
--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py
+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py
@@ -27,7 +27,7 @@
     "240L RECYCLING MIXED GLASS": "mdi:bottle-wine",
     "240L RECYCLING PAPER": "mdi:newspaper",
     "1100L GENERAL WASTE": "mdi:trash-can",
-    "1100L RECYCLING CARD": "mdi:package-varient",
+    "1100L RECYCLING CARD": "mdi:package-variant",
     "360L RECYCLING PLASTIC/CANS": "mdi:bottle-soda-classic",
 }
 HEADERS = {

{"golden_diff": "diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py\n--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py\n+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py\n@@ -23,7 +23,7 @@\n     \"general_waste\": \"mdi:trash-can\",\n     \"food_waste\": \"mdi:food\",\n     \"glass_waste\": \"mdi:bottle-wine\",\n-    \"papercard_waste\": \"mdi:package-varient\",\n+    \"papercard_waste\": \"mdi:package-variant\",\n     \"plasticcans_waste\": \"mdi:bottle-soda-classic\",\n }\n NAME_MAP = {\ndiff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py\n--- a/custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py\n+++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py\n@@ -27,7 +27,7 @@\n     \"240L RECYCLING MIXED GLASS\": \"mdi:bottle-wine\",\n     \"240L RECYCLING PAPER\": \"mdi:newspaper\",\n     \"1100L GENERAL WASTE\": \"mdi:trash-can\",\n-    \"1100L RECYCLING CARD\": \"mdi:package-varient\",\n+    \"1100L RECYCLING CARD\": \"mdi:package-variant\",\n     \"360L RECYCLING PLASTIC/CANS\": \"mdi:bottle-soda-classic\",\n }\n HEADERS = {\n", "issue": "[Bug]: Typo in icon specification: \"varient\" should be \"variant\"\n### I Have A Problem With:\n\nThe integration in general\n\n### What's Your Problem\n\nThere is no Material Design Icon with the spelling \"varient\", it should be \"variant\".\r\n\r\nIn the following files:\r\n* `custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py`\r\n* `custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py`\r\n\r\n![image](https://github.com/mampfes/hacs_waste_collection_schedule/assets/394687/8290ce4d-3014-4d0e-a75f-1406030fb20d)\r\n\n\n### Source (if relevant)\n\n_No response_\n\n### Logs\n\n_No response_\n\n### Relevant Configuration\n\n_No response_\n\n### Checklist Source Error\n\n- [ ] Use the example parameters for your source (often available in the documentation) (don't forget to restart Home Assistant after changing the configuration)\n- [ ] Checked that the website of your service provider is still working\n- [ ] Tested my attributes on the service provider website (if possible)\n- [X] I have tested with the latest version of the integration (master) (for HACS in the 3 dot menu of the integration click on \"Redownload\" and choose master as version)\n\n### Checklist Sensor Error\n\n- [ ] Checked in the Home Assistant Calendar tab if the event names match the types names (if types argument is used)\n\n### Required\n\n- [X] I have searched past (closed AND opened) issues to see if this bug has already been reported, and it hasn't been.\n- [X] I understand that people give their precious time for free, and thus I've done my very best to make this problem as easy as possible to investigate.\n", "before_files": [{"content": "# Credit where it's due:\n# This is predominantly a refactoring of the Bristol City Council script from the UKBinCollectionData repo\n# https://github.com/robbrad/UKBinCollectionData\n\nfrom datetime import datetime\n\nimport requests\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\n\nTITLE = \"Basildon Council\"\nDESCRIPTION = \"Source for basildon.gov.uk services for Basildon Council, UK.\"\nURL = \"https://basildon.gov.uk\"\n\nTEST_CASES = {\n    \"Test_Addres_001\": {\"postcode\": \"CM111BJ\", \"address\": \"6, HEADLEY ROAD\"},\n    \"Test_Addres_002\": {\"postcode\": \"SS14 1QU\", \"address\": \"25 LONG RIDING\"},\n    \"Test_UPRN_001\": {\"uprn\": \"100090277795\"},\n    \"Test_UPRN_002\": {\"uprn\": 10024197625},\n    \"Test_UPRN_003\": {\"uprn\": \"10090455610\"},\n}\nICON_MAP = {\n    \"green_waste\": \"mdi:leaf\",\n    \"general_waste\": \"mdi:trash-can\",\n    \"food_waste\": \"mdi:food\",\n    \"glass_waste\": \"mdi:bottle-wine\",\n    \"papercard_waste\": \"mdi:package-varient\",\n    \"plasticcans_waste\": \"mdi:bottle-soda-classic\",\n}\nNAME_MAP = {\n    \"green_waste\": \"Garden\",\n    \"general_waste\": \"General\",\n    \"food_waste\": \"Food\",\n    \"glass_waste\": \"Glass\",\n    \"papercard_waste\": \"Paper/Cardboard\",\n    \"plasticcans_waste\": \"Plastic/Cans\",\n}\nHEADERS = {\n    \"Accept\": \"*/*\",\n    \"Accept-Language\": \"en-GB,en;q=0.9\",\n    \"Connection\": \"keep-alive\",\n    \"Ocp-Apim-Trace\": \"true\",\n    \"Origin\": \"https://mybasildon.powerappsportals.com\",\n    \"Referer\": \"https://mybasildon.powerappsportals.com/\",\n    \"Sec-Fetch-Dest\": \"empty\",\n    \"Sec-Fetch-Mode\": \"cors\",\n    \"Sec-Fetch-Site\": \"cross-site\",\n    \"Sec-GPC\": \"1\",\n    \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36\",\n}\n\n\nclass Source:\n    def __init__(self, postcode=None, address=None, uprn=None):\n        if uprn is None and (postcode is None or address is None):\n            raise ValueError(\"Either uprn or postcode and address must be provided\")\n\n        self._uprn = str(uprn).zfill(12) if uprn is not None else None\n        self._postcode = postcode\n        self._address = address\n\n    def compare_address(self, address) -> bool:\n        return (\n            self._address.replace(\",\", \"\").replace(\" \", \"\").upper()\n            == address.replace(\",\", \"\").replace(\" \", \"\").upper()\n        )\n\n    def get_uprn(self, s):\n        r = s.post(\n            \"https://basildonportal.azurewebsites.net/api/listPropertiesByPostcode\",\n            headers=HEADERS,\n            json={\"postcode\": self._postcode},\n        )\n        r.raise_for_status()\n        data = r.json()\n        if data[\"result\"] != \"success\":\n            raise ValueError(\"Invalid postcode\")\n        for item in data[\"properties\"]:\n            if self.compare_address(item[\"line1\"]):\n                self._uprn = item[\"uprn\"]\n                break\n        if self._uprn is None:\n            raise ValueError(\"Invalid address\")\n\n    def fetch(self):\n        s = requests.Session()\n        if self._uprn is None:\n            self.get_uprn(s)\n\n        # Retrieve the schedule\n        payload = {\"uprn\": self._uprn}\n        response = s.post(\n            \"https://basildonportal.azurewebsites.net/api/getPropertyRefuseInformation\",\n            headers=HEADERS,\n            json=payload,\n        )\n        data = response.json()[\"refuse\"][\"available_services\"]\n        entries = []\n        for item in ICON_MAP:\n            for collection_date_key in [\n                \"current_collection_\",\n                \"next_collection_\",\n                \"last_collection_\",\n            ]:\n                if data[item][collection_date_key + \"active\"]:\n                    date_string = data[item][collection_date_key + \"date\"]\n                    entries.append(\n                        Collection(\n                            date=datetime.strptime(\n                                date_string,\n                                \"%Y-%m-%d\",\n                            ).date(),\n                            t=NAME_MAP[item],\n                            icon=ICON_MAP.get(item),\n                        )\n                    )\n\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py"}, {"content": "# Credit where it's due:\n# This is predominantly a refactoring of the Bristol City Council script from the UKBinCollectionData repo\n# https://github.com/robbrad/UKBinCollectionData\n\nfrom datetime import datetime\n\nimport requests\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\n\nTITLE = \"Bristol City Council\"\nDESCRIPTION = \"Source for bristol.gov.uk services for Bristol City Council, UK.\"\nURL = \"https://bristol.gov.uk\"\n\nTEST_CASES = {\n    \"Test_001\": {\"uprn\": \"107652\"},\n    \"Test_002\": {\"uprn\": \"2987\"},\n    \"Test_003\": {\"uprn\": 17929},\n}\nICON_MAP = {\n    \"90L BLUE SACK\": \"mdi:recycle\",\n    \"240L GARDEN WASTE BIN\": \"mdi:leaf\",\n    \"180L GENERAL WASTE\": \"mdi:trash-can\",\n    \"45L BLACK RECYCLING BOX\": \"mdi:recycle\",\n    \"23L FOOD WASTE BIN\": \"mdi:food\",\n    \"55L GREEN RECYCLING BOX\": \"mdi:recycle\",\n    \"140L FOOD WASTE BIN\": \"mdi:food\",\n    \"240L RECYCLING MIXED GLASS\": \"mdi:bottle-wine\",\n    \"240L RECYCLING PAPER\": \"mdi:newspaper\",\n    \"1100L GENERAL WASTE\": \"mdi:trash-can\",\n    \"1100L RECYCLING CARD\": \"mdi:package-varient\",\n    \"360L RECYCLING PLASTIC/CANS\": \"mdi:bottle-soda-classic\",\n}\nHEADERS = {\n    \"Accept\": \"*/*\",\n    \"Accept-Language\": \"en-GB,en;q=0.9\",\n    \"Connection\": \"keep-alive\",\n    \"Ocp-Apim-Subscription-Key\": \"47ffd667d69c4a858f92fc38dc24b150\",\n    \"Ocp-Apim-Trace\": \"true\",\n    \"Origin\": \"https://bristolcouncil.powerappsportals.com\",\n    \"Referer\": \"https://bristolcouncil.powerappsportals.com/\",\n    \"Sec-Fetch-Dest\": \"empty\",\n    \"Sec-Fetch-Mode\": \"cors\",\n    \"Sec-Fetch-Site\": \"cross-site\",\n    \"Sec-GPC\": \"1\",\n    \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36\",\n}\n\n\nclass Source:\n    def __init__(self, uprn):\n        self._uprn = str(uprn).zfill(12)\n\n    def fetch(self):\n        s = requests.Session()\n\n        # Initialise form\n        payload = {\"servicetypeid\": \"7dce896c-b3ba-ea11-a812-000d3a7f1cdc\"}\n        response = s.get(\n            \"https://bristolcouncil.powerappsportals.com/completedynamicformunauth/\",\n            headers=HEADERS,\n            params=payload,\n        )\n\n        # Set the search criteria\n        payload = {\"Uprn\": \"UPRN\" + self._uprn}\n        response = s.post(\n            \"https://bcprdapidyna002.azure-api.net/bcprdfundyna001-llpg/DetailedLLPG\",\n            headers=HEADERS,\n            json=payload,\n        )\n\n        # Retrieve the schedule\n        payload = {\"uprn\": self._uprn}\n        response = s.post(\n            \"https://bcprdapidyna002.azure-api.net/bcprdfundyna001-alloy/NextCollectionDates\",\n            headers=HEADERS,\n            json=payload,\n        )\n        data = response.json()[\"data\"]\n\n        entries = []\n        for item in data:\n            for collection in item[\"collection\"]:\n                for collection_date_key in [\"nextCollectionDate\", \"lastCollectionDate\"]:\n                    date_string = collection[collection_date_key].split(\"T\")[0]\n                    entries.append(\n                        Collection(\n                            date=datetime.strptime(\n                                date_string,\n                                \"%Y-%m-%d\",\n                            ).date(),\n                            t=item[\"containerName\"],\n                            icon=ICON_MAP.get(item[\"containerName\"].upper()),\n                        )\n                    )\n\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py"}], "after_files": [{"content": "# Credit where it's due:\n# This is predominantly a refactoring of the Bristol City Council script from the UKBinCollectionData repo\n# https://github.com/robbrad/UKBinCollectionData\n\nfrom datetime import datetime\n\nimport requests\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\n\nTITLE = \"Basildon Council\"\nDESCRIPTION = \"Source for basildon.gov.uk services for Basildon Council, UK.\"\nURL = \"https://basildon.gov.uk\"\n\nTEST_CASES = {\n    \"Test_Addres_001\": {\"postcode\": \"CM111BJ\", \"address\": \"6, HEADLEY ROAD\"},\n    \"Test_Addres_002\": {\"postcode\": \"SS14 1QU\", \"address\": \"25 LONG RIDING\"},\n    \"Test_UPRN_001\": {\"uprn\": \"100090277795\"},\n    \"Test_UPRN_002\": {\"uprn\": 10024197625},\n    \"Test_UPRN_003\": {\"uprn\": \"10090455610\"},\n}\nICON_MAP = {\n    \"green_waste\": \"mdi:leaf\",\n    \"general_waste\": \"mdi:trash-can\",\n    \"food_waste\": \"mdi:food\",\n    \"glass_waste\": \"mdi:bottle-wine\",\n    \"papercard_waste\": \"mdi:package-variant\",\n    \"plasticcans_waste\": \"mdi:bottle-soda-classic\",\n}\nNAME_MAP = {\n    \"green_waste\": \"Garden\",\n    \"general_waste\": \"General\",\n    \"food_waste\": \"Food\",\n    \"glass_waste\": \"Glass\",\n    \"papercard_waste\": \"Paper/Cardboard\",\n    \"plasticcans_waste\": \"Plastic/Cans\",\n}\nHEADERS = {\n    \"Accept\": \"*/*\",\n    \"Accept-Language\": \"en-GB,en;q=0.9\",\n    \"Connection\": \"keep-alive\",\n    \"Ocp-Apim-Trace\": \"true\",\n    \"Origin\": \"https://mybasildon.powerappsportals.com\",\n    \"Referer\": \"https://mybasildon.powerappsportals.com/\",\n    \"Sec-Fetch-Dest\": \"empty\",\n    \"Sec-Fetch-Mode\": \"cors\",\n    \"Sec-Fetch-Site\": \"cross-site\",\n    \"Sec-GPC\": \"1\",\n    \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36\",\n}\n\n\nclass Source:\n    def __init__(self, postcode=None, address=None, uprn=None):\n        if uprn is None and (postcode is None or address is None):\n            raise ValueError(\"Either uprn or postcode and address must be provided\")\n\n        self._uprn = str(uprn).zfill(12) if uprn is not None else None\n        self._postcode = postcode\n        self._address = address\n\n    def compare_address(self, address) -> bool:\n        return (\n            self._address.replace(\",\", \"\").replace(\" \", \"\").upper()\n            == address.replace(\",\", \"\").replace(\" \", \"\").upper()\n        )\n\n    def get_uprn(self, s):\n        r = s.post(\n            \"https://basildonportal.azurewebsites.net/api/listPropertiesByPostcode\",\n            headers=HEADERS,\n            json={\"postcode\": self._postcode},\n        )\n        r.raise_for_status()\n        data = r.json()\n        if data[\"result\"] != \"success\":\n            raise ValueError(\"Invalid postcode\")\n        for item in data[\"properties\"]:\n            if self.compare_address(item[\"line1\"]):\n                self._uprn = item[\"uprn\"]\n                break\n        if self._uprn is None:\n            raise ValueError(\"Invalid address\")\n\n    def fetch(self):\n        s = requests.Session()\n        if self._uprn is None:\n            self.get_uprn(s)\n\n        # Retrieve the schedule\n        payload = {\"uprn\": self._uprn}\n        response = s.post(\n            \"https://basildonportal.azurewebsites.net/api/getPropertyRefuseInformation\",\n            headers=HEADERS,\n            json=payload,\n        )\n        data = response.json()[\"refuse\"][\"available_services\"]\n        entries = []\n        for item in ICON_MAP:\n            for collection_date_key in [\n                \"current_collection_\",\n                \"next_collection_\",\n                \"last_collection_\",\n            ]:\n                if data[item][collection_date_key + \"active\"]:\n                    date_string = data[item][collection_date_key + \"date\"]\n                    entries.append(\n                        Collection(\n                            date=datetime.strptime(\n                                date_string,\n                                \"%Y-%m-%d\",\n                            ).date(),\n                            t=NAME_MAP[item],\n                            icon=ICON_MAP.get(item),\n                        )\n                    )\n\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/basildon_gov_uk.py"}, {"content": "# Credit where it's due:\n# This is predominantly a refactoring of the Bristol City Council script from the UKBinCollectionData repo\n# https://github.com/robbrad/UKBinCollectionData\n\nfrom datetime import datetime\n\nimport requests\nfrom waste_collection_schedule import Collection  # type: ignore[attr-defined]\n\nTITLE = \"Bristol City Council\"\nDESCRIPTION = \"Source for bristol.gov.uk services for Bristol City Council, UK.\"\nURL = \"https://bristol.gov.uk\"\n\nTEST_CASES = {\n    \"Test_001\": {\"uprn\": \"107652\"},\n    \"Test_002\": {\"uprn\": \"2987\"},\n    \"Test_003\": {\"uprn\": 17929},\n}\nICON_MAP = {\n    \"90L BLUE SACK\": \"mdi:recycle\",\n    \"240L GARDEN WASTE BIN\": \"mdi:leaf\",\n    \"180L GENERAL WASTE\": \"mdi:trash-can\",\n    \"45L BLACK RECYCLING BOX\": \"mdi:recycle\",\n    \"23L FOOD WASTE BIN\": \"mdi:food\",\n    \"55L GREEN RECYCLING BOX\": \"mdi:recycle\",\n    \"140L FOOD WASTE BIN\": \"mdi:food\",\n    \"240L RECYCLING MIXED GLASS\": \"mdi:bottle-wine\",\n    \"240L RECYCLING PAPER\": \"mdi:newspaper\",\n    \"1100L GENERAL WASTE\": \"mdi:trash-can\",\n    \"1100L RECYCLING CARD\": \"mdi:package-variant\",\n    \"360L RECYCLING PLASTIC/CANS\": \"mdi:bottle-soda-classic\",\n}\nHEADERS = {\n    \"Accept\": \"*/*\",\n    \"Accept-Language\": \"en-GB,en;q=0.9\",\n    \"Connection\": \"keep-alive\",\n    \"Ocp-Apim-Subscription-Key\": \"47ffd667d69c4a858f92fc38dc24b150\",\n    \"Ocp-Apim-Trace\": \"true\",\n    \"Origin\": \"https://bristolcouncil.powerappsportals.com\",\n    \"Referer\": \"https://bristolcouncil.powerappsportals.com/\",\n    \"Sec-Fetch-Dest\": \"empty\",\n    \"Sec-Fetch-Mode\": \"cors\",\n    \"Sec-Fetch-Site\": \"cross-site\",\n    \"Sec-GPC\": \"1\",\n    \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36\",\n}\n\n\nclass Source:\n    def __init__(self, uprn):\n        self._uprn = str(uprn).zfill(12)\n\n    def fetch(self):\n        s = requests.Session()\n\n        # Initialise form\n        payload = {\"servicetypeid\": \"7dce896c-b3ba-ea11-a812-000d3a7f1cdc\"}\n        response = s.get(\n            \"https://bristolcouncil.powerappsportals.com/completedynamicformunauth/\",\n            headers=HEADERS,\n            params=payload,\n        )\n\n        # Set the search criteria\n        payload = {\"Uprn\": \"UPRN\" + self._uprn}\n        response = s.post(\n            \"https://bcprdapidyna002.azure-api.net/bcprdfundyna001-llpg/DetailedLLPG\",\n            headers=HEADERS,\n            json=payload,\n        )\n\n        # Retrieve the schedule\n        payload = {\"uprn\": self._uprn}\n        response = s.post(\n            \"https://bcprdapidyna002.azure-api.net/bcprdfundyna001-alloy/NextCollectionDates\",\n            headers=HEADERS,\n            json=payload,\n        )\n        data = response.json()[\"data\"]\n\n        entries = []\n        for item in data:\n            for collection in item[\"collection\"]:\n                for collection_date_key in [\"nextCollectionDate\", \"lastCollectionDate\"]:\n                    date_string = collection[collection_date_key].split(\"T\")[0]\n                    entries.append(\n                        Collection(\n                            date=datetime.strptime(\n                                date_string,\n                                \"%Y-%m-%d\",\n                            ).date(),\n                            t=item[\"containerName\"],\n                            icon=ICON_MAP.get(item[\"containerName\"].upper()),\n                        )\n                    )\n\n        return entries\n", "path": "custom_components/waste_collection_schedule/waste_collection_schedule/source/bristol_gov_uk.py"}]}