Created
October 23, 2018 13:58
-
-
Save fpcMotif/bcc2ec1019c9da158b3d886a591cea8f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import random | |
| from facebookads.adobjects.adcreativeobjectstoryspec import AdCreativeObjectStorySpec | |
| from facebookads.adobjects.adcreativelinkdata import AdCreativeLinkData | |
| from ads_app.api import AdsApi | |
| from ads_app.api.objects import Ad, AdLabel, CarouselAd | |
| from sjp_app.documents.sjp_image import SjpImage | |
| from sjp_app.documents.strategy import Strategy | |
| from w4.documents.mongo_job import MongoJob | |
| ads_too_many_matching_filters = [] | |
| ads_no_filters_for_job = [] | |
| ads_no_filters_for_image = [] | |
| ads_unknown_state = [] | |
| ads_caroussel = [] | |
| def is_wording_matching(filter_set, link_data, job): | |
| """ | |
| Return True if all the `filter_set` wording exactly the | |
| same as the ad woding. | |
| Sometimes some ad do not have all the keys (name, message, | |
| description). For instance check creative 6092189325241. | |
| """ | |
| filter_set_wording = filter_set.get_ad_creative_texts(job, job.job_title_pure) | |
| return all([ | |
| link_data[key] == filter_set_wording[key] | |
| for key in filter_set_wording if link_data.get(key) | |
| ]) | |
| def is_image_matching(filter_set, image_hash): | |
| """" | |
| Return True if the `image_hash` is in the `filter_set`. | |
| """ | |
| return any([ | |
| image.facebook_img_hash == image_hash for image in filter_set.images | |
| ]) | |
| def get_filter_set(strategy, ad, link_data, image_hash, job): | |
| """ | |
| Tries to get the filter set. | |
| """ | |
| default_fs = None | |
| job_fs = set() | |
| for filter_set, filter_jobs in strategy.get_filters_with_their_jobs(): | |
| if filter_set.is_default: | |
| default_fs = filter_set | |
| if job in filter_jobs: | |
| job_fs.add(filter_set) | |
| if not job_fs: | |
| print("No filter_set found for this job, you'll be killed one day!!") | |
| ads_no_filters_for_job.append(ad) | |
| return None | |
| if len(job_fs) == 1: | |
| print("Only one filter that's the one <3") | |
| return job_fs.pop() | |
| job_wording_matching_fs = set( | |
| filter_set for filter_set in job_fs if is_wording_matching(filter_set, link_data, job) | |
| ) | |
| job_image_matching_fs = set( | |
| filter_set for filter_set in job_fs if is_image_matching(filter_set, image_hash) | |
| ) | |
| # If there are several filter set matching then ads ops are A/B testing and the default | |
| # filter set is not the one used. | |
| if len(job_wording_matching_fs) > 1: | |
| job_wording_matching_fs = job_wording_matching_fs - set(default_fs) | |
| if len(job_image_matching_fs) > 1: | |
| job_image_matching_fs = job_image_matching_fs - set(default_fs) | |
| if not job_image_matching_fs: | |
| print("No corresponding image, you need to be paused!!") | |
| ads_no_filters_for_image.append(ad) | |
| return None | |
| if len(job_wording_matching_fs) == 1: | |
| print("Only one filter set has the same wording <3") | |
| return job_wording_matching_fs.pop() | |
| if len(job_image_matching_fs) == 1: | |
| print("Only one filter set has the same image <3") | |
| return job_image_matching_fs.pop() | |
| if len(job_wording_matching_fs) > 1 or len(job_image_matching_fs) > 1: | |
| print("The ad could be in different filter set... we pick one randomly and notify the ops") | |
| all_matching_fs = job_image_matching_fs.union(job_image_matching_fs) | |
| ads_too_many_matching_filters.append(ad) | |
| return random.sample(all_matching_fs, 1) | |
| print("OOOPSY we don't handle that case (yet)") | |
| ads_unknown_state.append(ad) | |
| return None | |
| api = AdsApi() | |
| batch = api.new_batch() | |
| ads = api.account.get_ads( | |
| params={ | |
| Ad.Field.effective_status: [ | |
| Ad.EffectiveStatus.active, | |
| Ad.EffectiveStatus.pending_review, | |
| Ad.EffectiveStatus.pending_billing_info, | |
| Ad.EffectiveStatus.campaign_paused, | |
| Ad.EffectiveStatus.adset_paused | |
| ], | |
| 'limit': 500 | |
| }, | |
| fields=[ | |
| Ad.Field.name, | |
| 'creative{object_story_spec}', # crucial to have the right Ad classes (carousel) | |
| Ad.Field.adlabels, | |
| Ad.Field.campaign_id | |
| ] | |
| ) | |
| for ad in ads: | |
| fs_label = None | |
| image_label = None | |
| # checks if we have a any filter set label or image label | |
| for adlabel in ad.get(Ad.Field.adlabels, []): | |
| label_name = adlabel.get('name', '') | |
| if AdLabel.FILTER_SET_LABEL_PREFIX in label_name: | |
| fs_label = label_name | |
| if "img_id=" in label_name: | |
| image_label = label_name | |
| if image_label and fs_label: | |
| print "Ad (%s) already got and image (%s) and filter set (%s) label." % ( | |
| ad.get_id(), image_label, fs_label | |
| ) | |
| continue | |
| print "Ad (%s) got missing label: image (%s), filter set (%s)." % ( | |
| ad.get_id(), image_label, fs_label | |
| ) | |
| creative = ad.ensure_field(ad.Field.creative) | |
| fb_campaign_id = ad.get(Ad.Field.campaign_id) | |
| strategy = Strategy.objects(fb_campaign_id=fb_campaign_id).first() | |
| if not strategy: | |
| print "Lovely some custom ads camapign (%s) in the SJP account" % fb_campaign_id | |
| continue | |
| if isinstance(ad, CarouselAd): | |
| print "Ad (%s) is a CarouselAd." % (ad.get_id()) | |
| ads_caroussel.append(ad) | |
| job_ids = creative.get_job_ids() | |
| image_hashes = creative.get_image_hashes() | |
| jobs = [ | |
| MongoJob.objects(job_id=job_id).first() | |
| for job_id in job_ids | |
| ] | |
| # TODO: deal with carousel ad | |
| else: | |
| job_id = ad.get_job_id() | |
| job = MongoJob.objects(job_id=job_id).first() | |
| link_data = creative[creative.Field.object_story_spec][AdCreativeObjectStorySpec.Field.link_data] | |
| image_hash = link_data.get(AdCreativeLinkData.Field.image_hash) | |
| filter_set = get_filter_set(strategy, ad, link_data, image_hash, job) | |
| adlabel_batch = api.new_batch() | |
| if image_hash: | |
| images = SjpImage.objects.filter(facebook_img_hash=image_hash) | |
| if len(images) == 1: | |
| image = images[0] | |
| elif filter_set: | |
| adlabel = AdLabel(parent_id=api.account_id) | |
| adlabel.remote_create(params={ | |
| AdLabel.Field.name: AdLabel.IMAGE_LABEL_PREFIX % image.google_id | |
| }) | |
| ad.add_adlabel(adlabel) | |
| if not filter_set: | |
| print "No filter set found for Ad(%s)." % (ad.get_id()) | |
| adlabel = AdLabel(parent_id=api.account_id) | |
| adlabel.remote_create(params={ | |
| AdLabel.Field.name: AdLabel.FILTER_SET_LABEL_PREFIX + str(filter_set.id) | |
| }, batch=adlabel_batch) | |
| ad.add_adlabel(adlabel) | |
| adlabel_batch.execute() | |
| ad_batch = api.new_batch() | |
| ad.remote_update(batch=ad_batch) | |
| ad_batch.execute() | |
| # DEBUGG POST SCRIPT | |
| print len(ads_too_many_matching_filters) | |
| print len(ads_no_filters_for_job) | |
| print len(ads_no_filters_for_image) | |
| print len(ads_unknown_state) | |
| print len(ads_caroussel) | |
| creative = ad.ensure_field(ad.Field.creative) | |
| fb_campaign_id = ad.get(Ad.Field.campaign_id) | |
| strategy = Strategy.objects(fb_campaign_id=fb_campaign_id).first() | |
| job_id = ad.get_job_id() | |
| job = MongoJob.objects(job_id=job_id).first() | |
| link_data = creative[creative.Field.object_story_spec][AdCreativeObjectStorySpec.Field.link_data] | |
| image_hash = link_data[AdCreativeLinkData.Field.image_hash] | |
| filter_set = get_filter_set(strategy, ad, link_data, image_hash, job) | |
| print strategy.id | |
| strategies = set(Strategy.objects(fb_campaign_id=ad.get(Ad.Field.campaign_id)).first() for ad in ads_too_many_matching_filters) | |
| for strategy in strategies: | |
| if not strategy.is_over: | |
| print strategy | |
| print strategy.id | |
| print strategy.state | |
| # EMEA - SJP - Manpower France - Logistique Vente Privee - 201801 - MF - RT - St-Vulbas - PRIO_1 - Lead_Ads | |
| # 5a5f7f89baeb406179449474 | |
| # active | |
| # EMEA - SJP - Start People - BTP - 201711 - MF - RT - Multiple Locations - Vertical - PRIO_1 - Lead_Ads - Delivering | |
| # 5a267f55f32a5c691ff0ff01 | |
| # active |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment