Skip to content

Commit

Permalink
Merge pull request #964 from m26dvd/master
Browse files Browse the repository at this point in the history
feat: Council Pack 13
  • Loading branch information
robbrad authored Nov 6, 2024
2 parents e14bef9 + 79a04cf commit cd4ae1e
Show file tree
Hide file tree
Showing 6 changed files with 294 additions and 4 deletions.
24 changes: 23 additions & 1 deletion uk_bin_collection/tests/input.json
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@
"wiki_command_url_override": "https://lincoln.gov.uk",
"uprn": "000235024846",
"postcode": "LN5 7SH",
"wiki_name": "Tunbridge Wells Council",
"wiki_name": "Lincoln Council",
"wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
},
"LisburnCastlereaghCityCouncil": {
Expand Down Expand Up @@ -794,6 +794,13 @@
"wiki_name": "London Borough Redbridge",
"wiki_note": "Follow the instructions [here](https://my.redbridge.gov.uk/RecycleRefuse) until you get the page listing your \"Address\" then copy the entire address text and use that in the house number field."
},
"LondonBoroughSutton": {
"url": "https://waste-services.sutton.gov.uk/waste",
"wiki_command_url_override": "https://waste-services.sutton.gov.uk/waste",
"uprn": "4473006",
"wiki_name": "London Borough Sutton",
"wiki_note": "You will need to find your unique property reference by going to (https://waste-services.sutton.gov.uk/waste), entering your details and then using the 7 digit reference in the URL as your UPRN"
},
"LutonBoroughCouncil": {
"url": "https://myforms.luton.gov.uk",
"wiki_command_url_override": "https://myforms.luton.gov.uk",
Expand Down Expand Up @@ -839,6 +846,13 @@
"wiki_name": "Mid and East Antrim Borough Council",
"wiki_note": "Pass the house name/number plus the name of the street with the postcode parameter, wrapped in double quotes. Check the address in the web site first. This version will only pick the first SHOW button returned by the search or if it is fully unique. The search is not very predictable (e.g. house number 4 returns 14,24,4,44 etc.)."
},
"MidDevonCouncil": {
"url": "https://www.middevon.gov.uk",
"wiki_command_url_override": "https://www.middevon.gov.uk",
"uprn": "200003997770",
"wiki_name": "Mid Devon Council",
"wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
},
"MidlothianCouncil": {
"house_number": "52",
"postcode": "EH19 2EB",
Expand Down Expand Up @@ -1021,6 +1035,14 @@
"wiki_name": "Oldham Council",
"wiki_note": "Replace UPRN in URL with your own UPRN."
},
"OxfordCityCouncil": {
"url": "https://www.oxford.gov.uk",
"wiki_command_url_override": "https://www.oxford.gov.uk",
"uprn": "100120820551",
"postcode": "OX3 7QF",
"wiki_name": "Oxford City Council",
"wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
},
"PerthAndKinrossCouncil": {
"url": "https://www.pkc.gov.uk",
"wiki_command_url_override": "https://www.pkc.gov.uk",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def parse_data(self, page: str, **kwargs) -> dict:
for icon in icons:
cal_item = icon.find_parent().find_parent()
bin_date = datetime.strptime(
cal_item["title"],
cal_item["title"].replace("today is ", ""),
"%A, %d %B %Y",
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from time import sleep

import requests
from bs4 import BeautifulSoup

from uk_bin_collection.uk_bin_collection.common import *
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass


# import the wonderful Beautiful Soup and the URL grabber
class CouncilClass(AbstractGetBinDataClass):
"""
Concrete classes have to implement all abstract operations of the
base class. They can also override some operations with a default
implementation.
"""

def parse_data(self, page: str, **kwargs) -> dict:

user_uprn = kwargs.get("uprn")
# check_uprn(user_uprn)
bindata = {"bins": []}

URI = f"https://waste-services.sutton.gov.uk/waste/{user_uprn}"

s = requests.Session()

r = s.get(URI)
while "Loading your bin days..." in r.text:
sleep(2)
r = s.get(URI)
r.raise_for_status()

soup = BeautifulSoup(r.content, "html.parser")

current_year = datetime.now().year
next_year = current_year + 1

services = soup.find_all("h3", class_="govuk-heading-m waste-service-name")

for service in services:
bin_type = service.get_text(
strip=True
) # Bin type name (e.g., 'Food waste', 'Mixed recycling')
if bin_type == "Bulky waste":
continue
service_details = service.find_next("div", class_="govuk-grid-row")

next_collection = (
service_details.find("dt", string="Next collection")
.find_next_sibling("dd")
.get_text(strip=True)
)

next_collection = datetime.strptime(
remove_ordinal_indicator_from_date_string(next_collection),
"%A, %d %B",
)

if next_collection.month == 1:
next_collection = next_collection.replace(year=next_year)
else:
next_collection = next_collection.replace(year=current_year)

dict_data = {
"type": bin_type,
"collectionDate": next_collection.strftime("%d/%m/%Y"),
}
bindata["bins"].append(dict_data)

bindata["bins"].sort(
key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
)

return bindata
93 changes: 93 additions & 0 deletions uk_bin_collection/uk_bin_collection/councils/MidDevonCouncil.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import time

import requests

from uk_bin_collection.uk_bin_collection.common import *
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass


# import the wonderful Beautiful Soup and the URL grabber
class CouncilClass(AbstractGetBinDataClass):
"""
Concrete classes have to implement all abstract operations of the
base class. They can also override some operations with a default
implementation.
"""

def parse_data(self, page: str, **kwargs) -> dict:

user_uprn = kwargs.get("uprn")
check_uprn(user_uprn)
bindata = {"bins": []}

SESSION_URL = "https://my.middevon.gov.uk/authapi/isauthenticated?uri=https%253A%252F%252Fmy.middevon.gov.uk%252Fen%252FAchieveForms%252F%253Fform_uri%253Dsandbox-publish%253A%252F%252FAF-Process-2289dd06-9a12-4202-ba09-857fe756f6bd%252FAF-Stage-eb382015-001c-415d-beda-84f796dbb167%252Fdefinition.json%2526redirectlink%253D%25252Fen%2526cancelRedirectLink%253D%25252Fen%2526consentMessage%253Dyes&hostname=my.middevon.gov.uk&withCredentials=true"

API_URL = "https://my.middevon.gov.uk/apibroker/runLookup"

payload = {
"formValues": {
"Your Address": {
"listAddress": {"value": user_uprn},
},
},
}

headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"User-Agent": "Mozilla/5.0",
"X-Requested-With": "XMLHttpRequest",
"Referer": "https://my.middevon.gov.uk/fillform/?iframe_id=fillform-frame-1&db_id=",
}

ids = [
"6423144f50ec0",
"641c7ae9b4c96",
"645e13a01dba1",
"642315aacb919",
"64231699483cf",
"642421bab7478",
"6424229605d13",
"645e14020c9cc",
]

rows_data = []

for id in ids:
s = requests.session()
r = s.get(SESSION_URL)
r.raise_for_status()
session_data = r.json()
sid = session_data["auth-session"]

params = {
"id": id,
"repeat_against": "",
"noRetry": "false",
"getOnlyTokens": "undefined",
"log_id": "",
"app_name": "AF-Renderer::Self",
# unix_timestamp
"_": str(int(time.time() * 1000)),
"sid": sid,
}
r = s.post(API_URL, json=payload, headers=headers, params=params)
r.raise_for_status()
data = r.json()
rows_data = data["integration"]["transformed"]["rows_data"]
if isinstance(rows_data, dict):
date = datetime.strptime(rows_data["0"]["display"], "%d-%b-%y")
bin_types = (rows_data["0"]["CollectionItems"]).split(" and ")

for bin_type in bin_types:
dict_data = {
"type": bin_type,
"collectionDate": date.strftime(date_format),
}
bindata["bins"].append(dict_data)

bindata["bins"].sort(
key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
)

return bindata
63 changes: 63 additions & 0 deletions uk_bin_collection/uk_bin_collection/councils/OxfordCityCouncil.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import requests
from bs4 import BeautifulSoup

from uk_bin_collection.uk_bin_collection.common import *
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass


# import the wonderful Beautiful Soup and the URL grabber
class CouncilClass(AbstractGetBinDataClass):
"""
Concrete classes have to implement all abstract operations of the
base class. They can also override some operations with a default
implementation.
"""

def parse_data(self, page: str, **kwargs) -> dict:

user_uprn = kwargs.get("uprn")
user_postcode = kwargs.get("postcode")
check_uprn(user_uprn)
check_postcode(user_postcode)
bindata = {"bins": []}

session_uri = "https://www.oxford.gov.uk/mybinday"
URI = "https://www.oxford.gov.uk/xfp/form/142"

session = requests.Session()
token_response = session.get(session_uri)
soup = BeautifulSoup(token_response.text, "html.parser")
token = soup.find("input", {"name": "__token"}).attrs["value"]

form_data = {
"__token": token,
"page": "12",
"locale": "en_GB",
"q6ad4e3bf432c83230a0347a6eea6c805c672efeb_0_0": user_postcode,
"q6ad4e3bf432c83230a0347a6eea6c805c672efeb_1_0": user_uprn,
"next": "Next",
}

collection_response = session.post(URI, data=form_data)

collection_soup = BeautifulSoup(collection_response.text, "html.parser")
for paragraph in collection_soup.find("div", class_="editor").find_all("p"):
matches = re.match(r"^(\w+) Next Collection: (.*)", paragraph.text)
if matches:
collection_type, date_string = matches.groups()
try:
date = datetime.strptime(date_string, "%A %d %B %Y").date()
except ValueError:
date = datetime.strptime(date_string, "%A %d %b %Y").date()

dict_data = {
"type": collection_type,
"collectionDate": date.strftime("%d/%m/%Y"),
}
bindata["bins"].append(dict_data)

bindata["bins"].sort(
key=lambda x: datetime.strptime(x.get("collectionDate"), "%d/%m/%Y")
)

return bindata
41 changes: 39 additions & 2 deletions wiki/Councils.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,21 +111,23 @@ This document is still a work in progress, don't worry if your council isn't lis
- [Lancaster City Council](#lancaster-city-council)
- [Leeds City Council](#leeds-city-council)
- [Lichfield District Council](#lichfield-district-council)
- [Tunbridge Wells Council](#tunbridge-wells-council)
- [Lincoln Council](#lincoln-council)
- [Lisburn and Castlereagh City Council](#lisburn-and-castlereagh-city-council)
- [Liverpool City Council](#liverpool-city-council)
- [London Borough Ealing](#london-borough-ealing)
- [London Borough Harrow](#london-borough-harrow)
- [London Borough Hounslow](#london-borough-hounslow)
- [London Borough Lambeth](#london-borough-lambeth)
- [London Borough Redbridge](#london-borough-redbridge)
- [London Borough Sutton](#london-borough-sutton)
- [Luton Borough Council](#luton-borough-council)
- [Maldon District Council](#maldon-district-council)
- [Malvern Hills District Council](#malvern-hills-district-council)
- [Manchester City Council](#manchester-city-council)
- [Mansfield District Council](#mansfield-district-council)
- [Merton Council](#merton-council)
- [Mid and East Antrim Borough Council](#mid-and-east-antrim-borough-council)
- [Mid Devon Council](#mid-devon-council)
- [Midlothian Council](#midlothian-council)
- [Mid Sussex District Council](#mid-sussex-district-council)
- [Milton Keynes City Council](#milton-keynes-city-council)
Expand All @@ -152,6 +154,7 @@ This document is still a work in progress, don't worry if your council isn't lis
- [Northumberland Council](#northumberland-council)
- [Nottingham City Council](#nottingham-city-council)
- [Oldham Council](#oldham-council)
- [Oxford City Council](#oxford-city-council)
- [Perth and Kinross Council](#perth-and-kinross-council)
- [Plymouth Council](#plymouth-council)
- [Portsmouth City Council](#portsmouth-city-council)
Expand Down Expand Up @@ -1411,7 +1414,7 @@ Note: You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/searc

---

### Tunbridge Wells Council
### Lincoln Council
```commandline
python collect_data.py LincolnCouncil https://lincoln.gov.uk -u XXXXXXXX -p "XXXX XXX"
```
Expand Down Expand Up @@ -1497,6 +1500,17 @@ Note: Follow the instructions [here](https://my.redbridge.gov.uk/RecycleRefuse)

---

### London Borough Sutton
```commandline
python collect_data.py LondonBoroughSutton https://waste-services.sutton.gov.uk/waste -u XXXXXXXX
```
Additional parameters:
- `-u` - UPRN

Note: You will need to find your unique property reference by going to (https://waste-services.sutton.gov.uk/waste), entering your details and then using the 7 digit reference in the URL as your UPRN

---

### Luton Borough Council
```commandline
python collect_data.py LutonBoroughCouncil https://myforms.luton.gov.uk -u XXXXXXXX
Expand Down Expand Up @@ -1570,6 +1584,17 @@ Note: Pass the house name/number plus the name of the street with the postcode p

---

### Mid Devon Council
```commandline
python collect_data.py MidDevonCouncil https://www.middevon.gov.uk -u XXXXXXXX
```
Additional parameters:
- `-u` - UPRN

Note: You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN.

---

### Midlothian Council
```commandline
python collect_data.py MidlothianCouncil https://www.midlothian.gov.uk/info/1054/bins_and_recycling/343/bin_collection_days -s -p "XXXX XXX" -n XX
Expand Down Expand Up @@ -1857,6 +1882,18 @@ Note: Replace UPRN in URL with your own UPRN.

---

### Oxford City Council
```commandline
python collect_data.py OxfordCityCouncil https://www.oxford.gov.uk -u XXXXXXXX -p "XXXX XXX"
```
Additional parameters:
- `-u` - UPRN
- `-p` - postcode

Note: You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN.

---

### Perth and Kinross Council
```commandline
python collect_data.py PerthAndKinrossCouncil https://www.pkc.gov.uk -u XXXXXXXX
Expand Down

0 comments on commit cd4ae1e

Please sign in to comment.