def update(self, request, *args, **kwargs): line_item = self.get_object() data = copy.copy(request.data) data[ 'account_id'] = line_item.tw_campaign_id.tw_account_id.tw_account_id data['campaign_id'] = line_item.tw_campaign_id.tw_campaign_id data['line_item_id'] = line_item.pk data['paused'] = data.get('status') != 'enabled' res = TwitterLineItem.update(data) if res['success']: res = TwitterTargeting.set_targeting(data['targeting'], data['account_id']) if not res['success']: return Response(dict(messages=res['error']['messages']), status=status.HTTP_400_BAD_REQUEST) else: return Response(dict(error=res['message']), status=status.HTTP_400_BAD_REQUEST) data['tweet_ids'] = ','.join(data['tweet_ids']) res = TwitterPromotedTweet.set_promoted_tweet(data, data['account_id']) if res['success']: cpi_target_goal = data['cpi_target_goal'] revmap, created = TwitterRevmap.objects_raw.get_or_create( campaign_id=line_item.tw_campaign_id.campaign_id, tw_campaign_id=line_item.tw_campaign_id.pk, tw_line_item_id=line_item.pk) revmap.opt_type = 'install' revmap.opt_value = cpi_target_goal revmap.save() else: return Response(dict( error='Associating promotable tweets with line item failed!'), status=status.HTTP_400_BAD_REQUEST) return Response( TwitterLineItemDetailSerializer(self.get_object()).data)
def _generate_campaign_explode_by_campaign(self): campaigns_data = list() for r in self.rows: campaign_data = dict() campaign_data['account_id'] = self.account_id campaign_data['daily_budget_amount_local_micro'] = \ long(round(float(self.data['daily_budget_amount_local_micro']), 2) * 1000000) campaign_data['funding_instrument_id'] = self.data[ 'funding_instrument'] campaign_data['name'] = r[2] campaign_data['paused'] = r[5] == 'PAUSED' campaign_data['start_time'] = self.data.get( 'flight_start_date', datetime.now(pytz.timezone('US/Central')).strftime( '%Y-%m-%dT%H:%M:%S%z')) campaign_data['end_time'] = self.data.get('flight_end_date') campaign_data['total_budget_amount_local_micro'] = \ long(round(float(self.data.get('total_budget_amount_local_micro') or 0), 2) * 1000000) campaigns_data.append(campaign_data) campaigns_res = TwitterCampaign.batch_create(campaigns_data, self.account_id) campaign_data = campaigns_data[0] if campaigns_res['success']: campaign_id = self.data.get('internal_campaign_id') campaign = Campaign.objects_raw.filter(pk=campaign_id).first() if campaign: self.res_json = CampaignSerializer(campaign).data line_items = [] targeting_data = [] for campaign_res in campaigns_res['data']: for r in self.rows: if r[2] == campaign_res['name']: line_item_data, targetings = self._get_line_item_and_targeting( r, campaign_data, campaign_res['id']) line_items.append(line_item_data) targeting_data += targetings # create batch line items line_items_res = TwitterLineItem.batch_create( line_items, self.account_id) if line_items_res['success']: self._revise_targeting_data_with_line_items_res( line_items_res, targeting_data) # set batch targetings targetings_res = TwitterTargeting.set_targeting( targeting_data, self.account_id) if not targetings_res['success']: raise Exception(targetings_res['error']['messages']) else: raise Exception( line_items_res.get('error', {}).get('messages', '')) else: raise Exception(campaigns_res.get('error', {}).get('messages', ''))
def get(self, request): params = request.data if request.method == 'POST' else request.query_params account_id = params.get('account_id', None) tw_account_id = params.get('tw_account_id', None) if account_id is not None and tw_account_id is None: tw_account = TwitterLineItem.objects.get(account_id=account_id) tw_account_id = tw_account.tw_account_id if tw_account_id is not None: data = TwitterLineItem.fetch_line_items( dict(tw_account_id=tw_account_id)) return Response(data=data, status=status.HTTP_200_OK) return Response(data=dict(status='error', msg='Missing input tw_account_id ID'), status=status.HTTP_404_NOT_FOUND)
def _update_tw_line_item(self, tw_line_item): self._log(tw_line_item.bid_amount_computed_reason) tw_line_item.save_raw() # Auto-optimize if tw_line_item.tw_line_item_id in settings.TW_AUTO_OPTIMIZE_LINE_ITEMS and \ tw_line_item.bid_amount_local_micro != tw_line_item.bid_amount_computed: self._log("Auto-optimizing tw_line_item_id %d to $%.2f" % (tw_line_item.tw_line_item_id, float(tw_line_item.bid_amount_computed) / 1000000)) tw_account_id = tw_line_item.tw_campaign_id.tw_account_id.tw_account_id res = TwitterLineItem.update({ 'account_id': tw_account_id, 'line_item_id': tw_line_item.tw_line_item_id, 'bid_amount_local_micro': tw_line_item.bid_amount_computed }) if not res['success']: self._log("ERROR: Failed updating tw_line_item_id bid: " + res['message'])
def post(self, request, *args, **kwargs): tw_line_items = request.DATA.get('tw_line_items') success_count = 0 for obj in tw_line_items: if obj.get('tw_line_item_id'): tw_line_item_id = obj['tw_line_item_id'] instance = TwitterLineItem.objects.filter( tw_line_item_id=tw_line_item_id).first() if obj.get('bid_amount_local_micro') and \ instance.bid_amount_local_micro != obj['bid_amount_local_micro']: account_id = instance.tw_campaign_id.tw_account_id.tw_account_id data = dict(account_id=account_id, line_item_id=tw_line_item_id, bid_amount_local_micro=obj.get( 'bid_amount_local_micro'), paused=(instance.status != 'enabled')) res = TwitterLineItem.update(data) if res['success']: success_count += 1 tw_campaign_id = instance.tw_campaign_id.tw_campaign_id campaign = instance.tw_campaign_id.campaign_id if obj.get('cpi_target_goal'): revmap, created = TwitterRevmap.objects.get_or_create( campaign_id=campaign, tw_campaign_id=tw_campaign_id, tw_line_item_id=tw_line_item_id) revmap.opt_type = 'install' if revmap.opt_value != obj['cpi_target_goal']: revmap.opt_value = obj['cpi_target_goal'] revmap.save() return Response({'status': 'ok', 'success_count': success_count})
def handle(self, *args, **options): manage_campaign_id = None tw_campaign_id = None tw_account_id = None if 'tw_account_id' in options: tw_account_id = options['tw_account_id'] if 'tw_campaign_id' in options: tw_campaign_id = options['tw_campaign_id'] if 'campaign_id' in options: manage_campaign_id = options['campaign_id'] if 'targeting' in options: targeting = options['targeting'] if 'dryrun' in options and options['dryrun'] is True: self.dryrun = True if 'verbose' in options and options['verbose'] is True: self.verbose = True # gq10nzw account = TwitterAccount.objects_raw.get(tw_account_id=1011176351) oauth_token = account.tw_twitter_user_id.oauth_token oauth_secret = account.tw_twitter_user_id.oauth_secret # api_campaigns_data = TwitterCampaign.fetch_campaigns(dict(account_id=account.tw_account_id), True) # api_campaign_data = api_campaigns_data['data'] # campaign_data = api_campaign_data[0] # new_campaign_data = {} # new_campaign_data['name'] = "CREATE API - Image {1201}" # new_campaign_data['account_id'] = 1011176351 # new_campaign_data['funding_instrument_id'] = campaign_data['funding_instrument_id'] # new_campaign_data['daily_budget_amount_local_micro'] = campaign_data['daily_budget_amount_local_micro'] # new_campaign_data['paused'] = str(True).lower() # new_campaign_data['standard_delivery'] = str(True).lower() # new_campaign_data['start_time'] = '2016-08-09T13:45:00Z' # print new_campaign_data # new_campaign = TwitterCampaign.create_campaign(new_campaign_data, oauth_token, oauth_secret) # print "-------- RESULT --------" # print new_campaign # update_campaign_data = {} # update_campaign_data['campaign_id'] = 8148469 # update_campaign_data['account_id'] = 1011176351 # update_campaign_data['daily_budget_amount_local_micro'] = campaign_data['daily_budget_amount_local_micro'] * 2 # #print update_campaign_data # update_campaign = TwitterCampaign.update_campaign(update_campaign_data, oauth_token, oauth_secret) # print "-------- RESULT --------" # print update_campaign ############################################# # Line Item ############################################# # new_line_item_data = {} # new_line_item_data['account_id'] = 1011176351 # new_line_item_data['campaign_id'] = '4uned' # new_line_item_data['name'] = 'CREATE API - VAN - LINE_ITEM' # new_line_item_data['product_type'] = 'PROMOTED_TWEETS' # new_line_item_data['placements'] = 'ALL_ON_TWITTER' # new_line_item_data['objective'] = 'APP_INSTALLS' # new_line_item_data['bid_amount_local_micro'] = 10000 # new_line_item_data['automatically_select_bid'] = str(False).lower() # new_line_item_data['paused'] = str(True).lower() # new_line_item = TwitterLineItem.create_line_item(new_line_item_data, oauth_token, oauth_secret) # print "-------- RESULT --------" # print new_line_item # update_line_item_data = {} # update_line_item_data['account_id'] = 1011176351 # update_line_item_data['campaign_id'] = '4uned' # update_line_item_data['line_item_id'] = int_to_base36(9911328) # update_line_item_data['bid_amount_local_micro'] = 500000 # update_line_item_data['automatically_select_bid'] = str(False).lower() # update_line_item_data['paused'] = str(False).lower() # update_line_item_data2 = {} # update_line_item_data2['account_id'] = 1011176351 # update_line_item_data2['campaign_id'] = '4uned' # update_line_item_data2['line_item_id'] = int_to_base36(9939049) # update_line_item_data2['bid_amount_local_micro'] = 400000 # update_line_item_data2['automatically_select_bid'] = str(False).lower() # update_line_item_data2['paused'] = str(False).lower() # update_line_item = TwitterLineItem.update_line_item(update_line_item_data, oauth_token, oauth_secret) # print "-------- RESULT --------" # print update_line_item # batch = [] # batch.append(update_line_item_data) # batch.append(update_line_item_data2) # bath_update_line_item = TwitterLineItem.batch_update_line_item(batch, 1011176351, '339117672-TI1rfxzoiQdrOHfrPqzbE0FCWkOCcePr9mDDJ4qX', 'ZTSkOFGPXXJqGIWzpgAN7mh3ogg7jxbR1Sc1EPbVL3rDW') # print "-------- RESULT --------" # print bath_update_line_item # m_tw_line_item_targeting = TwitterTargeting.objects_raw.filter(tw_line_item_id=8460210).values() # m_tw_line_item_targeting_list = list(m_tw_line_item_targeting) # targeting_list = m_tw_line_item_targeting_list #print targeting_list # new = { # "tw_line_item_id": 8460210, # "tw_targeting_type": 17, # "tw_targeting_id": "3009", # "targeting_value": "" # } # targeting_list.append(new) #print targeting_list # batch = [] # batches = [] # for x in range(0, len(targeting_list), 20): # batch = targeting_list[x:x+20] # batches.append(batch) # print chunks # criteria = json.loads(criteria_str) # update_targeting = TwitterTargeting.set_targeting(targeting_list, 4503599654958352, oauth_token, oauth_secret) # print "=" * 100 # print json.dumps(update_targeting, indent=4) campaign_list = [] line_item_list = [] for number in range(3, 100): print number # new_campaign_data = {} # new_campaign_data['name'] = "CREATE API - {}".format(number) # new_campaign_data['account_id'] = 1011176351 # new_campaign_data['paused'] = str(True).lower() # new_campaign_data['standard_delivery'] = str(True).lower() # new_campaign_data['start_time'] = '2016-08-09T13:45:00Z' # campaign_list.append(new_campaign_data) new_line_item_data = {} new_line_item_data['account_id'] = 1011176351 new_line_item_data['campaign_id'] = 'gq10nz' new_line_item_data['name'] = "'CREATE API - LINE_ITEM {}".format( number) new_line_item_data['product_type'] = 'PROMOTED_TWEETS' new_line_item_data['placements'] = 'ALL_ON_TWITTER' new_line_item_data['objective'] = 'APP_INSTALLS' new_line_item_data['bid_amount_local_micro'] = 10000 new_line_item_data['automatically_select_bid'] = str(False).lower() new_line_item_data['paused'] = str(True).lower() line_item_list.append(new_line_item_data) #print line_item_list new_line_items = TwitterLineItem.batch_create(line_item_list, 1011176351, oauth_token, oauth_secret) print new_line_items
def _twitter_sync_account(self, args): start_time = datetime.now() settings.SYSTEM_USER = True manage_campaign_cache = {} if self.verbose: print "Syncing Twitter Data" # Fetch all twitter accounts os_platform = None if 'tw_account_id' in args and args['tw_account_id']: account_id = args['tw_account_id'] if isinstance(account_id, basestring) and not account_id.isdigit(): account_id = base36_to_int(account_id) m_accounts = [] try: account = TwitterAccount.objects_raw.get( tw_account_id=account_id) m_accounts.append(account) except TwitterAccount.DoesNotExist: print "Cannot find account: " + str(account_id) else: m_accounts = TwitterAccount.objects_raw.all() data = {} for m_account in m_accounts: try: oauth_token = None oauth_secret = None try: oauth_token = m_account.tw_twitter_user_id.oauth_token oauth_secret = m_account.tw_twitter_user_id.oauth_secret except TwitterUser.DoesNotExist: oauth_token = None oauth_secret = None pass if oauth_token == '': oauth_token = None if oauth_secret == '': oauth_secret = None # Check status of each Twitter Account via API api_accounts_data = TwitterAccount.fetch_accounts( dict(account_id=m_account.tw_account_id)) self._check_api_errors(api_accounts_data, m_account, "TwitterAccount") api_accounts = [] if isinstance(api_accounts_data['data'], dict): api_accounts.append(api_accounts_data['data']) elif isinstance(api_accounts_data['data'], (list, tuple)): api_accounts = api_accounts_data['data'] if self.verbose: print "--> Fetching Account data for: " + str( m_account.tw_account_id) + " (" + str( int_to_base36(m_account.tw_account_id)) + ")" except KeyError: pass for api_account in api_accounts: # Fetch campaigns from Twitter try: if 'manage_campaign_id' in args and args[ 'manage_campaign_id'] is not None: manage_campaign_id = args['manage_campaign_id'] if oauth_token is not None and oauth_secret is not None: api_campaigns_data = TwitterCampaign.fetch_campaigns( dict(account_id=m_account.tw_account_id, campaign_id=manage_campaign_id), True, oauth_token, oauth_secret) else: api_campaigns_data = TwitterCampaign.fetch_campaigns( dict(account_id=m_account.tw_account_id, campaign_id=manage_campaign_id), True) else: if oauth_token is not None and oauth_secret is not None: api_campaigns_data = TwitterCampaign.fetch_campaigns( dict(account_id=m_account.tw_account_id), True, oauth_token, oauth_secret) else: api_campaigns_data = TwitterCampaign.fetch_campaigns( dict(account_id=m_account.tw_account_id), True) self._check_api_errors(api_campaigns_data, m_account, "TwitterCampaign") api_campaigns = [] if isinstance(api_campaigns_data['data'], dict): api_campaigns.append(api_campaigns_data['data']) elif isinstance(api_campaigns_data['data'], (list, tuple)): api_campaigns = api_campaigns_data['data'] if 'os_platform' in api_campaigns_data: os_platform = api_campaigns_data['os_platform'] if self.verbose: print "--> Fetching App Cards for: " + str( m_account.tw_account_id) api_campaign_app_cards_data = TwitterAppCard.fetch_app_cards( dict(account_id=m_account.tw_account_id), True, oauth_token, oauth_secret) self._check_api_errors(api_campaign_app_cards_data, m_account, "TwitterAppCard") api_campaign_app_cards = [] if isinstance(api_campaign_app_cards_data['data'], dict): api_campaign_app_cards.append( api_campaign_app_cards_data['data']) elif isinstance(api_campaign_app_cards_data['data'], (list, tuple)): api_campaign_app_cards = api_campaign_app_cards_data[ 'data'] for api_campaign_app_card in api_campaign_app_cards: if self.verbose: print "----> Syncing App Card: " + str( api_campaign_app_card['name']) + " (" + str( api_campaign_app_card['card_type']) + ")" if self.verbose: print "--> Fetching Tailored Audiences for: " + str( m_account.tw_account_id) api_tailored_audiences_data = TwitterTailoredAudience.fetch_tailored_audience( dict(account_id=m_account.tw_account_id), True, oauth_token, oauth_secret) api_tailored_audiences = [] if isinstance(api_tailored_audiences_data['data'], dict): api_tailored_audiences.append( api_tailored_audiences_data['data']) elif isinstance(api_tailored_audiences_data['data'], (list, tuple)): api_tailored_audiences = api_tailored_audiences_data[ 'data'] for api_tailored_audience in api_tailored_audiences: if self.verbose: print "----> Syncing Tailored Audience: " + str( api_tailored_audience['name']) if self.verbose: print "--> (" + str( len(api_campaigns)) + ") total Campaigns" except KeyError: pass for api_campaign in api_campaigns: api_line_items = [] try: campaign_id_int = base36_to_int(api_campaign['id']) if 'tw_campaign_id' in args and args[ 'tw_campaign_id'] is not None and args[ 'tw_campaign_id'] != '': if args['tw_campaign_id'] != str(campaign_id_int): continue if self.verbose: print "--> Syncing Campaign: " + str( api_campaign['name']) + " - (" + str( api_campaign['id']) + ")" campaign_id_int = base36_to_int(api_campaign['id']) # Get Line Items api_line_items_data = TwitterLineItem.fetch_line_items( dict(account_id=m_account.tw_account_id, campaign_id=api_campaign['id']), True, oauth_token, oauth_secret) if isinstance(api_line_items_data['data'], dict): api_line_items.append(api_line_items_data['data']) elif isinstance(api_line_items_data['data'], (list, tuple)): api_line_items = api_line_items_data['data'] # Parse Manage Campaign ID from TW Campaign name manage_campaign_id = None if 'manage_campaign_id' in api_campaign and api_campaign[ 'manage_campaign_id']: manage_campaign_id = api_campaign[ 'manage_campaign_id'] # Look up Manage Campaign manage_campaign = None if manage_campaign_id in manage_campaign_cache: manage_campaign = manage_campaign_cache[ manage_campaign_id] elif manage_campaign_id is not None: try: manage_campaign = Campaign.objects_raw.filter( campaign_id=manage_campaign_id, source_type=2).first() manage_campaign_cache[ manage_campaign_id] = manage_campaign except Campaign.DoesNotExist: manage_campaign = None if manage_campaign is None: if self.verbose: print "----> Error: Cannot find internal Manage Campaign: " + str( api_campaign['name']) # Since advertisers are now granting us access to existing Twitter Campaigns, # the Manage Campaign ID won't exist in the Twitter Campaign Name. # For now, we won't flag these as sync errors. We will skip for now. # self._insert_sync_error({"errors":{"100": self.SYNC_ERROR_CODES['100'] + " - "+ str(api_campaign['name'])}}, m_account, "ManageCampaign") continue # Twitter Advertiser should match internal Manage Campaign advertiser if m_account.advertiser_id.advertiser_id != manage_campaign.advertiser_id.advertiser_id and api_campaign[ 'deleted'] is not True: sync_error = self.SYNC_ERROR_CODES['101'] + ": TW_CAMPAGIN: {tw_campaign} ({tw_campaign_id}), TW_ADVERTISER: {tw_advertiser} ({tw_advertiser_id}), MANAGE_ADVERTISER: {manage_advertiser} ({manage_advertiser_id})." \ .format(tw_campaign=str(api_campaign['name']), tw_campaign_id=str(base36_to_int(api_campaign['id'])), \ tw_advertiser=str(m_account.advertiser_id), tw_advertiser_id=str(m_account.advertiser_id.advertiser_id), \ manage_advertiser=str(manage_campaign.advertiser_id), manage_advertiser_id=str(manage_campaign.advertiser_id.advertiser_id)) if self.verbose: print "----> Error: " + sync_error self._insert_sync_error( {"errors": { "101": sync_error }}, m_account, "ManageCampaign") continue if self.verbose: print "---> (" + str( len(api_line_items)) + ") total Line Items" except KeyError: pass for api_line_item in api_line_items: try: if self.verbose: try: print "----> Syncing Line Item: " + str( api_line_item['name']) + " - (" + str( api_line_item['id']) + ")" except UnicodeEncodeError: pass line_item_id_int = base36_to_int( api_line_item['id']) api_line_item_targetings_data = TwitterTargeting.fetch_targeting( dict(account_id=m_account.tw_account_id, line_item_id=api_line_item['id']), True, oauth_token, oauth_secret) self._check_api_errors( api_line_item_targetings_data, m_account, "TwitterTargeting") api_line_item_targetings = [] if isinstance( api_line_item_targetings_data['data'], dict): api_line_item_targetings.append( api_line_item_targetings_data['data']) elif isinstance( api_line_item_targetings_data['data'], (list, tuple)): api_line_item_targetings = api_line_item_targetings_data[ 'data'] for api_line_item_targeting in api_line_item_targetings: if self.verbose: try: print "------> Syncing Line Item Targeting: " + str( api_line_item_targeting['name']) except UnicodeEncodeError: pass # Line Item Promoted Tweets api_line_item_promoted_tweets_data = TwitterPromotedTweet.fetch_promoted_tweet( dict(account_id=m_account.tw_account_id, line_item_id=api_line_item['id'], os_platform=os_platform), True, oauth_token, oauth_secret) self._check_api_errors( api_line_item_promoted_tweets_data, m_account, "TwitterPromotedTweet") api_line_item_promoted_tweets = [] if isinstance( api_line_item_promoted_tweets_data['data'], dict): api_line_item_promoted_tweets.append( api_line_item_promoted_tweets_data['data']) elif isinstance( api_line_item_promoted_tweets_data['data'], (list, tuple)): api_line_item_promoted_tweets = api_line_item_promoted_tweets_data[ 'data'] for api_line_item_promoted_tweet in api_line_item_promoted_tweets: if self.verbose: print "------> Syncing Line Item Promoted Tweet: " + str( api_line_item_promoted_tweet[ 'tweet_id']) # Get Rev Map if self.verbose: print "--> Sync Revmap Manage Campaign: " + str( manage_campaign) if manage_campaign is not None: manage_campaign_rev_map = TwitterRevmap.objects_raw.filter( campaign_id=manage_campaign, tw_campaign_id=0, tw_line_item_id=0).first() if manage_campaign_rev_map is not None: manage_campaign_opt_type = manage_campaign_rev_map.opt_type manage_campaign_opt_value = manage_campaign_rev_map.opt_value tw_campaign_rev_map = None if manage_campaign_opt_type is not None and manage_campaign_opt_value is not None: try: tw_line_item = TwitterLineItem.objects_raw.get( tw_campaign_id=campaign_id_int, tw_line_item_id=line_item_id_int ) if tw_line_item: tw_campaign_rev_map = TwitterRevmap.objects_raw.get( campaign_id=manage_campaign, tw_campaign_id=tw_line_item .tw_campaign_id, tw_line_item_id=tw_line_item ) except TwitterLineItem.DoesNotExist: tw_campaign_rev_map = None except TwitterRevmap.DoesNotExist: tw_campaign_rev_map = TwitterRevmap( campaign_id=manage_campaign, tw_campaign_id=tw_line_item. tw_campaign_id, tw_line_item_id=tw_line_item) if tw_campaign_rev_map is not None: tw_campaign_rev_map.opt_type = manage_campaign_opt_type tw_campaign_rev_map.opt_value = manage_campaign_opt_value tw_campaign_rev_map.save_raw() if self.verbose: print "-" * 50 except KeyError: pass if self.verbose: print "+" * 100 # Fetch all Manage Twitter Campaigns owned by Advertiser and sync Manage Campaign status manage_campaigns = Campaign.objects_raw.filter( advertiser_id=m_account.advertiser_id, source_type=2) for manage_campaign in manage_campaigns: # Find any active Twitter Campaigns tw_campaigns = TwitterCampaign.objects_raw.filter( campaign_id=manage_campaign.campaign_id, status='enabled') if tw_campaigns is not None and manage_campaign.status != 'enabled': manage_campaign.status = 'enabled' manage_campaign.save_raw() elif tw_campaigns is None and manage_campaign.status != 'paused': manage_campaign.status = 'paused' manage_campaign.save_raw() if self.verbose: print "--> Setting Manage Campaign status - " + str( manage_campaign) + ": " + str( manage_campaign.status) if self.verbose: print "*" * 150 # Return Sync Result end_time = datetime.now() if self.verbose: print 'Sync Script Duration: {}'.format(end_time - start_time) if self.sync_errors: send_twitter_sync_error_email( {"data": json.dumps(self.sync_errors)}) print { 'error': True, 'code': json.dumps(self.sync_errors), 'message': 'Twitter API Errors' } else: sql = "REPLACE INTO job_status SET job_name='twitter_sync', job_type='twitter', last_finished=NOW(), threshold=120" cursor = connection.cursor() try: cursor.execute(sql) if settings.TW_SYNC_ALERT: send_twitter_email( 'Twitter Sync Success', 'Twitter Sync Success. Script Duration: {}'.format( end_time - start_time)) print {'error': False, 'code': 200, 'message': 'OK'} except: print { 'error': True, 'message': 'Twitter synced but cannot add entry to job_status table' } finally: cursor.close()
def create(self, request, *args, **kwargs): data = copy(request.data) data['paused'] = data['status'] != 'enabled' targetings = data['targeting_obj'] #calc bulk values products = [] def append_product_vals(vals): temp = [] for v in vals: if v['val']: temp.append(v['val']) if temp: products.append(temp) append_product_vals(targetings.get('app_categories', [])) if data.get('target_each_country') and targetings.get('location'): products.append(targetings['location']) append_product_vals(targetings.get('interests', [])) if not data.get('separate_keyword_follower'): append_product_vals(targetings.get('handles', [])) append_product_vals(targetings.get('keywords', [])) products = list(itertools.product(*products)) else: temp = copy(products) append_product_vals(targetings.get('handles', [])) _products = list(itertools.product(*products)) products = temp append_product_vals(targetings.get('keywords', [])) products = _products + list(itertools.product(*products)) targeting_data = [] line_items_data = [] base_line_item_data = { 'paused': data['paused'], 'name': data.get('name'), 'start_time': data.get('start_time'), 'end_time': data.get('end_time'), 'campaign_id': int_to_base36(data.get('campaign_id')), 'bid_amount_local_micro': data.get('bid_amount_local_micro') } _index = 0 safe_targeting_fields = ( 'os_version', 'device', 'carriers', 'included_tailored_audience', 'included_mobile_tailored_audience', 'excluded_mobile_tailored_audience', 'excluded_mobile_tailored_audience', 'events', ) for p in products: temp = [] temp.append(p) for f in safe_targeting_fields: if targetings.get(f): temp.append(targetings[f]) if not data.get('target_each_country') and targetings['location']: temp.append(targetings['location']) temp = flatten(temp) # check wi-fi targeting if data.get('wifi_only'): temp.append({ 'targeting_value': 1, 'tw_targeting_id': '', 'tw_targeting_type': 5 }) # check platform targeting flag = True # platform targeting should be added for l in temp: if l['tw_targeting_type'] in [ 4, 16 ]: # if device or min_verison is there flag = False break if flag: temp.append({ 'targeting_value': '0' if targetings['os'] == 'iOS' else '1', 'tw_targeting_type': 3, 'tw_targeting_id': '' }) # get location targetings location_targetings = [] for l in temp: if l['tw_targeting_type'] == 2: location_targetings.append(l) if len(location_targetings) == 1: # set tv targeting location_id = location_targetings[0]['tw_targeting_id'] tv = targetings['tv'].get(location_id) if tv: temp.append(tv['shows']) temp.append(tv['channels']) temp.append(tv['genres']) # set behavior targeting behavior = targetings['behaviors'].get(location_id) if behavior: temp.append(behavior['vals']) # set line item data line_item_data = copy(base_line_item_data) line_item_name = '%s_' % line_item_data['name'] if location_targetings: line_item_name += TwitterLocation.objects_raw.get( tw_targeting_id=location_targetings[0] ['tw_targeting_id']).country_code3 _index += 1 line_item_name = '%s_%s_%s' % (line_item_name, targetings['os'], _index) line_item_data['name'] = line_item_name line_items_data.append(line_item_data) temp = flatten(temp) for t in temp: tt = copy(t) tt['name'] = line_item_name targeting_data.append(tt) # create batch line items account_id = data.get('tw_account_id') cpi_target_goal = data.get('cpi_target_goal') line_items_res = TwitterLineItem.batch_create(line_items_data, account_id) if line_items_res['success']: for line_item_res in line_items_res['data']: tw_line_item_id = base36_to_int(line_item_res['id']) line_item_name = line_item_res['name'] for t in targeting_data: if t['name'] == line_item_name: t['tw_line_item_id'] = tw_line_item_id tweets_data = { 'line_item_id': tw_line_item_id, 'tweet_ids': ','.join(data.get('tweet_ids', [])) } promoted_res = TwitterPromotedTweet.set_promoted_tweet( tweets_data, account_id) if not promoted_res['success']: return Response(dict( message= "Associating promotable tweets with line item \"%s\" was failed..." % line_item_name), status=status.HTTP_400_BAD_REQUEST) line_item = TwitterLineItem.objects_raw.get(pk=tw_line_item_id) revmap, created = TwitterRevmap.objects_raw.get_or_create( campaign_id=line_item.tw_campaign_id.campaign_id, tw_campaign_id=line_item.tw_campaign_id.pk, tw_line_item_id=line_item.pk) revmap.opt_type = 'install' revmap.opt_value = cpi_target_goal revmap.save() # set batch targetings targetings_res = TwitterTargeting.set_targeting( targeting_data, account_id) if not targetings_res['success']: return Response( dict(message=targetings_res['error']['messages']), status=status.HTTP_400_BAD_REQUEST) else: return Response(dict(message=line_items_res.get('error') or line_items_res.get('message')), status=status.HTTP_400_BAD_REQUEST) return Response(dict(status='ok'))
def _generate_campaign_explode_by_adgroup(self): campaign_data = {} campaign_data['account_id'] = self.account_id campaign_data['daily_budget_amount_local_micro'] = \ long(round(float(self.data['daily_budget_amount_local_micro']), 2) * 1000000) campaign_data['funding_instrument_id'] = self.data[ 'funding_instrument'] campaign_data['name'] = self.rows[0][2] campaign_data['paused'] = self.rows[0][5] == 'PAUSED' campaign_data['start_time'] = self.data.get( 'flight_start_date', datetime.now( pytz.timezone('US/Central')).strftime('%Y-%m-%dT%H:%M:%S%z')) campaign_data['end_time'] = self.data.get('flight_end_date') campaign_data['total_budget_amount_local_micro'] = \ long(round(float(self.data.get('total_budget_amount_local_micro') or 0), 2) * 1000000) campaign_res = TwitterCampaign.create(campaign_data) if campaign_res['success']: tw_campaign_id = base36_to_int(campaign_res['data']['id']) tw_campaign = TwitterCampaign.objects_raw.filter( pk=tw_campaign_id).first() if tw_campaign: self.res_json = TwitterCampaignSerializer(tw_campaign).data line_items = [] targeting_data = [] for r in self.rows: line_item_data, targetings = self._get_line_item_and_targeting( r, campaign_data, campaign_res['data']['id']) line_items.append(line_item_data) targeting_data += targetings # create batch line items line_items_res = TwitterLineItem.batch_create( line_items, self.account_id) if line_items_res['success']: for line_item_res in line_items_res['data']: tw_line_item_id = base36_to_int(line_item_res['id']) line_item_name = line_item_res['name'] for t in targeting_data: if t['name'] == line_item_name: t['tw_line_item_id'] = tw_line_item_id tweets_data = { 'line_item_id': tw_line_item_id, 'tweet_ids': ','.join(self.data.get('tweet_ids', [])) } promoted_res = TwitterPromotedTweet.set_promoted_tweet( tweets_data, self.account_id) if not promoted_res['success']: return False, "Associating promotable tweets with line item \"%s\" was failed..." % line_item_name line_item = TwitterLineItem.objects_raw.get( pk=tw_line_item_id) revmap, created = TwitterRevmap.objects_raw.get_or_create( **{ k: v for k, v in ( ('campaign_id', line_item.tw_campaign_id.campaign_id), ('tw_campaign_id', line_item.tw_campaign_id), ('tw_line_item_id', line_item)) if v }) revmap.opt_type = 'install' revmap.opt_value = self.cpi_target_goal revmap.save() self._revise_targeting_data_with_line_items_res( line_items_res, targeting_data) # set batch targetings targetings_res = TwitterTargeting.set_targeting( targeting_data, self.account_id) if not targetings_res['success']: raise Exception(targetings_res['error']['messages']) else: raise Exception( line_items_res.get('error', {}).get('messages', '')) else: raise Exception(campaign_res['message'])
def post(self, request, *args, **kwargs): try: data = request.DATA tw_account_id = data['tw_account_id'] diff_account = data['different_ads_account'] create_new_campaign = data['create_new_campaign'] tweet_ids = data['tweet_ids'] tw_line_item_ids = data.get('tw_line_item_ids', []) objective = data.get('objective') daily_budget_amount_local_micro = \ long(round(float(data.get('daily_budget_amount_local_micro', 0)), 2) \ * 1000000) clone_campaigns = False campaigns_daily_budgets = {} if data['type'] == 'tw_campaigns_clone': clone_campaigns = True tw_line_item_ids = [t.tw_line_item_id \ for t in TwitterLineItem.objects.filter( tw_campaign_id__tw_campaign_id__in=data['tw_campaign_ids'])] tw_account = TwitterAccount.objects.get( tw_account_id=tw_account_id) oauth_token = tw_account.tw_twitter_user_id.oauth_token \ or settings.TW_ACCESS_TOKEN oauth_token_secret = tw_account.tw_twitter_user_id.oauth_secret \ or settings.TW_ACCESS_SECRET tw_campaign_id_to_line_items = {} campaign_data = {} # active line item count in selected twitter account active_line_item_count = TwitterLineItem.objects \ .filter( tw_campaign_id__tw_account_id=tw_account, status='enabled') \ .count() if create_new_campaign: # in case we create active line items if not data['status'] == 'PAUSED': if active_line_item_count + len(tw_line_item_ids) > 2000: return Response( dict(error="There should be less than 2000 active line" \ " items in one account."), status=status.HTTP_400_BAD_REQUEST) def _create_tw_campaign(name): campaign_data['account_id'] = tw_account_id campaign_data['daily_budget_amount_local_micro'] = \ daily_budget_amount_local_micro if isinstance(data['funding_instrument_id'], (int, long)): campaign_data['funding_instrument_id'] = \ int_to_base36(data['funding_instrument_id']) else: campaign_data['funding_instrument_id'] = \ data['funding_instrument_id'] campaign_data['name'] = name campaign_data['paused'] = data['status'] == 'PAUSED' campaign_data['start_time'] = data.get( 'flight_start_date', datetime.now(pytz.timezone('US/Central')) \ .strftime('%Y-%m-%dT%H:%M:%S%z')) campaign_data['end_time'] = data.get('flight_end_date') campaign_data['total_budget_amount_local_micro'] = \ long( round( float(data.get('total_budget_amount_local_micro') or 0), 2 ) * 1000000) campaign_res = TwitterCampaign.create_update_campaign( campaign_data, oauth_token, oauth_token_secret) if not campaign_res['success']: raise Exception( campaign_res.get('error') or campaign_res.get('message')) return campaign_res['data']['id'] if clone_campaigns: for tw_campaign in TwitterCampaign.objects.filter( tw_campaign_id__in=data['tw_campaign_ids']).all(): tw_campaign_id = _create_tw_campaign( "%s{%s}" % (re.sub(r'{.*}', '', tw_campaign.name), data['campaign_id'])) tw_campaign_id_to_line_items[tw_campaign_id] = \ TwitterLineItem.objects \ .filter(tw_campaign_id=tw_campaign.tw_campaign_id).values() else: tw_campaign_id = _create_tw_campaign( "%s {%s}" % (data['campaign'], data['campaign_id'])) tw_campaign_id_to_line_items[tw_campaign_id] = \ TwitterLineItem.objects \ .filter(tw_line_item_id__in=tw_line_item_ids).values() else: cloned_active_line_item_count = TwitterLineItem.objects.filter( tw_line_item_id__in=tw_line_item_ids, status='enabled').count() if (len(data['tw_campaign_ids']) * cloned_active_line_item_count \ + active_line_item_count > 2000): return Response( dict(error="There should be less than 200 active line" \ " items in one account."), status=status.HTTP_400_BAD_REQUEST) # newly created line item daily budget should be greater than # it's campaign daily budget so we need to campaigns' daily # budgets for them for tc in TwitterCampaign.objects \ .filter(tw_campaign_id__in=data['tw_campaign_ids']): campaigns_daily_budgets[int_to_base36(tc.tw_campaign_id)] = \ tc.daily_budget_amount_local_micro for campaign_id in data['tw_campaign_ids']: tw_campaign_id_to_line_items[int_to_base36(int(campaign_id))] = \ TwitterLineItem.objects \ .filter(tw_line_item_id__in=tw_line_item_ids).values() # make line item data line_items_data = [] name_to_ids = {} success_line_item_count = 0 ignored_line_item_count = 0 ignored_targetings = [] for (campaign_id, line_items) in tw_campaign_id_to_line_items.iteritems(): for item in line_items: item['campaign_id'] = campaign_id if objective: item['objective'] = objective del item['bid_unit'] del item['charge_by'] del item['optimization'] # set line item daily budget to it's campaign's one if create_new_campaign: item['bid_amount_local_micro'] = \ min( daily_budget_amount_local_micro, item['bid_amount_local_micro'] ) else: item['bid_amount_local_micro'] = \ min( campaigns_daily_budgets[campaign_id], item['bid_amount_local_micro'] ) item['placements'] = json.loads(item['placements']) item['categories'] = json.loads(item['categories']) item['tracking_tags'] = json.loads(item['tracking_tags']) item['placements'] = item['placements'] \ if item['placements'] else None item['categories'] = item['categories'] \ if item['categories'] else None item['tracking_tags'] = item['tracking_tags'] \ if item['tracking_tags'] else None if 'PUBLISHER_NETWORK' in item['placements']: ignored_line_item_count += 1 continue if create_new_campaign: item['start_time'] = campaign_data.get('start_time') item['end_time'] = campaign_data.get('end_time') item['paused'] = campaign_data.get('paused') else: campaign = \ TwitterCampaign.objects.get(pk=base36_to_int(campaign_id)) if campaign.start_time: item['start_time'] = \ campaign.start_time.strftime('%Y-%m-%dT%H:%M:%S%z') if campaign.end_time: item['end_time'] = \ campaign.end_time.strftime('%Y-%m-%dT%H:%M:%S%z') else: item['end_time'] = None item['paused'] = campaign.status != 'enabled' name_to_ids[item['name']] = item['tw_line_item_id'] success_line_item_count += 1 line_items_data.append(item) if not line_items_data: return Response(dict( error="All line items are TAP enabled so can't clone."), status=status.HTTP_400_BAD_REQUEST) line_items_res = TwitterLineItem.batch_create( line_items_data, tw_account_id, oauth_token, oauth_token_secret) if not line_items_res['success']: return Response(dict(error=line_items_res.get('error') or line_items_res.get('message')), status=status.HTTP_400_BAD_REQUEST) line_items_data = line_items_res['data'] targeting_data = [] EXCLUDE_TARGETING_TYPES = (16, 18) if not create_new_campaign: EXCLUDE_TARGETING_TYPES = (16, ) for item in line_items_data: # set promotable tweets line_item_id = base36_to_int(item['id']) # if cloning line items to existing tw campaign, # tweets are not provided. So original tweet ids from origin # line item should be fetched if not create_new_campaign: tw_tweet_ids = TwitterPromotedTweet.objects \ .filter(tw_line_item_id=name_to_ids[item['name']]) \ .values('tw_tweet_id') tweet_ids = [str(r['tw_tweet_id']) for r in tw_tweet_ids] tweet_data = dict(line_item_id=line_item_id, tweet_ids=','.join(tweet_ids)) tweet_res = TwitterPromotedTweet \ .set_promoted_tweet(tweet_data, tw_account_id) if not tweet_res['success']: return Response( dict(error=tweet_res.get('error') or \ tweet_res.get('message') or \ "Associating promotable tweets with" \ " line item failed!"), status=status.HTTP_400_BAD_REQUEST) # making targeting data targetings = TwitterTargeting.objects \ .filter(tw_line_item_id=name_to_ids[item['name']]) \ .exclude(tw_targeting_type__in=EXCLUDE_TARGETING_TYPES) \ .values() for t in targetings: t['tw_line_item_id'] = line_item_id del t['tw_criteria_id'] if not t['tw_targeting_type']: ignored_targetings.append(t) continue # tailored audience if t['tw_targeting_type'] == 18: if not t['targeting_params'] or \ 'EXCLUDED_' in t['targeting_params']: t['operator_type'] = 'NE' else: t['operator_type'] = 'EQ' targeting_data.append(t) # pick lowest platform version version_targeting = TwitterTargeting.objects.filter( tw_line_item_id=name_to_ids[item['name']], tw_targeting_type=16).order_by('tw_targeting_id').first() if version_targeting: targeting_data.append( dict( tw_line_item_id=line_item_id, tw_targeting_type=16, tw_targeting_id=version_targeting.tw_targeting_id)) # tailored auidence part if create_new_campaign: audience_fields = [ 'excluded_tailored_audience', 'excluded_mobile_tailored_audience', 'included_tailored_audience', 'included_mobile_tailored_audience' ] for field in audience_fields: if data.get(field): for audience in data[field]: audience['tw_line_item_id'] = line_item_id targeting_data.append(audience) targeting_res = TwitterTargeting.set_targeting( targeting_data, tw_account_id, oauth_token, oauth_token_secret) if not targeting_res['success']: return Response(dict(error=targeting_res.get('error') or targeting_res.get('message')), status=status.HTTP_400_BAD_REQUEST) return Response( data=dict(success=True, success_line_item_count=success_line_item_count, ignored_targetings=ignored_targetings, ignored_line_item_count=ignored_line_item_count)) except Exception as e: traceback.print_exc() return Response(dict(error=str(e)), status=status.HTTP_400_BAD_REQUEST)