File size: 4,738 Bytes
69f2337 a08f988 69f2337 a08f988 69f2337 a08f988 69f2337 a08f988 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
from datetime import datetime
from typing import List, Optional
from uuid import UUID, uuid4
from fastapi import HTTPException, status
from app.api.messages.schemas import MessageCreate
from app.api.messages.services import MessageService
from app.api.topics.parser import TopicLineParser
from app.api.topics.schemas import AddMessageRequest, Topic, TopicCreate, TopicMessage
from app.core.config import (
FORBIDDEN_WORDS,
FORBIDDEN_WORDS_MESSAGE,
TABLE_TOPICS,
TOPIC_NOT_FOUND_MESSAGE,
)
from app.core.file_manager import FileManager
from app.core.link import Link, TopicLink, ParticipantLink
class TopicService:
def __init__(self, file_manager: FileManager, message_service: MessageService | None = None) -> None:
self.file_manager = file_manager
self.message_service = message_service
@staticmethod
def _resolve_topic_id(value: UUID | Link) -> UUID:
if isinstance(value, UUID):
return value
return value.resolve({TABLE_TOPICS: lambda link_value: link_value})
def list_topics(self) -> List[Topic]:
topics: List[Topic] = []
for line in self.file_manager.read_lines():
try:
topics.append(TopicLineParser.parse(line))
except ValueError:
continue
return topics
def get_topic(self, topic_id: UUID | Link) -> Topic:
resolved_id = self._resolve_topic_id(topic_id)
for topic in self.list_topics():
if topic.id == resolved_id:
return topic
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=TOPIC_NOT_FOUND_MESSAGE,
)
def create_topic(self, payload: TopicCreate) -> Topic:
topic_messages = (
[]
if self.message_service
else [
TopicMessage(
participant_id=message.participant_id,
content=message.content,
)
for message in payload.messages
]
)
topic = Topic(
id=uuid4(),
title=payload.title,
description=payload.description,
created_at=datetime.utcnow(),
participants=payload.participants,
messages=topic_messages,
)
serialized = TopicLineParser.serialize(topic)
self.file_manager.append_line(serialized)
if self.message_service:
for message in payload.messages:
self.message_service.create_message(
MessageCreate(
topic_id=TopicLink(value=topic.id),
participant_id=message.participant_id,
content=message.content,
)
)
return topic
@staticmethod
def check_forbidden_words(content: str) -> Optional[str]:
content_lower = content.lower()
for word in FORBIDDEN_WORDS:
if word in content_lower:
return word
return None
def add_message(self, topic_id: UUID | Link, payload: AddMessageRequest) -> Topic:
forbidden_word = self.check_forbidden_words(payload.content)
if forbidden_word:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"{FORBIDDEN_WORDS_MESSAGE}: '{forbidden_word}'",
)
resolved_id = self._resolve_topic_id(topic_id)
if self.message_service:
self.message_service.create_message(
MessageCreate(
topic_id=TopicLink(value=resolved_id),
participant_id=ParticipantLink(value=payload.participant_id.value),
content=payload.content,
)
)
return self.get_topic(resolved_id)
topics = self.list_topics()
topic_index = None
for i, topic in enumerate(topics):
if topic.id == resolved_id:
topic_index = i
break
if topic_index is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=TOPIC_NOT_FOUND_MESSAGE,
)
new_message = TopicMessage(
participant_id=payload.participant_id,
content=payload.content,
)
topics[topic_index].messages.append(new_message)
lines = [TopicLineParser.serialize(t) for t in topics]
self.file_manager.write_lines(lines)
return topics[topic_index]
def export_topic(self, topic_id: UUID | Link) -> str:
topic = self.get_topic(topic_id)
return TopicLineParser.serialize(topic)
|