mirror of
https://github.com/kuhyx/screen-locker.git
synced 2026-07-04 16:43:03 +02:00
Extracted from testsAndMisc monorepo. Changes: - Rewrote imports from python_pkg.screen_locker.* → screen_locker.* - Vendored python_pkg.shared.log_integrity → screen_locker._log_integrity - Vendored wake_alarm constants (ALARM_DAYS, WAKE_AFTER_HOURS, RTCWAKE_BIN) into _constants.py - Extracted has_workout_skip_today into new screen_locker._wake_state module - Added tests for _wake_state.py (392 tests, 100% branch coverage) - Moved scripts/service files to repo root - Added standalone pyproject.toml, requirements.txt, .pre-commit-config.yaml, .gitignore - Added GitHub Actions CI workflows Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
"""Early bird window detection and log helpers for ScreenLocker."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
import json
|
|
import logging
|
|
|
|
from screen_locker._constants import (
|
|
EARLY_BIRD_END_HOUR,
|
|
EARLY_BIRD_END_MINUTE,
|
|
EARLY_BIRD_START_HOUR,
|
|
)
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class EarlyBirdMixin:
|
|
"""Mixin providing early-bird time window checks and log helpers."""
|
|
|
|
def _get_local_time_minutes(self) -> int:
|
|
"""Return current local time as minutes from midnight."""
|
|
now = datetime.now(tz=timezone.utc).astimezone()
|
|
return now.hour * 60 + now.minute
|
|
|
|
def _is_early_bird_time(self) -> bool:
|
|
"""Return True if current local time is in the early bird window."""
|
|
minutes = self._get_local_time_minutes()
|
|
start = EARLY_BIRD_START_HOUR * 60
|
|
end = EARLY_BIRD_END_HOUR * 60 + EARLY_BIRD_END_MINUTE
|
|
return start <= minutes < end
|
|
|
|
def _is_early_bird_log(self) -> bool:
|
|
"""Check if today's workout log entry is an early_bird provisional entry."""
|
|
if not self.log_file.exists():
|
|
return False
|
|
try:
|
|
with self.log_file.open() as f:
|
|
logs = json.load(f)
|
|
except (OSError, json.JSONDecodeError):
|
|
return False
|
|
today = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d")
|
|
entry = logs.get(today)
|
|
if entry is None:
|
|
return False
|
|
return entry.get("workout_data", {}).get("type") == "early_bird"
|
|
|
|
def _save_early_bird_log(self) -> None:
|
|
"""Save an early_bird provisional entry to the workout log."""
|
|
self.workout_data = {"type": "early_bird"}
|
|
self.save_workout_log()
|
|
|
|
def _try_auto_upgrade_early_bird(self) -> bool:
|
|
"""Silently upgrade today's early_bird entry if phone shows a workout."""
|
|
try:
|
|
status, message = self._verify_phone_workout()
|
|
except (OSError, RuntimeError) as exc:
|
|
_logger.info("Early bird upgrade phone check failed: %s", exc)
|
|
return False
|
|
if status != "verified":
|
|
_logger.info(
|
|
"Early bird upgrade skipped (phone status=%s): %s",
|
|
status,
|
|
message,
|
|
)
|
|
return False
|
|
self.workout_data["type"] = "phone_verified"
|
|
self.workout_data["source"] = message
|
|
self.workout_data["after_early_bird"] = "true"
|
|
self._adjust_shutdown_time_later()
|
|
self.save_workout_log()
|
|
return True
|