Skip to content

Commit

Permalink
add Knowsley Council, UK
Browse files Browse the repository at this point in the history
  • Loading branch information
5ila5 committed Dec 28, 2024
1 parent 934e69f commit 66b9626
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2111,6 +2111,7 @@ If your service provider is not listed, feel free to open a [source request issu
- [Itouchvision Source using the encrypted API](/doc/source/iapp_itouchvision_com.md) / itouchvision.com
- [Joint Waste Solutions](/doc/source/jointwastesolutions_org.md) / jointwastesolutions.org
- [Kirklees Council](/doc/source/kirklees_gov_uk.md) / kirklees.gov.uk
- [Knowsley Council](/doc/source/knowsley_gov_uk.md) / knowsley.gov.uk
- [Lancaster City Council](/doc/source/lancaster_gov_uk.md) / lancaster.gov.uk
- [Leeds](/doc/source/apps_imactivate_com.md) / leeds.gov.uk
- [Leicester City Council](/doc/source/biffaleicester_co_uk.md) / leicester.gov.uk
Expand Down
6 changes: 6 additions & 0 deletions custom_components/waste_collection_schedule/sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -13406,6 +13406,12 @@
"default_params": {},
"id": "kirklees_gov_uk"
},
{
"title": "Knowsley Council",
"module": "knowsley_gov_uk",
"default_params": {},
"id": "knowsley_gov_uk"
},
{
"title": "Lancaster City Council",
"module": "lancaster_gov_uk",
Expand Down
25 changes: 25 additions & 0 deletions custom_components/waste_collection_schedule/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -14400,6 +14400,31 @@
"uprn": "Eine einfache Möglichkeit, Ihre Unique Property Reference Number (UPRN) zu finden, besteht darin, auf https://www.findmyaddress.co.uk/ zu gehen und Ihre Adressdaten einzugeben."
}
},
"args_knowsley_gov_uk": {
"title": "Quelle konfigurieren",
"description": "Konfiguriere deinen Service Provider. Mehr details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/knowsley_gov_uk.md",
"data": {
"calendar_title": "Kalender Titel",
"postcode": "PLZ",
"uprn": "UPRN"
},
"data_description": {
"calendar_title": "Ein lesbarerer oder benutzerfreundlicherer Name für den Müllkalender. Wenn nichts angegeben wird, wird der Name der Quelle verwendet.",
"uprn": "Eine einfache Möglichkeit, Ihre Unique Property Reference Number (UPRN) zu finden, besteht darin, auf https://www.findmyaddress.co.uk/ zu gehen und Ihre Adressdaten einzugeben."
}
},
"reconfigure_knowsley_gov_uk": {
"title": "Quelle Neu Konfigurieren",
"description": "Konfiguriere deinen Service Provider. Mehr details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/knowsley_gov_uk.md",
"data": {
"calendar_title": "Kalender Titel",
"postcode": "PLZ",
"uprn": "UPRN"
},
"data_description": {
"uprn": "Eine einfache Möglichkeit, Ihre Unique Property Reference Number (UPRN) zu finden, besteht darin, auf https://www.findmyaddress.co.uk/ zu gehen und Ihre Adressdaten einzugeben."
}
},
"args_lancaster_gov_uk": {
"title": "Quelle konfigurieren",
"description": "Konfiguriere deinen Service Provider. Mehr details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/lancaster_gov_uk.md",
Expand Down
25 changes: 25 additions & 0 deletions custom_components/waste_collection_schedule/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14421,6 +14421,31 @@
"uprn": "An easy way to discover your Unique Property Reference Number (UPRN) is by going to https://www.findmyaddress.co.uk/ and entering in your address details."
}
},
"args_knowsley_gov_uk": {
"title": "Configure Source",
"description": "Configure your service provider. More details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/knowsley_gov_uk.md.",
"data": {
"calendar_title": "Calendar Title",
"postcode": "Postcode",
"uprn": "UPRN"
},
"data_description": {
"calendar_title": "A more readable, or user-friendly, name for the waste calendar. If nothing is provided, the name returned by the source will be used.",
"uprn": "An easy way to discover your Unique Property Reference Number (UPRN) is by going to https://www.findmyaddress.co.uk/ and entering in your address details."
}
},
"reconfigure_knowsley_gov_uk": {
"title": "Reconfigure Source",
"description": "Configure your service provider. More details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/knowsley_gov_uk.md.",
"data": {
"calendar_title": "Calendar Title",
"postcode": "Postcode",
"uprn": "UPRN"
},
"data_description": {
"uprn": "An easy way to discover your Unique Property Reference Number (UPRN) is by going to https://www.findmyaddress.co.uk/ and entering in your address details."
}
},
"args_lancaster_gov_uk": {
"title": "Configure Source",
"description": "Configure your service provider. More details: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/lancaster_gov_uk.md.",
Expand Down
25 changes: 25 additions & 0 deletions custom_components/waste_collection_schedule/translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -14382,6 +14382,31 @@
"uprn": "Un modo facile per scoprire il tuo Numero di Riferimento Proprietà Unica (UPRN) è andare su https://www.findmyaddress.co.uk/ e inserire i dettagli del tuo indirizzo."
}
},
"args_knowsley_gov_uk": {
"title": "Configurazione Sorgente",
"description": "Compila i campi per ottenere le informazioni sul tuo servizio di raccolta. Maggiori informazioni: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/knowsley_gov_uk.md.",
"data": {
"calendar_title": "Nome Calendario",
"postcode": "Codice Postale CAP",
"uprn": "UPRN"
},
"data_description": {
"calendar_title": "Puoi cambiare il nome del calendario della raccolta dei rifiuti, altrimenti di default verra' utilizzato il nome del tuo fornitore di servizi.",
"uprn": "Un modo facile per scoprire il tuo Numero di Riferimento Proprietà Unica (UPRN) è andare su https://www.findmyaddress.co.uk/ e inserire i dettagli del tuo indirizzo."
}
},
"reconfigure_knowsley_gov_uk": {
"title": "Riconfigurazione Sorgente",
"description": "Compila i campi per ottenere le informazioni sul tuo servizio di raccolta. Per maggiori informazioni: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/knowsley_gov_uk.md.",
"data": {
"calendar_title": "Nome Calendario",
"postcode": "Codice Postale CAP",
"uprn": "UPRN"
},
"data_description": {
"uprn": "Un modo facile per scoprire il tuo Numero di Riferimento Proprietà Unica (UPRN) è andare su https://www.findmyaddress.co.uk/ e inserire i dettagli del tuo indirizzo."
}
},
"args_lancaster_gov_uk": {
"title": "Configurazione Sorgente",
"description": "Compila i campi per ottenere le informazioni sul tuo servizio di raccolta. Maggiori informazioni: https://github.com/mampfes/hacs_waste_collection_schedule/blob/master/doc/source/lancaster_gov_uk.md.",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
import logging
import re
import time
from datetime import datetime

import requests
from waste_collection_schedule import Collection # type: ignore[attr-defined]
from waste_collection_schedule.exceptions import SourceArgumentNotFound

TITLE = "Knowsley Council"
DESCRIPTION = "Source for Knowsley Council."
URL = "https://www.knowsley.gov.uk/"
TEST_CASES = {
"L364AR 000040082756": {"postcode": "L364AR", "uprn": "000040082756"},
"L34 0HZ, 40029195": {"postcode": "L34 0HZ", "uprn": 40029195},
}
_LOGGER = logging.getLogger(__name__)


ICON_MAP = {
"Maroon": "mdi:trash-can",
"Grey": "mdi:recycle",
"Blue": "mdi:leaf",
}

BASE_URL = "https://knowsleytransaction.mendixcloud.com/"
INIT_URL = f"{BASE_URL}link/youarebeingredirected?target=bincollectioninformation"
API_URL = f"{BASE_URL}xas/"

INIT_PAYLOAD = {
"action": "get_session_data",
"params": {
"hybrid": False,
"offline": False,
"referrer": None,
"profile": "",
"timezoneoffset": -60,
"timezoneId": "Europe/Berlin",
"preferredLanguages": ["en-US", "en"],
"version": 2,
},
}


class Source:
def __init__(self, postcode: str, uprn: str | int):
self._postcode: str = postcode
self._uprn: str | int = uprn
self._request_id = 3

def _do_request(
self,
s: requests.Session,
action: str,
x_csrf_token: str,
changes: dict = {},
objects: list = [],
params: dict[str, str | list[str] | dict] = {},
profile_data: dict[str, int] = {},
operation_id: str | None = None,
validation_guids: list[str] | None = None,
) -> dict:
time_str = str(int(time.time()))
headers = {
"Content-Type": "application/json",
"x-csrf-token": x_csrf_token,
"x-mx-reqtoken": time_str + "-" + str(self._request_id),
}
self._request_id += 1

payload = {
"action": action,
"changes": changes,
"objects": objects,
"params": params,
"profiledata": profile_data,
}
if operation_id:
payload["operationId"] = operation_id
if validation_guids:
payload["validationGuids"] = validation_guids

r = s.post(API_URL, json=payload, headers=headers)
if r.status_code != 200:
_LOGGER.error("error doing request: " + r.text)
r.raise_for_status()
return r.json()

def fetch(self) -> list[Collection]:
self._request_id = 3
s = requests.Session()
r = s.get(INIT_URL)
r.raise_for_status()

r = s.post(API_URL, json=INIT_PAYLOAD)
r.raise_for_status()

init_data = r.json()

objects = [init_data["objects"][1]]
params: dict[str, str | list[str] | dict] = {
"actionname": "Service_YouAreBeingRedirected.SUB_YouAreBeingRedirected",
"applyto": "selection",
"guids": [init_data["objects"][1]["guid"]],
}
x_csrf_token = init_data["csrftoken"]
cachebust = init_data["cachebust"]

data = self._do_request(
s,
action="executeaction",
x_csrf_token=x_csrf_token,
objects=objects,
params=params,
)

r = requests.get(
BASE_URL + "pages/en_US/" + data["instructions"][0]["args"]["FormPath"],
params={cachebust: ""},
)
r.raise_for_status()
OPERATION_ID_REGEX = r'"config":{"operationId":"([a-zA-Z0-9/]+)",'
operation_ids = list(re.finditer(OPERATION_ID_REGEX, r.text))
operation_id_post = operation_ids[0].group(1)
operation_id_uprn = operation_ids[1].group(1)

objects = data["objects"]
changes_postcode = data["changes"]
changes_postcode[list(changes_postcode.keys())[0]][
"EnquiryPostcodeOrStreetName"
] = {"value": self._postcode}

params = {
"OS_MissedBinEnquiry": {
"guid": data["objects"][0]["guid"],
}
}
validation_guids = [data["objects"][0]["guid"]]

data = self._do_request(
s,
action="runtimeOperation",
x_csrf_token=x_csrf_token,
objects=objects,
changes=changes_postcode,
operation_id=operation_id_post,
params=params,
validation_guids=validation_guids,
)

uprn_chage_element: tuple[str, dict] | None = None

for change_id, chage_dict in data["changes"].items():
if "UPRN" in chage_dict and chage_dict["UPRN"]["value"].strip().strip(
"0"
) == str(self._uprn).strip().strip("0"):
uprn_chage_element = (change_id, chage_dict)
break

if uprn_chage_element is None:
raise SourceArgumentNotFound("uprn", self._uprn)

objects += [
next(
iter([o for o in data["objects"] if o["guid"] == uprn_chage_element[0]])
)
]
params = {"Generic_Address": {"guid": objects[-1]["guid"]}}

changes = changes_postcode.copy()
changes[list(changes.keys())[0]]["ShowAddressResults"] = {"value": True}

changes.update({uprn_chage_element[0]: uprn_chage_element[1]})
data = self._do_request(
s,
"runtimeOperation",
changes=changes,
objects=objects,
operation_id=operation_id_uprn,
x_csrf_token=x_csrf_token,
validation_guids=validation_guids,
params=params,
)

entries = []
for change in data["changes"].values():
for key, value in change.items():
if not key.startswith("Next"):
continue

# Tuesday 07/01/2025
date_str = value["value"]
bin_type = key.replace("Next", "")
try:
date = datetime.strptime(date_str, "%A %d/%m/%Y").date()
except ValueError:
_LOGGER.warning(
f"Could not parse date: {date_str} for bin type {bin_type}"
)
icon = ICON_MAP.get(bin_type)
entries.append(Collection(date=date, t=bin_type, icon=icon))

return entries
48 changes: 48 additions & 0 deletions doc/source/knowsley_gov_uk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Knowsley Council

Support for schedules provided by [Knowsley Council](https://www.knowsley.gov.uk/), serving Knowsley Council, UK.

## Configuration via configuration.yaml

```yaml
waste_collection_schedule:
sources:
- name: knowsley_gov_uk
args:
postcode: POSTCODE
uprn: UPRN
```
### Configuration Variables
**postcode**
*(String) (required)*
**uprn**
*(String | Integer) (required)*
## Example
```yaml
waste_collection_schedule:
sources:
- name: knowsley_gov_uk
args:
postcode: L364AR
uprn: "000040082756"
```
```yaml
waste_collection_schedule:
sources:
- name: knowsley_gov_uk
args:
postcode: L34 0HZ
uprn: 40029195
```
## How to get the source argument
Use your postcode as the `postcode` argument and your Unique Property Reference Number (UPRN) as the `uprn` argument.

An easy way to discover your Unique Property Reference Number (UPRN) is by going to <https://www.findmyaddress.co.uk/> and entering in your address details.
Loading

0 comments on commit 66b9626

Please sign in to comment.