from app.config import settings from app.models import ( ConversationState, SenderType, TextMessage, TextMessageAttachment, User, ) class FansifterConnector: def __init__(self) -> None: self.state = ConversationState.GREETING def _create( self, text: str, attachments: list[TextMessageAttachment] | None = None ) -> TextMessage: return TextMessage( sender=SenderType.fansifter, text=text, attachments=attachments or [], ) async def handle_incoming_message( self, message: str, user: User, ) -> list[TextMessage]: norm = message.strip().lower() handler = self._state_handlers().get(self.state) if handler: return handler(norm, user) return [] def _state_handlers(self): return { ConversationState.GREETING: self._handle_greeting, ConversationState.OPT_IN_ASKED: self._handle_opt_in_asked, ConversationState.OPTED_IN: self._handle_opted_in, ConversationState.OPTED_OUT: self._handle_opted_out, } def _handle_greeting(self, message: str, user: User) -> list[TextMessage]: self.state = ConversationState.OPT_IN_ASKED opt_in = user.settings.fansifter_settings.opt_in opt_in_terms = user.settings.fansifter_settings.opt_in_terms if message == "start": return [self._create(opt_in_terms)] if message == "stop": return [] return [self._create(opt_in + "\n" + opt_in_terms)] def _handle_opt_in_asked(self, message: str, user: User) -> list[TextMessage]: welcome = user.settings.fansifter_settings.welcome welcome_instructions = user.settings.fansifter_settings.welcome_instructions vcard = self._build_vcard_attachment(user) if message != "yes": return [] self.state = ConversationState.OPTED_IN return [ self._create( welcome + "\n" + welcome_instructions, attachments=[vcard] if vcard else [] ) ] def _handle_opted_in(self, message: str, user: User) -> list[TextMessage]: info = user.settings.fansifter_settings.info if message == "info": return [self._create(info)] if message == "stop": self.state = ConversationState.OPTED_OUT return [] def _handle_opted_out(self, message: str, _user: User | None = None) -> list[TextMessage]: if message == "start": self.state = ConversationState.OPTED_IN return [] def _build_vcard_attachment(self, user: User) -> TextMessageAttachment | None: if settings.default_user_settings is None: return None phone_number = "+1-555-0100" lines = [ "BEGIN:VCARD", "VERSION:3.0", f"FN:{user.settings.app_settings.artist_name}", f"TEL;TYPE=CELL:{phone_number}", "END:VCARD", ] content = "\r\n".join(lines).encode("utf-8") return TextMessageAttachment( type="vcard", content=content, filename=f"{user.settings.app_settings.artist_name.replace(' ', '_')}.vcf", mimetype="text/vcard", )