Default to America/Phoenix and email-alert once when the session expires
All checks were successful
Deploy / deploy (push) Successful in 25s
All checks were successful
Deploy / deploy (push) Successful in 25s
Phoenix doesn't observe DST, so schedule times stay meaningful year-round without needing a seasonal adjustment. notify.py reuses lunch-notifier's existing Gmail-SMTP-with-app-password pattern rather than adding a new notification channel. The alert fires exactly once per expiry (not on every failed scheduled run while it's down) via a dedupe flag in notify_state.json, reset the moment a fresh session is successfully imported. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H6TgffxTvYhqxykAbVQg2v
This commit is contained in:
parent
48d8bac332
commit
3b08af7938
7 changed files with 111 additions and 10 deletions
|
|
@ -36,6 +36,7 @@ from datetime import datetime, timezone
|
|||
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
import notify
|
||||
import storage
|
||||
|
||||
logger = logging.getLogger("massprice.automation")
|
||||
|
|
@ -79,9 +80,33 @@ def _is_logged_out(page):
|
|||
return "/Rule" not in page.url
|
||||
|
||||
|
||||
def _notify_session_expired_once():
|
||||
"""Send the email alert only on the first failure after the session
|
||||
goes bad, not on every scheduled run that fails while it's down —
|
||||
the flag resets when a fresh session is imported successfully."""
|
||||
state = storage.load("notify_state.json", {})
|
||||
if state.get("session_expired_notified"):
|
||||
return
|
||||
sent = notify.send_alert(
|
||||
"MassPrice Scheduler: login session expired",
|
||||
"The saved MassPrice session has expired or is missing. "
|
||||
"Scheduled rule runs will keep failing until you log back in "
|
||||
"via the Session page in the MassPrice Scheduler webui and "
|
||||
"import a fresh cookie export.",
|
||||
)
|
||||
# Only mark as notified if the email actually sent — an unset/broken
|
||||
# mail config shouldn't silently swallow the next attempt forever.
|
||||
if sent:
|
||||
storage.save(
|
||||
"notify_state.json",
|
||||
{"session_expired_notified": True, "notified_at": datetime.now(timezone.utc).isoformat()},
|
||||
)
|
||||
|
||||
|
||||
def _ensure_authenticated(page):
|
||||
page.goto(f"{BASE_URL}/Rule/List")
|
||||
if _is_logged_out(page):
|
||||
_notify_session_expired_once()
|
||||
raise AutomationError(
|
||||
"MassPrice session expired or missing — log in via the "
|
||||
"Session page and paste in a fresh cookie export."
|
||||
|
|
@ -264,5 +289,6 @@ def import_cookies(raw_text):
|
|||
"itself, after finishing login, not from the login page."
|
||||
)
|
||||
_save_state(context)
|
||||
storage.save("notify_state.json", {"session_expired_notified": False})
|
||||
finally:
|
||||
browser.close()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue