feat(agent-office): issue_* 텔레그램 콜백 디스패치
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,9 @@ async def _handle_callback(callback_query: dict) -> Optional[dict]:
|
|||||||
if callback_id.startswith("render_"):
|
if callback_id.startswith("render_"):
|
||||||
return await _handle_insta_render(callback_query, callback_id)
|
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)
|
cb = get_telegram_callback(callback_id)
|
||||||
if not cb:
|
if not cb:
|
||||||
return None
|
return None
|
||||||
@@ -132,6 +135,40 @@ async def _handle_insta_render(callback_query: dict, callback_id: str) -> dict:
|
|||||||
return {"ok": False, "error": str(e)}
|
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": <int>}) 로 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]:
|
async def _handle_message(message: dict, agent_dispatcher) -> Optional[dict]:
|
||||||
"""슬래시 명령 메시지 처리."""
|
"""슬래시 명령 메시지 처리."""
|
||||||
from .router import parse_command, resolve_agent_command, HELP_TEXT
|
from .router import parse_command, resolve_agent_command, HELP_TEXT
|
||||||
|
|||||||
@@ -73,3 +73,48 @@ async def test_callback_reject_marks_rejected(monkeypatch):
|
|||||||
res = await agent.on_callback("issue_reject", {"slate_id": 8})
|
res = await agent.on_callback("issue_reject", {"slate_id": 8})
|
||||||
assert res["ok"] is True
|
assert res["ok"] is True
|
||||||
dec.assert_awaited_once_with(8, "rejected")
|
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"
|
||||||
|
|||||||
Reference in New Issue
Block a user