"""User subscription expiration helpers.""" from __future__ import annotations from datetime import datetime, timedelta from typing import Optional def user_is_expired(user: dict, *, now: Optional[datetime] = None) -> bool: """True when absolute expiration_date is in the past.""" exp_str = user.get('expiration_date') if not exp_str: return False try: exp_date = datetime.fromisoformat(str(exp_str)) except Exception: return False return (now or datetime.now()) > exp_date def maybe_start_user_expiration(data: dict, user_id: str, *, now: Optional[datetime] = None) -> Optional[str]: """If user waits for first config use, start the countdown. Returns the new expiration_date ISO string when activated, else None. """ if not user_id: return None user = next((u for u in data.get('users', []) if u.get('id') == user_id), None) if not user: return None if not user.get('expire_after_first_use'): return None if user.get('expiration_date'): return None days = int(user.get('expiration_days') or 0) if days <= 0: return None stamp = now or datetime.now() expires = stamp + timedelta(days=days) iso = expires.isoformat() user['expiration_date'] = iso return iso