import json from db import db from models.marketing_accounts import MarketingAccount, MarketingAccountSource from typing import List, Optional from psycopg2.extras import NumericRange from models.territories import Territory from utils.snowflake.google_data.models import GRASCampaignUrl, LinkfireLink from utils.snowflake.facebook_data.models import FacebookCampaignsQueryResult from constants.labels_constants import TEST_UK_LABEL_ID, TEST_US_LABEL_ID ALL_AUTOMATED_APP_ADS = "All (Automated App Ads)" FACEBOOK_PLATFORMS = ["facebook", "instagram", "audience_network", "messenger"] ALL_PLATFORMS = "all" class FacebookImporterUtils: def map_links(self, links: Optional[str]) -> Optional[List[GRASCampaignUrl]]: if links: return [self.__map_link(link) for link in json.loads(links) if link.get("final_urls")] else: return [] def __map_link(self, link) -> GRASCampaignUrl: urls = link["final_urls"] return GRASCampaignUrl(title=link.get("display_url"), links=[urls]) def map_linkfire_links(self, links: Optional[str]) -> Optional[List[LinkfireLink]]: if links: return [ LinkfireLink(link_id=link.get("linkfire_id"), link_url=link.get("linkfire_url")) for link in json.loads(links) if link.get("linkfire_id") ] else: return None def map_artists_external_ids(self, item: FacebookCampaignsQueryResult) -> List[str]: if not item.artists: return [] artists = json.loads(item.artists) ids = [artist.get("member_id", artist.get("artist_id")) for artist in artists if artist != {}] return [f"GRAS_{id}" for id in ids] def marketing_accounts(self) -> List[str]: accounts = ( db.session.query(MarketingAccount.external_id) .filter( MarketingAccount.source == MarketingAccountSource.FACEBOOK.value, MarketingAccount.label_id.notin_([TEST_UK_LABEL_ID, TEST_US_LABEL_ID]) ) .all() ) return [item[0] for item in accounts] class FacebookWorkerUtils: source_name = "facebook" global_country_code = "GLBL" default_genders = [1, 2, 3] global_territory_id = 0 all_ages = 0, 65 unknown_age_ranges = [ALL_AUTOMATED_APP_ADS, "Unknown"] def build_gender_ids(self, genders: List[str]) -> Optional[List[int]]: if not genders: return None return list(map(self.__map_gender_from, genders)) def build_campaign_links(self, links) -> List[str]: links_values = [link.links[0] for link in links or []] return list(set(links_values)) def __map_gender_from(self, gender_string: str) -> (int, int): if gender_string == "male": return 1 if gender_string == "female": return 2 else: return 3 def build_age_range(self, age_ranges: List[str]) -> NumericRange: if ( not age_ranges or (len(age_ranges) == 1 and age_ranges[0] in self.unknown_age_ranges) or (age_ranges and ALL_AUTOMATED_APP_ADS in age_ranges) ): return NumericRange(self.all_ages[0], self.all_ages[1], "[]") ranges = map(self.__map_range_from, filter(lambda item: item != "Unknown", age_ranges)) result = [] for begin, end in sorted(ranges): if result and result[-1][1] >= begin - 1: result[-1][1] = max(result[-1][1], end) else: result.append([begin, end]) return NumericRange(result[0][0], result[-1][1], "[]") def __map_range_from(self, age_string: str) -> (int, int): if age_string == "65+": return 65, 65 values = age_string.split("-") return int(values[0]), int(values[1]) def build_objective(self, objective: Optional[str]) -> int: objective_map = { "APP_INSTALLS": 1, # App Promotion "MESSAGES": 12, # Messages "REACH": 13, # Reach "VIDEO_VIEWS": 17, # Video Views "EVENT_RESPONSES": 18, # Event Responses "BRAND_AWARENESS": 9, # Brand Awareness "LEAD_GENERATION": 4, # Leads "LINK_CLICKS": 16, # Traffic "PAGE_LIKES": 5, # Followers / Subscribers "POST_ENGAGEMENT": 14, # Engagement "PRODUCT_CATALOG_SALES": 7, # Sales "CONVERSIONS": 3, # Conversions } return objective_map.get(objective, 1) def map_territories(self, country_codes: List[str]): if not country_codes: return [self.global_territory_id] territory_ids = db.session.query(Territory.id).filter(Territory.code.in_(country_codes)).all() if len(territory_ids) == 0: territory_ids = [self.global_territory_id] return territory_ids def get_campaign_platforms(self, platform_names: List[str]): if ALL_PLATFORMS in platform_names or ALL_AUTOMATED_APP_ADS in platform_names: platform_names = FACEBOOK_PLATFORMS mapped_platforms = [name.lower() for name in platform_names if name.lower() in FACEBOOK_PLATFORMS] mapped_platforms = [item.replace("_", " ") for item in mapped_platforms if item] return ["Social Ads", mapped_platforms]