|
1 | | -from typing import Annotated |
| 1 | +""" |
| 2 | +File: backend/api/routes/feedback.py |
| 3 | +Task: 5.1.3 & 5.3.1 - Slack Webhooks (Refactored to use Lexicon) |
| 4 | +""" |
2 | 5 |
|
3 | | -from fastapi import APIRouter, Depends, status |
| 6 | +import json |
4 | 7 |
|
5 | | -from backend.api.dependencies import get_feedback_repository |
6 | | -from backend.models.schemas import FeedbackCreate, FeedbackResponse |
7 | | -from backend.repositories.feedback_repository import FeedbackRepository |
| 8 | +import structlog |
| 9 | +from fastapi import APIRouter, HTTPException, Request, Response |
8 | 10 |
|
9 | | -router = APIRouter(prefix="/feedback", tags=["Feedback"]) |
| 11 | +from backend.config.lexicon import SLACK_UI |
| 12 | +from backend.workers.tasks.generate_draft import generate_draft_task |
10 | 13 |
|
| 14 | +logger = structlog.get_logger() |
| 15 | +router = APIRouter(prefix="/slack", tags=["Slack Integration"]) |
11 | 16 |
|
12 | | -@router.post("/", response_model=FeedbackResponse, status_code=status.HTTP_201_CREATED) |
13 | | -async def create_feedback( |
14 | | - feedback_in: FeedbackCreate, |
15 | | - feedback_repo: Annotated[FeedbackRepository, Depends(get_feedback_repository)], |
16 | | -): |
17 | | - """Зберігає відгук користувача щодо згенерованої чернетки.""" |
18 | | - feedback = await feedback_repo.create(feedback_in) |
19 | | - return feedback |
| 17 | + |
| 18 | +@router.post("/commands") |
| 19 | +async def slack_slash_command(request: Request): |
| 20 | + """ |
| 21 | + Обробляє слеш-команду /draft від Slack. |
| 22 | + Формат очікуваного тексту: "Тема публікації | платформа" |
| 23 | + """ |
| 24 | + form_data = await request.form() |
| 25 | + |
| 26 | + command = form_data.get("command") |
| 27 | + text = str(form_data.get("text", "")).strip() |
| 28 | + user_id = form_data.get("user_id") |
| 29 | + # channel_id = form_data.get("channel_id") |
| 30 | + |
| 31 | + if command != "/draft": |
| 32 | + return {"response_type": "ephemeral", "text": SLACK_UI["cmd_unknown"]} |
| 33 | + |
| 34 | + if not text: |
| 35 | + return {"response_type": "ephemeral", "text": SLACK_UI["cmd_missing_args"]} |
| 36 | + |
| 37 | + parts = [p.strip() for p in text.split("|")] |
| 38 | + topic = parts[0] |
| 39 | + platform = parts[1].lower() if len(parts) > 1 else "telegram" |
| 40 | + |
| 41 | + valid_platforms = ["telegram", "twitter", "threads"] |
| 42 | + if platform not in valid_platforms: |
| 43 | + return { |
| 44 | + "response_type": "ephemeral", |
| 45 | + "text": SLACK_UI["cmd_invalid_platform"].format( |
| 46 | + platform=platform, valid_platforms=", ".join(valid_platforms) |
| 47 | + ), |
| 48 | + } |
| 49 | + |
| 50 | + logger.info( |
| 51 | + "slack_command_received", topic=topic, platform=platform, user_id=user_id |
| 52 | + ) |
| 53 | + |
| 54 | + # Відправляємо задачу в Taskiq |
| 55 | + await generate_draft_task.kiq(topic=topic, platform=platform) # type: ignore[call-overload] |
| 56 | + |
| 57 | + # Повертаємо миттєву відповідь для Slack |
| 58 | + return { |
| 59 | + "response_type": "in_channel", |
| 60 | + "text": SLACK_UI["cmd_accepted"].format(topic=topic, platform=platform), |
| 61 | + } |
| 62 | + |
| 63 | + |
| 64 | +@router.post("/interactions") |
| 65 | +async def slack_interactions(request: Request): |
| 66 | + # ... код обробки кнопок залишається тим самим ... |
| 67 | + form_data = await request.form() |
| 68 | + payload_str = form_data.get("payload") |
| 69 | + |
| 70 | + if not payload_str: |
| 71 | + raise HTTPException(status_code=400, detail="Missing payload") |
| 72 | + |
| 73 | + payload = json.loads(str(payload_str)) |
| 74 | + user_id = payload.get("user", {}).get("id") |
| 75 | + |
| 76 | + if payload.get("type") == "block_actions": |
| 77 | + actions = payload.get("actions", []) |
| 78 | + for action in actions: |
| 79 | + action_id = action.get("action_id") |
| 80 | + |
| 81 | + if action_id == "action_publish_draft": |
| 82 | + logger.info("slack_draft_approved_button", user_id=user_id) |
| 83 | + |
| 84 | + elif action_id == "action_reject_draft": |
| 85 | + logger.info("slack_draft_rejected_button", user_id=user_id) |
| 86 | + |
| 87 | + return Response(status_code=200) |
0 commit comments