diff --git a/agent-office/app/telegram/webhook.py b/agent-office/app/telegram/webhook.py index 82a1e63..a736842 100644 --- a/agent-office/app/telegram/webhook.py +++ b/agent-office/app/telegram/webhook.py @@ -40,6 +40,9 @@ async def _handle_callback(callback_query: dict) -> Optional[dict]: if callback_id.startswith("render_"): return await _handle_insta_render(callback_query, callback_id) + if callback_id.startswith("issue_"): + return await _handle_insta_issue(callback_query, callback_id) + cb = get_telegram_callback(callback_id) if not cb: return None @@ -132,6 +135,40 @@ async def _handle_insta_render(callback_query: dict, callback_id: str) -> dict: return {"ok": False, "error": str(e)} +async def _handle_insta_issue(callback_query: dict, callback_id: str) -> dict: + """issue_{approve|reject|regen}_{slate_id} 콜백 → InstaAgent.on_callback. + + callback_data 예시: issue_approve_8, issue_reject_8, issue_regen_8 + InstaAgent.on_callback("issue_approve" | "issue_reject" | "issue_regen", {"slate_id": }) 로 dispatch. + """ + from .messaging import send_raw + from ..agents import AGENT_REGISTRY + + await api_call( + "answerCallbackQuery", + {"callback_query_id": callback_query["id"], "text": "처리 중..."}, + ) + + try: + rest = callback_id.removeprefix("issue_") # 예: "approve_8" + verb, sid = rest.rsplit("_", 1) # ("approve", "8") + slate_id = int(sid) + except (ValueError, AttributeError): + await send_raw("⚠️ 잘못된 issue 콜백 데이터") + return {"ok": False, "error": "invalid_callback_data"} + + agent = AGENT_REGISTRY.get("insta") + if not agent: + await send_raw("⚠️ insta agent 미등록") + return {"ok": False, "error": "agent_missing"} + + try: + return await agent.on_callback(f"issue_{verb}", {"slate_id": slate_id}) + except Exception as e: + await send_raw(f"⚠️ issue 콜백 처리 실패: {e}") + return {"ok": False, "error": str(e)} + + async def _handle_message(message: dict, agent_dispatcher) -> Optional[dict]: """슬래시 명령 메시지 처리.""" from .router import parse_command, resolve_agent_command, HELP_TEXT diff --git a/agent-office/tests/test_insta_autonomous.py b/agent-office/tests/test_insta_autonomous.py index d05054b..1616313 100644 --- a/agent-office/tests/test_insta_autonomous.py +++ b/agent-office/tests/test_insta_autonomous.py @@ -73,3 +73,48 @@ async def test_callback_reject_marks_rejected(monkeypatch): res = await agent.on_callback("issue_reject", {"slate_id": 8}) assert res["ok"] is True dec.assert_awaited_once_with(8, "rejected") + + +@pytest.mark.asyncio +async def test_handle_insta_issue_dispatch(monkeypatch): + """_handle_insta_issue: issue_approve_8 → on_callback('issue_approve', {slate_id:8}).""" + import sys + # stub api_call so answerCallbackQuery doesn't hit real Telegram + import app.telegram.webhook as wh + monkeypatch.setattr(wh, "api_call", AsyncMock(return_value={"ok": True})) + + agent = InstaAgent() + on_cb = AsyncMock(return_value={"ok": True}) + monkeypatch.setattr(agent, "on_callback", on_cb) + + from app.agents import AGENT_REGISTRY + old = AGENT_REGISTRY.get("insta") + AGENT_REGISTRY["insta"] = agent + try: + result = await wh._handle_insta_issue( + {"id": "cq1", "data": "issue_approve_8"}, + "issue_approve_8", + ) + finally: + if old is None: + AGENT_REGISTRY.pop("insta", None) + else: + AGENT_REGISTRY["insta"] = old + + on_cb.assert_awaited_once_with("issue_approve", {"slate_id": 8}) + assert result["ok"] is True + + +@pytest.mark.asyncio +async def test_handle_insta_issue_invalid_data(monkeypatch): + """_handle_insta_issue: 잘못된 callback_data → ok=False, error=invalid_callback_data.""" + import app.telegram.webhook as wh + monkeypatch.setattr(wh, "api_call", AsyncMock(return_value={"ok": True})) + monkeypatch.setattr("app.telegram.messaging.send_raw", AsyncMock()) + + result = await wh._handle_insta_issue( + {"id": "cq2", "data": "issue_bad"}, + "issue_bad", + ) + assert result["ok"] is False + assert result["error"] == "invalid_callback_data"