예제 #1
0
 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})
예제 #6
0
    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
예제 #7
0
    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()
예제 #8
0
    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'])
예제 #10
0
    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)