diff --git a/pyproject.toml b/pyproject.toml index 99a71f2..eda00d3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "opower" -version = "0.0.19" +version = "0.0.20" license = {text = "Apache-2.0"} authors = [ { name="tronikos", email="tronikos@gmail.com" }, diff --git a/src/demo.py b/src/demo.py index 893bba1..2270fd5 100644 --- a/src/demo.py +++ b/src/demo.py @@ -67,6 +67,8 @@ async def _main(): async with aiohttp.ClientSession() as session: opower = Opower(session, args.utility, username, password) await opower.async_login() + # Re-login to make sure code handles already logged in sessions. + await opower.async_login() forecasts = await opower.async_get_forecast() for forecast in forecasts: print("\nData for meter:", forecast.account.meter_type) diff --git a/src/opower/utilities/exelon.py b/src/opower/utilities/exelon.py index ee2b55a..1e46d8a 100644 --- a/src/opower/utilities/exelon.py +++ b/src/opower/utilities/exelon.py @@ -37,62 +37,65 @@ async def async_login( raise_for_status=True, ) as resp: result = await resp.text() - # transId = "StateProperties=..." - # policy = "B2C_1A_SignIn" - # tenant = "/euazurebge.onmicrosoft.com/B2C_1A_SignIn" - # api = "CombinedSigninAndSignup" - settings = json.loads(re.search(r"var SETTINGS = ({.*});", result).group(1)) - login_post_domain = resp.real_url.host - async with session.post( - "https://" - + login_post_domain - + settings["hosts"]["tenant"] - + "/SelfAsserted", - params={ - "tx": settings["transId"], - "p": settings["hosts"]["policy"], - }, - data={ - "request_type": "RESPONSE", - "signInName": username, - "password": password, - }, - headers={ - "X-CSRF-TOKEN": settings["csrf"], - "User-Agent": USER_AGENT, - }, - raise_for_status=True, - ) as resp: - result = json.loads(await resp.text()) + # If we are already logged in, we get redirected to /accounts/dashboard, so skip the login + if not resp.request_info.url.path.endswith("dashboard"): + # transId = "StateProperties=..." + # policy = "B2C_1A_SignIn" + # tenant = "/euazurebge.onmicrosoft.com/B2C_1A_SignIn" + # api = "CombinedSigninAndSignup" + settings = json.loads(re.search(r"var SETTINGS = ({.*});", result).group(1)) + login_post_domain = resp.real_url.host - if result["status"] != "200": - raise InvalidAuth(result["message"]) + async with session.post( + "https://" + + login_post_domain + + settings["hosts"]["tenant"] + + "/SelfAsserted", + params={ + "tx": settings["transId"], + "p": settings["hosts"]["policy"], + }, + data={ + "request_type": "RESPONSE", + "signInName": username, + "password": password, + }, + headers={ + "X-CSRF-TOKEN": settings["csrf"], + "User-Agent": USER_AGENT, + }, + raise_for_status=True, + ) as resp: + result = json.loads(await resp.text()) - async with session.get( - "https://" - + login_post_domain - + settings["hosts"]["tenant"] - + "/api/" - + settings["api"] - + "/confirmed", - params={ - "rememberMe": settings["config"]["enableRememberMe"], - "csrf_token": settings["csrf"], - "tx": settings["transId"], - "p": settings["hosts"]["policy"], - "diags": json.dumps( - { - "pageViewId": settings["pageViewId"], - "pageId": settings["api"], - "trace": [], - } - ), - }, - headers={"User-Agent": USER_AGENT}, - raise_for_status=True, - ) as resp: - result = await resp.text(encoding="utf-8") + if result["status"] != "200": + raise InvalidAuth(result["message"]) + + async with session.get( + "https://" + + login_post_domain + + settings["hosts"]["tenant"] + + "/api/" + + settings["api"] + + "/confirmed", + params={ + "rememberMe": settings["config"]["enableRememberMe"], + "csrf_token": settings["csrf"], + "tx": settings["transId"], + "p": settings["hosts"]["policy"], + "diags": json.dumps( + { + "pageViewId": settings["pageViewId"], + "pageId": settings["api"], + "trace": [], + } + ), + }, + headers={"User-Agent": USER_AGENT}, + raise_for_status=True, + ) as resp: + result = await resp.text(encoding="utf-8") async with session.post( "https://"