from dataclasses import dataclass, field from typing import ClassVar from fansifter_common.auth.requests import AuthRequest from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from email_campaigns.adapters.db import Repository from email_campaigns.api.schemas import CustomFont from email_campaigns.emails.exceptions import EmailNotFoundError from email_campaigns.emails.models import BaseEmail from email_campaigns.fonts.cache import GoogleFontsCache from email_campaigns.fonts.exceptions import InvalidGoogleFontError from email_campaigns.fonts.services.google_fonts import GoogleFontsService @dataclass(kw_only=True) class UpdateEmailFontsRequest(AuthRequest): email_id: str font: CustomFont = field(default_factory=list) class UpdateEmailFontsHandler[T: BaseEmail]: permission: ClassVar[Permission] def __init__( self, auth_service: AuthService, email_repository: Repository[T], google_fonts_cache: GoogleFontsCache, google_fonts_service: GoogleFontsService, ) -> None: self.auth_service = auth_service self.email_repository = email_repository self.google_fonts_cache = google_fonts_cache self.google_fonts_service = google_fonts_service def handle(self, request: UpdateEmailFontsRequest) -> list[CustomFont]: email = self.email_repository.get(request.email_id) if email is None: raise EmailNotFoundError self._check_can_update_fonts(email) self.auth_service.authorize_account( request.identity_id, account=email.account, permission=self.permission, ) font = self._validate_google_font(request.font.name) if current_fonts := email.custom_fonts: fonts = {f.name: f for f in current_fonts} else: fonts = {} fonts[font.name] = font result_fonts = list(fonts.values()) email.custom_fonts = result_fonts self.email_repository.save(email) return result_fonts def _check_can_update_fonts(self, email: T) -> None: pass def _validate_google_font(self, name: str) -> CustomFont: if not self.google_fonts_cache.is_populated(): fonts = self.google_fonts_service.get_fonts() self.google_fonts_cache.populate(fonts) google_font = self.google_fonts_cache.get_font(name) if google_font is None: raise InvalidGoogleFontError return CustomFont( name=google_font.name, cssFontFamily=google_font.css_font_family, url=google_font.url, )