import base64 from datetime import datetime from uuid import UUID from app.api.messages.schemas import Message from app.api.participants.schemas import Participant from app.core.config import ( ENCODING_ASCII, ENCODING_UTF8, MESSAGE_EXPECTED_PARTS, MESSAGE_PARSE_EMPTY_ERROR, MESSAGE_PARSE_INVALID_ERROR, MESSAGE_SEPARATOR, TABLE_PARTICIPANTS, TABLE_TOPICS, ) from app.core.link import Link, TopicLink, ParticipantLink class MessageLineParser: SEPARATOR = MESSAGE_SEPARATOR EXPECTED_PARTS = MESSAGE_EXPECTED_PARTS @staticmethod def _decode_content(encoded: str) -> str: return base64.b64decode(encoded.encode(ENCODING_ASCII)).decode(ENCODING_UTF8) @staticmethod def _encode_content(value: str) -> str: return base64.b64encode(value.encode(ENCODING_UTF8)).decode(ENCODING_ASCII) @classmethod def parse(cls, line: str) -> Message: raw = line.strip() if not raw: raise ValueError(MESSAGE_PARSE_EMPTY_ERROR) parts = raw.split(cls.SEPARATOR) if len(parts) != cls.EXPECTED_PARTS: raise ValueError(MESSAGE_PARSE_INVALID_ERROR) ( message_id, topic_raw, order_in_topic, participant_raw, created_at_value, encoded_content, ) = parts return Message( id=UUID(message_id), topic_id=Link.from_raw(topic_raw), order_in_topic=int(order_in_topic), participant_id=Link.from_raw(participant_raw), created_at=datetime.fromisoformat(created_at_value), content=cls._decode_content(encoded_content), ) @classmethod def serialize(cls, message: Message) -> str: return cls.SEPARATOR.join( [ str(message.id), message.topic_id.as_path(), str(message.order_in_topic), message.participant_id.as_path(), message.created_at.isoformat(), cls._encode_content(message.content), ] )