修正
This commit is contained in:
85
backend/app/modules/egov/state.py
Normal file
85
backend/app/modules/egov/state.py
Normal file
@@ -0,0 +1,85 @@
|
||||
import asyncio
|
||||
import time
|
||||
from enum import Enum
|
||||
from typing import Optional, Any
|
||||
|
||||
|
||||
class EGovStatus(str, Enum):
|
||||
IDLE = "idle"
|
||||
STARTING = "starting"
|
||||
WAITING_MFA = "waiting_mfa"
|
||||
LOGGED_IN = "logged_in"
|
||||
DOWNLOADING = "downloading"
|
||||
ERROR = "error"
|
||||
|
||||
|
||||
class EGovState:
|
||||
def __init__(self):
|
||||
self.status: EGovStatus = EGovStatus.IDLE
|
||||
self.message: str = ""
|
||||
self.mfa_event: asyncio.Event = asyncio.Event()
|
||||
self.mfa_code: Optional[str] = None
|
||||
self.screenshot_b64: Optional[str] = None
|
||||
self.last_download: Optional[dict] = None # {filename, path, size}
|
||||
|
||||
# ブラウザセッション(Playwright 方式, 後方互換用)
|
||||
self._playwright: Optional[Any] = None
|
||||
self._browser: Optional[Any] = None
|
||||
self._context: Optional[Any] = None
|
||||
self._page: Optional[Any] = None
|
||||
|
||||
# ── OAuth2 / e-Gov API 方式 ──────────────────────────────
|
||||
self.access_token: Optional[str] = None
|
||||
self.refresh_token: Optional[str] = None
|
||||
self.token_expires_at: Optional[float] = None # unix timestamp
|
||||
self._pkce_verifier: Optional[str] = None
|
||||
self._oauth_state: Optional[str] = None
|
||||
|
||||
def is_token_valid(self) -> bool:
|
||||
"""アクセストークンが有効かどうかを返す(60秒マージン)"""
|
||||
if not self.access_token:
|
||||
return False
|
||||
if self.token_expires_at and time.time() >= self.token_expires_at - 60:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_tokens(self, token_response: dict):
|
||||
"""トークンレスポンスをステートにセット"""
|
||||
self.access_token = token_response.get("access_token")
|
||||
self.refresh_token = token_response.get("refresh_token")
|
||||
expires_in = token_response.get("expires_in", 300)
|
||||
self.token_expires_at = time.time() + int(expires_in)
|
||||
|
||||
def reset(self):
|
||||
self.status = EGovStatus.IDLE
|
||||
self.message = ""
|
||||
self.mfa_event = asyncio.Event()
|
||||
self.mfa_code = None
|
||||
self.screenshot_b64 = None
|
||||
self.last_download = None
|
||||
self.access_token = None
|
||||
self.refresh_token = None
|
||||
self.token_expires_at = None
|
||||
self._pkce_verifier = None
|
||||
self._oauth_state = None
|
||||
|
||||
async def close_browser(self):
|
||||
"""ブラウザを閉じてリソースを解放"""
|
||||
try:
|
||||
if self._browser:
|
||||
await self._browser.close()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
if self._playwright:
|
||||
await self._playwright.stop()
|
||||
except Exception:
|
||||
pass
|
||||
self._playwright = None
|
||||
self._browser = None
|
||||
self._context = None
|
||||
self._page = None
|
||||
|
||||
|
||||
# モジュールレベルのシングルトン
|
||||
state = EGovState()
|
||||
Reference in New Issue
Block a user