Add support for Birmingham City Council (UK), birmingham.gov.uk (#2049)

* Add support for Birmingham City Council (UK), birmingham.gov.uk

* Update code logic of `birmingham_gov_uk` to reduce indentation

* Update `birmingham_gov_uk` test cases to demonstrate integer UPRN's

* Be more resilient to unknown collection types, and still return them, just with an "question mark" icon

* reformatting

---------

Co-authored-by: 5ila5 <5ila5@users.noreply.github.com>
This commit is contained in:
Danny Allen
2024-05-08 21:23:27 +01:00
committed by GitHub
parent cddfda6add
commit 662005ded0
4 changed files with 150 additions and 1 deletions

View File

@@ -1203,6 +1203,7 @@ Waste collection schedules in the following formats and countries are supported.
- [BCP Council](/doc/source/bcp_gov_uk.md) / bcpcouncil.gov.uk
- [Bedford Borough Council](/doc/source/bedford_gov_uk.md) / bedford.gov.uk
- [Binzone](/doc/source/binzone_uk.md) / southoxon.gov.uk
- [Birmingham City Council](/doc/source/birmingham_gov_uk.md) / birmingham.gov.uk
- [Blackburn with Darwen Borough Council](/doc/source/blackburn_gov_uk.md) / blackburn.gov.uk
- [Blackpool Council](/doc/source/blackpool_gov_uk.md) / blackpool.gov.uk
- [Borough Council of King's Lynn & West Norfolk](/doc/source/west_norfolk_gov_uk.md) / west-norfolk.gov.uk

View File

@@ -0,0 +1,97 @@
import re
from datetime import datetime
import requests
from bs4 import BeautifulSoup
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
from waste_collection_schedule import Collection # type: ignore[attr-defined]
TITLE = "Birmingham City Council"
DESCRIPTION = "Source for birmingham.gov.uk services for Birmingham, UK."
URL = "https://birmingham.gov.uk"
TEST_CASES = {
"Cherry Tree Croft": {"uprn": 100070321799, "postcode": "B27 6TF"},
"Ludgate Loft Apartments": {"uprn": 10033389698, "postcode": "B3 1DW"},
"Windermere Road": {"uprn": "100070566109", "postcode": "B13 9JP"},
"Park Hill": {"uprn": "100070475114", "postcode": "B13 8DS"},
}
HEADERS = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
}
API_URLS = {
"get_session": "https://www.birmingham.gov.uk/xfp/form/619",
"collection": "https://www.birmingham.gov.uk/xfp/form/619",
}
ICON_MAP = {
"Household Collection": "mdi:trash-can",
"Recycling Collection": "mdi:recycle",
"Green Recycling Chargeable Collections": "mdi:leaf",
}
class Source:
def __init__(self, uprn: str, postcode: str):
self._uprn = uprn
self._postcode = postcode
def fetch(self):
entries: list[Collection] = []
session = requests.Session()
session.headers.update(HEADERS)
token_response = session.get(API_URLS["get_session"])
soup = BeautifulSoup(token_response.text, "html.parser")
token = soup.find("input", {"name": "__token"}).attrs["value"]
if not token:
raise ValueError(
"Could not parse CSRF Token from initial response. Won't be able to proceed."
)
form_data = {
"__token": token,
"page": "491",
"locale": "en_GB",
"q1f8ccce1d1e2f58649b4069712be6879a839233f_0_0": self._postcode,
"q1f8ccce1d1e2f58649b4069712be6879a839233f_1_0": self._uprn,
"next": "Next",
}
collection_response = session.post(API_URLS["collection"], data=form_data)
collection_soup = BeautifulSoup(collection_response.text, "html.parser")
for table_row in collection_soup.find(
"table", class_="data-table"
).tbody.find_all("tr"):
collection_type = table_row.contents[0].text
collection_next = table_row.contents[1].text
collection_date = re.findall(r"\(.*?\)", collection_next)
if len(collection_date) != 1:
continue
collection_date_obj = parse(re.sub("[()]", "", collection_date[0])).date()
# since we only have the next collection day, if the parsed date is in the past,
# assume the day is instead next month
if collection_date_obj < datetime.now().date():
collection_date_obj += relativedelta(months=1)
entries.append(
Collection(
date=collection_date_obj,
t=collection_type,
icon=ICON_MAP.get(collection_type, "mdi:help"),
)
)
if not entries:
raise ValueError(
"Could not get collections for the given combination of UPRN and Postcode."
)
return entries

View File

@@ -0,0 +1,51 @@
# Birmingham City Council
Support for schedules provided by [Birmingham City Council](https://www.birmingham.gov.uk/), in the UK.
## Configuration via configuration.yaml
```yaml
waste_collection_schedule:
sources:
- name: birmingham_gov_uk
args:
uprn: UNIQUE_PROPERTY_REFERENCE_NUMBER
postcode: POSTCODE
```
### Configuration Variables
**uprn**<br>
*(string)*
The "Unique Property Reference Number" for your address. You can find it by searching for your address at https://www.findmyaddress.co.uk/.
**postcode**<br>
*(string)*
The Post Code for your address. This needs to match the postcode corresponding to your UPRN.
## Example
```yaml
waste_collection_schedule:
sources:
- name: birmingham_gov_uk
args:
uprn: 100070321799
postcode: B27 6TF
```
## Returned Collections
This source will return the next collection date for each container type.
## Returned collection types
### Household Collection
Grey lid rubbish bin is for general waste.
### Recycling Collection
Green lid recycling bin is for dry recycling (metals, glass and plastics).
Blue lid recycling bin is for paper and card.
### Green Recycling Chargeable Collections
Green Recycling (Chargeable Collections).

File diff suppressed because one or more lines are too long