Replace Playwright with requests for login
Playwright is heavyweight and currently broken. The login now uses the OAuth2 token endpoint directly with requests library instead of browser automation. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2ade1eee5e
commit
cdf7c3e2bc
1 changed files with 32 additions and 19 deletions
51
schedule.py
51
schedule.py
|
|
@ -12,7 +12,6 @@ from datetime import date, datetime, timezone
|
||||||
import ics # type: ignore
|
import ics # type: ignore
|
||||||
import jinja2
|
import jinja2
|
||||||
import requests
|
import requests
|
||||||
from playwright.sync_api import Playwright, sync_playwright # type: ignore
|
|
||||||
|
|
||||||
base_dir = os.path.dirname(__file__)
|
base_dir = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
|
@ -41,28 +40,43 @@ dest = config["location"]["dest"]
|
||||||
ics_file = config["location"]["ics_file"]
|
ics_file = config["location"]["ics_file"]
|
||||||
|
|
||||||
|
|
||||||
def run(playwright: Playwright) -> None:
|
def perform_login() -> None:
|
||||||
"""Login to the Wheelie Fresh Bin website."""
|
"""Login to the Wheelie Fresh Bin website using OAuth2 token endpoint."""
|
||||||
browser = playwright.chromium.launch(headless=True)
|
session = requests.Session()
|
||||||
context = browser.new_context()
|
|
||||||
|
|
||||||
page = context.new_page()
|
# OAuth2 password grant format
|
||||||
|
token_data = {
|
||||||
|
"grant_type": "password",
|
||||||
|
"username": username,
|
||||||
|
"password": password,
|
||||||
|
}
|
||||||
|
|
||||||
page.goto(login_url)
|
# POST to the token endpoint
|
||||||
page.locator('input[name="UserName"]').fill(username)
|
token_url = "https://portal.wheeliefreshbins.com/Token"
|
||||||
page.locator('input[name="Password"]').fill(password)
|
response = session.post(token_url, data=token_data)
|
||||||
page.locator('input[name="RememberMe"]').check()
|
|
||||||
|
|
||||||
with page.expect_navigation(url=summary_url):
|
if response.status_code != 200:
|
||||||
page.locator('input:has-text("Log in")').click()
|
raise Exception(f"Login failed with status {response.status_code}: {response.text}")
|
||||||
|
|
||||||
page.locator('a:has-text("Schedule")').click()
|
# The token endpoint should set the authentication cookie
|
||||||
|
cookie_value = session.cookies.get(".AspNet.Cookies")
|
||||||
|
if not cookie_value:
|
||||||
|
raise Exception("Authentication cookie not found after login")
|
||||||
|
|
||||||
page.close()
|
# Save cookie in the same format as Playwright did
|
||||||
|
auth_data = {
|
||||||
|
"cookies": [
|
||||||
|
{
|
||||||
|
"name": ".AspNet.Cookies",
|
||||||
|
"value": cookie_value,
|
||||||
|
"domain": "portal.wheeliefreshbins.com",
|
||||||
|
"path": "/",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
context.storage_state(path=auth_json_path)
|
with open(auth_json_path, "w") as f:
|
||||||
context.close()
|
json.dump(auth_data, f, indent=2)
|
||||||
browser.close()
|
|
||||||
|
|
||||||
|
|
||||||
def get_cookie_value() -> str:
|
def get_cookie_value() -> str:
|
||||||
|
|
@ -92,8 +106,7 @@ def read_html_from_json(r: requests.models.Response) -> str:
|
||||||
|
|
||||||
def login() -> None:
|
def login() -> None:
|
||||||
"""Login to Wheelie Fresh Bins."""
|
"""Login to Wheelie Fresh Bins."""
|
||||||
with sync_playwright() as playwright:
|
perform_login()
|
||||||
run(playwright)
|
|
||||||
|
|
||||||
|
|
||||||
def get_schedule_html() -> str | typing.NoReturn:
|
def get_schedule_html() -> str | typing.NoReturn:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue