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)