42 lines
1.2 KiB
Python
42 lines
1.2 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import re
|
||
|
|
from dataclasses import dataclass
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from yuxi.utils.logging_config import logger
|
||
|
|
|
||
|
|
_APPROVER_ID_RE = re.compile(r"^ou_[a-f0-9]+$", re.IGNORECASE)
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass
|
||
|
|
class FeishuApprovalAdapter:
|
||
|
|
approvers: list[str]
|
||
|
|
timeout_s: float = 300.0
|
||
|
|
|
||
|
|
def normalize_approver_id(self, raw_id: str) -> str | None:
|
||
|
|
cleaned = raw_id.strip()
|
||
|
|
if _APPROVER_ID_RE.match(cleaned):
|
||
|
|
return cleaned
|
||
|
|
if cleaned.startswith("on_"):
|
||
|
|
return cleaned
|
||
|
|
if cleaned.startswith("ou_"):
|
||
|
|
return cleaned
|
||
|
|
logger.debug("[FeishuApproval] Invalid approver ID format: %s", cleaned)
|
||
|
|
return None
|
||
|
|
|
||
|
|
def check_approval(self, open_id: str) -> bool:
|
||
|
|
for approver in self.approvers:
|
||
|
|
normalized = self.normalize_approver_id(approver)
|
||
|
|
if normalized and normalized == open_id:
|
||
|
|
return True
|
||
|
|
return False
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def from_config(cls, config: dict[str, Any]) -> FeishuApprovalAdapter:
|
||
|
|
approval_cfg = config.get("approval", {}) or {}
|
||
|
|
return cls(
|
||
|
|
approvers=approval_cfg.get("approvers", []),
|
||
|
|
timeout_s=float(approval_cfg.get("timeout", 300)),
|
||
|
|
)
|