from collections.abc import Sequence from dataclasses import dataclass from typing import ClassVar from anydi import singleton from fansifter_common.auth.account import Account from fansifter_common.auth.identity import Identity from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from dmp.adapters.features import AUDIENCE_SHOW_ADD_SECONDARY_FANS_TOGGLE, Features from dmp.audiences.dtos import AudiencesQueryCriteria from dmp.audiences.enums import AudienceTarget from dmp.audiences.models import Audience from dmp.audiences.repositories import AudienceRepository from dmp.audiences.types import AudiencesOrderBy @dataclass(kw_only=True) class GetAudiencesRequest: DEFAULT_LIMIT: ClassVar[int] = 50 DEFAULT_OFFSET: ClassVar[int] = 0 DEFAULT_ORDER_BY: ClassVar[AudiencesOrderBy] = "createdAt.desc" identity: Identity search: str | None vendor_id: int | None subaccount_id: int | None global_participant_id: str | None custom_list_id: str | None audience_ids: list[str] | None include_archived: bool = False target: AudienceTarget | None order_by: AudiencesOrderBy limit: int offset: int @property def account(self) -> Account | None: if self.vendor_id: return Account( vendor_id=self.vendor_id, subaccount_id=self.subaccount_id or 0, ) return None @dataclass(frozen=True) class GetAudiencesResponse: total: int items: Sequence[Audience] @singleton class GetAudiencesHandler: access_permission = Permission("audience", "access") ad_target_permission = Permission("audience", "view_ad_target") email_target_permission = Permission("audience", "view_email_target") text_target_permission = Permission("audience", "view_text_target") def __init__( self, auth_service: AuthService, audience_repository: AudienceRepository, features: Features, ) -> None: self.auth_service = auth_service self.audience_repository = audience_repository self.features = features def handle(self, request: GetAudiencesRequest) -> GetAudiencesResponse: self.auth_service.authorize_for_permission( request.identity.id, permission=self.access_permission ) ad_target_account_access = self.auth_service.get_account_access_for_permission( request.identity.id, permission=self.ad_target_permission, ) email_target_account_access = ( self.auth_service.get_account_access_for_permission( request.identity.id, permission=self.email_target_permission, ) ) text_target_account_access = ( self.auth_service.get_account_access_for_permission( request.identity.id, permission=self.text_target_permission, ) ) ad_target_vendor_ids = ad_target_account_access.filter_vendor_ids( request.vendor_id ) ad_target_subaccount_ids = ad_target_account_access.filter_subaccount_ids( request.subaccount_id ) email_target_vendor_ids = email_target_account_access.filter_vendor_ids( request.vendor_id ) email_target_subaccount_ids = email_target_account_access.filter_subaccount_ids( request.subaccount_id ) text_target_vendor_ids = text_target_account_access.filter_vendor_ids( request.vendor_id ) text_target_subaccount_ids = text_target_account_access.filter_subaccount_ids( request.subaccount_id ) criteria = AudiencesQueryCriteria( ad_target_vendor_ids=ad_target_vendor_ids, ad_target_subaccount_ids=ad_target_subaccount_ids, email_target_vendor_ids=email_target_vendor_ids, email_target_subaccount_ids=email_target_subaccount_ids, text_target_vendor_ids=text_target_vendor_ids, text_target_subaccount_ids=text_target_subaccount_ids, search=request.search, global_participant_id=request.global_participant_id, custom_list_id=request.custom_list_id, audience_ids=request.audience_ids, target=request.target, include_archived=request.include_archived, ) total = self.audience_repository.count_by_criteria( criteria, identity_id=request.identity.id ) audiences = ( self.audience_repository.find_by_criteria( criteria, order_by=request.order_by, limit=request.limit, offset=request.offset, identity_id=request.identity.id, ) if total > 0 else [] ) # Update secondary fans if the feature flag is on if self.features.is_on_for_identity( feature_flag_name=AUDIENCE_SHOW_ADD_SECONDARY_FANS_TOGGLE, identity_id=request.identity.id, ): for audience in audiences: audience.filters.set_include_secondary_fans(target=audience.target) return GetAudiencesResponse(total=total, items=audiences)