from dataclasses import dataclass from campaigns.assets.dtos import AssetUploadCredentials from campaigns.assets.services import AssetService from campaigns.connectors.facebook.base import FacebookClient from campaigns.meta.enums import AssetPositionGroup from campaigns.meta.exceptions import CampaignImageDoesNotExist from campaigns.meta.models import Campaign, CampaignImage from campaigns.meta.repositories import CampaignImageRepository @dataclass class CampaignImageService: facebook_client: FacebookClient campaign_image_repository: CampaignImageRepository asset_service: AssetService async def create_campaign_image( self, campaign: Campaign, *, filename: str, position_group: AssetPositionGroup, ) -> tuple[CampaignImage, AssetUploadCredentials]: asset, credentials = await self.asset_service.create_asset_with_credentials( filename ) image = CampaignImage() image.campaign_id = campaign.id image.asset_id = asset.id image.position_group = position_group self.campaign_image_repository.add(image) credentials.upload_metadata.update( { "meta_campaign_id": image.campaign_id, "meta_campaign_image_id": image.id, "meta_campaign_image_position_group": image.position_group, } ) return image, credentials async def get_image(self, image_id: str) -> CampaignImage: image = await self.campaign_image_repository.get(image_id) if not image: raise CampaignImageDoesNotExist return image async def delete_image(self, image: CampaignImage) -> None: await self.asset_service.delete_asset(image.asset) if image.image_hash: await self.facebook_client.delete_ad_image(image.image_hash) await self.campaign_image_repository.delete(image) return None