import copy import uuid from statistics import mean from service.db import engine from service.tasks.api_service_handler.facebook.service_fb_db_handler import ( DbFbServiceHandler, ) from service.tasks.api_service_handler.facebook.service_fb_internal import ( FbServiceHandler, ) from service.tasks.audience.audience_facebook import FbAudience from service.tasks.delete_collection import _delete_collection from service.tasks.filtering import create_audience_collection def generate_fb_audience( user_id, collectionId, audienceName, audienceDescription, management_schema, workspace_schema=None, alliance_schema=None, ): audience_collection_id = create_audience_collection( schema=alliance_schema or workspace_schema, user_id=user_id, name=audienceName, collection_ids=[collectionId], )["id"] """Generating the collection data df""" audience = FbAudience( collection_id=audience_collection_id, schema=alliance_schema or workspace_schema ) fb_audience_data, test_data = audience.get_audience_data() """Creating audience in fb, adjusting the data, uploading the data to fb audience""" fb = FbServiceHandler() public_reference_id = str(uuid.uuid4()) audience_name = f"Fansifter - {audienceName}" response = fb.create_audience( audience_name=audience_name, description=audienceDescription, public_id=public_reference_id, ) # workaround made after introduction of lower and upper bounds in API v11 response["data"]["approximate_count"] = int( mean( [ response["data"]["approximate_count_lower_bound"], response["data"]["approximate_count_upper_bound"], ] ) ) response["data"]["actual_count"] = len(fb_audience_data) external_audience_id = response["data"]["id"] test_df = copy.deepcopy(test_data) test_df["audience_id"] = external_audience_id test_df.columns = map(str.lower, test_df.columns) """Saving the original data """ test_df.to_sql( "fb_temp_audience_data", engine, schema=alliance_schema or workspace_schema, if_exists="append", index=False, ) data = fb.generate_list_of_users(df=fb_audience_data) fb.upload_all_users_to_audience( audience_id=external_audience_id, data_obj=data ) # Store users_upload_status """Populating corresponding DB tables with audience data""" db_io = DbFbServiceHandler() db_io.populate_commons_fb_audience_meta_table( schema=alliance_schema or workspace_schema, external_audience_id=external_audience_id, collection_id=audience_collection_id, public_id=public_reference_id, ) internal_audience_id = db_io.populate_fb_audience_table( schema=alliance_schema or workspace_schema, user_id=user_id, response_obj=response["data"], collection_id=audience_collection_id, ) # AudienceExtended type for appsync df = db_io.list_audiences_and_adaccounts( schema=alliance_schema or workspace_schema, user_id=user_id, internal_audience_id=internal_audience_id, default_schema=management_schema, ) response = df.to_dict("records") try: response = response[0] except IndexError: response = None return response, external_audience_id def initiate_fb_audience_sharing( adAccountId, audienceId, user_id, management_schema, final_response=None, external_audience_id=None, workspace_schema=None, alliance_schema=None, ): """Initiating sharing process and actually sharing the audience if the sharing agreement with addaccount was previously established Adapted to be used in create_and_share_audience""" db_io = DbFbServiceHandler() if final_response is None: """Getting the base audience data""" final_response = db_io.get_audience_info( schema=alliance_schema or workspace_schema, internal_audience_id=audienceId ) external_audience_id = copy.deepcopy(final_response["external_id"]) del final_response["external_id"] fb = FbServiceHandler() sharing_response = fb.initiate_or_share_audience( audience_id=external_audience_id, partner_ad_account_id=adAccountId ) """ When sharing lookalike audience we get empty `sharing_data` parameter but share works""" if ( len(sharing_response["data"].get("sharing_data", [])) > 0 ): # checking if we got the data data = sharing_response["data"]["sharing_data"] else: data = [{"ad_acct_id": adAccountId, "audience_share_status": "shared"}] db_io.populate_fb_audience_shared_state_table( schema=alliance_schema or workspace_schema, internal_audience_id=audienceId, data=data, ) """ Getting list of all shared adaccounts for this audience""" df = db_io.list_audiences_and_adaccounts( schema=alliance_schema or workspace_schema, default_schema=management_schema, internal_audience_id=audienceId, user_id=user_id, ) final_response = df.to_dict("records") try: final_response = final_response[0] except IndexError: final_response = None # Returning AudienceExtended type for appsync return final_response def unshare_fb_audience( schema, user_id, audienceId, adAccountId, management_schema, **kw ): """Removing audience sharing with specific adaccount""" adaccount_id = str(adAccountId) db_io = DbFbServiceHandler() external_audience_id, account_id = db_io.get_audience_id( schema=schema, internal_id=audienceId ) """FB API call to revoke sharing""" fb = FbServiceHandler(account_id) fb.revoke_audience_sharing_from_adaccount( external_audience_id=external_audience_id, partner_ad_account_id=adaccount_id ) """DB queries to remove data from table""" db_io.delete_from_fb_audience_shared_state_table( schema=schema, internal_audience_id=audienceId, adaccount_id=adaccount_id ) """Getting updated AudienceExtended type from db""" df = db_io.list_audiences_and_adaccounts( schema=schema, internal_audience_id=audienceId, user_id=user_id, default_schema=management_schema, ) final_response = df.to_dict("records") try: final_response = final_response[0] except IndexError: final_response = None # Returning AudienceExtended type for appsync return final_response def soft_delete_audience(schema, management_schema, user_id, audienceId, **kw): """Nothing soft about the delete, it's just a fantasy we entartained at some point.""" db_io = DbFbServiceHandler() external_audience_id, account_id = db_io.get_audience_id( schema=schema, internal_id=audienceId ) audience_collection_id = db_io.get_audience_collection_id( schema=schema, internal_id=audienceId ) fb = FbServiceHandler(account_id) fb.delete_audience(str(external_audience_id)) db_io.delete_audience( schema=schema, internal_audience_id=audienceId, external_audience_id=external_audience_id, ) _delete_collection( schema, management_schema, user_id, audience_collection_id, related=False ) # Returning Audience type for appsync return { "id": audienceId, "name": "", "description": "", "size": 0, "collection_id": None, }