This commit is contained in:
admin
2026-05-20 17:45:09 +09:00
parent 63ac6bc99a
commit da3aef25ce
19 changed files with 17286 additions and 407 deletions

View 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()