Example #1
0
def new(request):
    """
    Returns a new campaign
    """
    client = Client(settings.SOCIAL_AUTH_TWITTER_KEY,
                    settings.SOCIAL_AUTH_TWITTER_SECRET,
                    settings.TWITTER_ACCESS_TOKEN,
                    settings.TWITTER_ACCESS_TOKEN_SECRET)
    account_id = request.GET.get("account_id", "")
    campaign_name = request.GET.get("campaign", "")
    daily_budget = request.GET.get("daily_budget", "")
    account = client.accounts(account_id)
    # create your campaign
    json_data = {}
    try:
        campaign = Campaign(account)
        campaign.funding_instrument_id = account.funding_instruments().next(
        ).id
        campaign.daily_budget_amount_local_micro = int(daily_budget) * 1000
        campaign.name = campaign_name
        campaign.paused = True
        campaign.start_time = datetime.datetime.utcnow()
        campaign.save()
        json_data = {
            "valid": True,
            "account_id": account_id,
            "campaign_name": campaign_name,
            "campaign_id": campaign.id
        }
    except Error as e:
        json_data["response"] = e.details
        json_data["valid"] = False
        # passing as we send the json_data
        pass
    return HttpResponse(json.dumps(json_data), content_type="application/json")
Example #2
0
def pushEmails2Twitter(hashedEmails,twCred):

    from twitter_ads.client import Client
    from twitter_ads.audience import TailoredAudience
    from twitter_ads.enum import TA_LIST_TYPES, TA_OPERATIONS

    CONSUMER_KEY = 'your consumer key'
    CONSUMER_SECRET = 'your consumer secret'
    ACCESS_TOKEN = 'access token'
    ACCESS_TOKEN_SECRET = 'access token secret'
    ACCOUNT_ID = 'account id'

    # initialize the client
    client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

    # load the advertiser account instance
    account = client.accounts(ACCOUNT_ID)

    # create a new tailored audience
    audience = TailoredAudience.create(account, '/path/to/file', 'my list', TA_LIST_TYPES.EMAIL)

    # check the processing status
    audience.status()

    # update the tailored audience
    audience.update('/path/to/file', TA_LIST_TYPES.TWITTER_ID, TA_OPERATIONS.REMOVE)
    audience.update('/path/to/file', TA_LIST_TYPES.PHONE_NUMBER, TA_OPERATIONS.ADD)

    # delete the tailored audience
    audience.delete()

    # add users to the account's global opt-out list
    TailoredAudience.opt_out(account, '/path/to/file', TA_OPERATIONS.HANDLE)
Example #3
0
def new(request):
    """
    Returns a new campaign
    """
    client = Client(
        settings.SOCIAL_AUTH_TWITTER_KEY,
        settings.SOCIAL_AUTH_TWITTER_SECRET,
        settings.TWITTER_ACCESS_TOKEN,
        settings.TWITTER_ACCESS_TOKEN_SECRET)
    account_id = request.GET.get("account_id", "")
    campaign_name = request.GET.get("campaign", "")
    daily_budget = request.GET.get("daily_budget", "")
    account = client.accounts(account_id)
    # create your campaign
    json_data = {}
    try:
        campaign = Campaign(account)
        campaign.funding_instrument_id = account.funding_instruments().next().id
        campaign.daily_budget_amount_local_micro = int(daily_budget) * 1000
        campaign.name = campaign_name
        campaign.paused = True
        campaign.start_time = datetime.datetime.utcnow()
        campaign.save()
        json_data = {
            "valid": True,
            "account_id": account_id,
            "campaign_name": campaign_name,
            "campaign_id": campaign.id}
    except Error as e:
        json_data["response"] = e.details
        json_data["valid"] = False
        # passing as we send the json_data
        pass
    return HttpResponse(json.dumps(json_data), content_type="application/json")
def json_handler(request):
    """
    Returns json_data {"campaigns": [campaign_list} for given request
    """
    client = Client(settings.SOCIAL_AUTH_TWITTER_KEY,
                    settings.SOCIAL_AUTH_TWITTER_SECRET,
                    settings.TWITTER_ACCESS_TOKEN,
                    settings.TWITTER_ACCESS_TOKEN_SECRET)
    account_id = request.GET.get("account_id", "")
    campaign_id = request.GET.get("campaign_id", "")
    account = client.accounts(account_id)
    # TODO: Link to Ads API Docs for LineItem.rst
    line_items = account.line_items(None, campaign_ids=campaign_id)
    line_item_list = []
    for line_item in line_items:
        name = line_item.name
        identifier = line_item.id
        objective = line_item.objective
        bid_amount = line_item.bid_amount_local_micro
        # Sometimes Bid Amount is None
        if bid_amount is not None:
            bid_amount = bid_amount / 10000
        line_item_list.append({
            "name": name,
            "id": identifier,
            "objective": objective,
            "bid_amount": bid_amount
        })
    return HttpResponse(json.dumps({
        "account_id": account_id,
        "campaign_id": campaign_id,
        "line_items": line_item_list
    }),
                        content_type="application/json")
def new_targeting(request):
    """
    Creates a new
    """
    line_item_id = request.GET.get("line_item_id", "")
    account_id = request.GET.get("account_id", "")
    targeting_value = request.GET.get("targeting_value")
    targeting_type = "BEHAVIOR_EXPANDED"
    json_data = {}
    try:
        client = Client(settings.SOCIAL_AUTH_TWITTER_KEY,
                        settings.SOCIAL_AUTH_TWITTER_SECRET,
                        settings.TWITTER_ACCESS_TOKEN,
                        settings.TWITTER_ACCESS_TOKEN_SECRET)
        account = client.accounts(account_id)
        targeting_criteria = TargetingCriteria(account)
        targeting_criteria.line_item_id = line_item_id
        targeting_criteria.targeting_type = targeting_type
        targeting_criteria.targeting_value = targeting_value
        if targeting_value == "TAILORED_AUDIENCE":
            targeting_criteria.tailored_audience_type = "FLEXIBLE"
        targeting_criteria.save()
        json_data = {
            "valid": True,
            "account_id": account_id,
            "line_item_id": line_item_id,
            "targeting_value": targeting_value
        }
    except Error as e:
        json_data["response"] = e.details
        json_data["valid"] = False
        # passing to push the json_data to the browser
        pass
    return HttpResponse(json.dumps(json_data), content_type="application/json")
Example #6
0
def json_handler(request):
    """
    Returns json_data {"campaigns": [campaign_list} for given request
    """
    client = Client(
        settings.SOCIAL_AUTH_TWITTER_KEY,
        settings.SOCIAL_AUTH_TWITTER_SECRET,
        settings.TWITTER_ACCESS_TOKEN,
        settings.TWITTER_ACCESS_TOKEN_SECRET)
    account_id = request.GET.get("account_id", "")
    campaign_id = request.GET.get("campaign_id", "")
    account = client.accounts(account_id)
    # TODO: Link to Ads API Docs for LineItem.rst
    line_items = account.line_items(None, campaign_ids=campaign_id)
    line_item_list = []
    for line_item in line_items:
        name = line_item.name
        identifier = line_item.id
        objective = line_item.objective
        bid_amount = line_item.bid_amount_local_micro
        # Sometimes Bid Amount is None
        if bid_amount is not None:
            bid_amount = bid_amount / 10000
        line_item_list.append({"name": name,
                               "id": identifier,
                               "objective": objective,
                               "bid_amount": bid_amount})
    return HttpResponse(
        json.dumps(
            {
                "account_id": account_id,
                "campaign_id": campaign_id,
                "line_items": line_item_list}),
        content_type="application/json")
Example #7
0
def new_targeting(request):
    """
    Creates a new
    """
    line_item_id = request.GET.get("line_item_id", "")
    account_id = request.GET.get("account_id", "")
    targeting_value = request.GET.get("targeting_value")
    targeting_type = "BEHAVIOR_EXPANDED"
    json_data = {}
    try:
        client = Client(
            settings.SOCIAL_AUTH_TWITTER_KEY,
            settings.SOCIAL_AUTH_TWITTER_SECRET,
            settings.TWITTER_ACCESS_TOKEN,
            settings.TWITTER_ACCESS_TOKEN_SECRET)
        account = client.accounts(account_id)
        targeting_criteria = TargetingCriteria(account)
        targeting_criteria.line_item_id = line_item_id
        targeting_criteria.targeting_type = targeting_type
        targeting_criteria.targeting_value = targeting_value
        if targeting_value == "TAILORED_AUDIENCE":
            targeting_criteria.tailored_audience_type = "FLEXIBLE"
        targeting_criteria.save()
        json_data = {
            "valid": True,
            "account_id": account_id,
            "line_item_id": line_item_id,
            "targeting_value": targeting_value}
    except Error as e:
        json_data["response"] = e.details
        json_data["valid"] = False
        # passing to push the json_data to the browser
        pass
    return HttpResponse(json.dumps(json_data), content_type="application/json")
Example #8
0
def test_accounts_with_no_id():
    responses.add(responses.GET,
                  with_resource('/1/accounts'),
                  body=with_fixture('accounts_all'),
                  content_type='application/json')

    client = Client(characters(40), characters(40), characters(40),
                    characters(40))

    cursor = client.accounts()
    assert cursor is not None
    assert isinstance(cursor, Cursor)
    assert cursor.count == 5
Example #9
0
def test_accounts_with_id():
    responses.add(responses.GET,
                  with_resource('/1/accounts/2iqph'),
                  body=with_fixture('accounts_load'),
                  content_type='application/json')

    client = Client(characters(40), characters(40), characters(40),
                    characters(40))

    account = client.accounts('2iqph')
    assert account is not None
    assert isinstance(account, Account)
    assert account.id == '2iqph'
Example #10
0
    def fetch_accounts(self, data, oauth_token=settings.TW_ACCESS_TOKEN, oauth_token_secret=settings.TW_ACCESS_SECRET):
        res = {}
        account_id = data.get('account_id')

        if isinstance(account_id,(int,long)):
            account_id = int_to_base36(account_id)

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET, oauth_token, oauth_token_secret)
        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX

        try:
            account = client.accounts(account_id)
            resource = '/{api_version}/accounts/{account_id}'.format(api_version=settings.TW_API_VERSION, account_id=account_id)
            response = Request(client, 'get', resource).perform()

            if response.headers['x-rate-limit-remaining'] == "0" and settings.TW_RATE_LIMIT_ALERT:
                send_twitter_alert_email({"account_id": account_id, "endpoint": resource})

            res['data'] = response.body['data']
            res['success'] = True

        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success': False,
                'message': e.details[0]['message'] if e.details and e.details[0] and e.details[0]['message'] else '',
                'errors': { str(code): True } if code else {}
            }
        except Exception as e:
            res = {
                'data': {},
                'success': False,
                'message': str(e)
            }
        return res
Example #11
0
    def get(self, request):
        q = request.query_params.get('q')
        tw_user_id = request.query_params.get('tw_user_id')
        tw_user = TwitterUser.objects_raw.get(pk=tw_user_id)
        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        tw_user.oauth_token, tw_user.oauth_secret)
        accounts = client.accounts()
        results = []
        for a in accounts:
            tw_account = TwitterAccount.objects_raw.filter(
                tw_account_id=int(a.id, 36)).first()
            if not tw_account and (not q or (q and
                                             (q in a.name or q in a.id))):
                results.append(dict(name=a.name, id=a.id))

        return Response(dict(results=results))
def test_accounts_with_no_id():
    responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts'),
                                 body=with_fixture('accounts_all'),
                                 content_type='application/json')

    client = Client(
        characters(40),
        characters(40),
        characters(40),
        characters(40)
    )

    cursor = client.accounts()
    assert cursor is not None
    assert isinstance(cursor, Cursor)
    assert cursor.count == 5
def test_accounts_with_id():
    responses.add(responses.GET, with_resource('/' + API_VERSION + '/accounts/2iqph'),
                                 body=with_fixture('accounts_load'),
                                 content_type='application/json')

    client = Client(
        characters(40),
        characters(40),
        characters(40),
        characters(40)
    )

    account = client.accounts('2iqph')
    assert account is not None
    assert isinstance(account, Account)
    assert account.id == '2iqph'
Example #14
0
def json_handler(request):
    """
    Returns json_data {"accounts": [account_list]} for given request
    """
    client = Client(settings.SOCIAL_AUTH_TWITTER_KEY,
                    settings.SOCIAL_AUTH_TWITTER_SECRET,
                    settings.TWITTER_ACCESS_TOKEN,
                    settings.TWITTER_ACCESS_TOKEN_SECRET)
    accounts = client.accounts()
    # TODO: Link to Ads API Docs for Account.request
    account_list = []
    for account in accounts:
        name = account.name
        identifier = account.id
        account_list.append({"name": name, "id": identifier})
    return HttpResponse(json.dumps({"accounts": account_list}),
                        content_type="application/json")
Example #15
0
def json_handler(request):
    """
    Returns json_data {"accounts": [account_list]} for given request
    """
    client = Client(
        settings.SOCIAL_AUTH_TWITTER_KEY,
        settings.SOCIAL_AUTH_TWITTER_SECRET,
        settings.TWITTER_ACCESS_TOKEN,
        settings.TWITTER_ACCESS_TOKEN_SECRET)
    accounts = client.accounts()
    # TODO: Link to Ads API Docs for Account.request
    account_list = []
    for account in accounts:
        name = account.name
        identifier = account.id
        account_list.append({"name": name, "id": identifier})
    return HttpResponse(json.dumps(
        {"accounts": account_list}), content_type="application/json")
Example #16
0
def json_handler(request):
    """
    Returns json_data {"campaigns": [campaign_list} for given request
    """

    client = Client(
        settings.SOCIAL_AUTH_TWITTER_KEY,
        settings.SOCIAL_AUTH_TWITTER_SECRET,
        settings.TWITTER_ACCESS_TOKEN,
        settings.TWITTER_ACCESS_TOKEN_SECRET)
    account_id = request.GET.get("account_id", "")
    account = client.accounts(account_id)
    # TODO: Link to Ads API Docs for Campaign.rst
    campaigns = account.campaigns()
    campaign_list = []
    for campaign in campaigns:
        name = campaign.name
        identifier = campaign.id
        campaign_list.append({"name": name, "id": identifier})
    return HttpResponse(json.dumps(
        {"account_id": account_id, "campaigns": campaign_list}), content_type="application/json")
def new(request):
    """
    Returns a new line item
    """
    client = Client(settings.SOCIAL_AUTH_TWITTER_KEY,
                    settings.SOCIAL_AUTH_TWITTER_SECRET,
                    settings.TWITTER_ACCESS_TOKEN,
                    settings.TWITTER_ACCESS_TOKEN_SECRET)
    account_id = request.GET.get("account_id", "")
    campaign_id = request.GET.get("campaign_id", "")
    campaign_name = request.GET.get("name", "")
    budget = request.GET.get("budget", "")
    account_id = request.GET.get("account_id", "")
    name = request.GET.get("name", "")
    bid_amount = request.GET.get("bid_amount", "")

    json_data = {}
    try:
        account = client.accounts(account_id)
        # create your campaign
        line_item = LineItem(account)
        line_item.campaign_id = campaign_id
        line_item.name = name
        line_item.product_type = PRODUCT.PROMOTED_TWEETS
        line_item.placements = [PLACEMENT.ALL_ON_TWITTER]
        line_item.objective = OBJECTIVE.TWEET_ENGAGEMENTS
        line_item.bid_amount_local_micro = int(bid_amount) * 1000
        line_item.paused = True
        line_item.save()
        json_data = {
            "account_id": account_id,
            "campaign_name": campaign_name,
            "campaign_id": campaign_id
        }
    except Error as e:
        json_data["response"] = e.details
        json_data["valid"] = False

        pass
    return HttpResponse(json.dumps(json_data), content_type="application/json")
Example #18
0
def new(request):
    """
    Returns a new line item
    """
    client = Client(
        settings.SOCIAL_AUTH_TWITTER_KEY,
        settings.SOCIAL_AUTH_TWITTER_SECRET,
        settings.TWITTER_ACCESS_TOKEN,
        settings.TWITTER_ACCESS_TOKEN_SECRET)
    account_id = request.GET.get("account_id", "")
    campaign_id = request.GET.get("campaign_id", "")
    campaign_name = request.GET.get("name", "")
    budget = request.GET.get("budget", "")
    account_id = request.GET.get("account_id", "")
    name = request.GET.get("name", "")
    bid_amount = request.GET.get("bid_amount", "")

    json_data = {}
    try:
        account = client.accounts(account_id)
        # create your campaign
        line_item = LineItem(account)
        line_item.campaign_id = campaign_id
        line_item.name = name
        line_item.product_type = PRODUCT.PROMOTED_TWEETS
        line_item.placements = [PLACEMENT.ALL_ON_TWITTER]
        line_item.objective = OBJECTIVE.TWEET_ENGAGEMENTS
        line_item.bid_amount_local_micro = int(bid_amount) * 1000
        line_item.paused = True
        line_item.save()
        json_data = {
            "account_id": account_id,
            "campaign_name": campaign_name,
            "campaign_id": campaign_id}
    except Error as e:
        json_data["response"] = e.details
        json_data["valid"] = False

        pass
    return HttpResponse(json.dumps(json_data), content_type="application/json")
Example #19
0
    def post(self, request):
        tw_user_id = request.data.get('tw_user_id')
        tw_user = TwitterUser.objects_raw.get(pk=tw_user_id)
        tw_account_id = request.data.get('tw_account_id')
        advertiser_id = request.data.get('advertiser_id')
        advertiser = Advertiser.objects_raw.get(pk=advertiser_id)
        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        tw_user.oauth_token, tw_user.oauth_secret)
        account = client.accounts(tw_account_id)
        users = account.promotable_users()
        user_info = None
        is_manage = False

        for u in users:
            if u.promotable_user_type == 'FULL':
                api = twitter.Api(consumer_key=settings.TW_CONSUMER_KEY,
                                  consumer_secret=settings.TW_CONSUMER_SECRET,
                                  access_token_key=tw_user.oauth_token,
                                  access_token_secret=tw_user.oauth_secret)
                # https://dev.twitter.com/rest/reference/get/users/show
                # https://api.twitter.com/1.1/users/show.json?screen_name=<user_id>
                user_info = api.GetUser(user_id=u.user_id)

        funding_instruments = account.funding_instruments()
        for f in funding_instruments:
            if not f.cancelled and f.id in settings.TW_MANAGE_FUNDING_INSTRUMENT_IDS:
                is_manage = True

        if user_info:
            tw_promotable_user, created = TwitterUser.objects_raw.get_or_create(
                tw_twitter_user_id=user_info.id, name=user_info.screen_name)
            TwitterAccount(tw_account_id=int(tw_account_id, 36),
                           promotable_user_id=tw_promotable_user,
                           name=account.name,
                           advertiser_id=advertiser,
                           tw_twitter_user_id=tw_user,
                           is_manage=is_manage).save()

        return Response({'status': 'ok'})
Example #20
0
def json_handler(request):
    """
    Returns json_data {"campaigns": [campaign_list} for given request
    """

    client = Client(settings.SOCIAL_AUTH_TWITTER_KEY,
                    settings.SOCIAL_AUTH_TWITTER_SECRET,
                    settings.TWITTER_ACCESS_TOKEN,
                    settings.TWITTER_ACCESS_TOKEN_SECRET)
    account_id = request.GET.get("account_id", "")
    account = client.accounts(account_id)
    # TODO: Link to Ads API Docs for Campaign.rst
    campaigns = account.campaigns()
    campaign_list = []
    for campaign in campaigns:
        name = campaign.name
        identifier = campaign.id
        campaign_list.append({"name": name, "id": identifier})
    return HttpResponse(json.dumps({
        "account_id": account_id,
        "campaigns": campaign_list
    }),
                        content_type="application/json")
Example #21
0
class TwitterReader(Reader):
    def __init__(
        self,
        consumer_key,
        consumer_secret,
        access_token,
        access_token_secret,
        account_id,
        report_type,
        entity,
        entity_attribute,
        granularity,
        metric_group,
        placement,
        segmentation_type,
        platform,
        country,
        start_date,
        end_date,
        add_request_date_to_report,
        date_range,
    ):
        # Authentication inputs
        self.client = Client(consumer_key, consumer_secret, access_token,
                             access_token_secret)
        self.account = self.client.accounts(account_id)

        # General inputs
        self.report_type = report_type
        self.entity = entity
        self.start_date, self.end_date = build_date_range(
            start_date, end_date, date_range)
        self.end_date = self.end_date + timedelta(days=1)
        self.add_request_date_to_report = add_request_date_to_report

        # Report inputs: ENTITY
        self.entity_attributes = list(entity_attribute)

        # Report inputs: ANALYTICS
        self.granularity = granularity
        self.metric_groups = list(metric_group)
        self.placement = placement
        self.segmentation_type = segmentation_type
        self.platform = platform
        self.country = country

        # Validate inputs
        self.validate_inputs()

    def validate_inputs(self):
        """
        Validate combination of input parameters (triggered in TwitterReader constructor).
        """

        self.validate_analytics_segmentation()
        self.validate_analytics_metric_groups()
        self.validate_analytics_entity()
        self.validate_reach_entity()
        self.validate_entity_attributes()

    def validate_analytics_segmentation(self):

        if self.report_type == "ANALYTICS":
            if self.segmentation_type in ["DEVICES", "PLATFORM VERSION"
                                          ] and not self.platform:
                raise ClickException("Please provide a value for 'platform'.")

            elif self.segmentation_type in [
                    "CITIES", "POSTAL_CODES", "REGION"
            ] and not self.country:
                raise ClickException("Please provide a value for 'country'.")

    def validate_analytics_metric_groups(self):

        if self.report_type == "ANALYTICS":

            if self.entity == "FUNDING_INSTRUMENT" and any([
                    metric_group not in ["ENGAGEMENT", "BILLING"]
                    for metric_group in self.metric_groups
            ]):
                raise ClickException(
                    "'FUNDING_INSTRUMENT' only accept the 'ENGAGEMENT' and 'BILLING' metric groups."
                )

            if "MOBILE_CONVERSION" in self.metric_groups and len(
                    self.metric_groups) > 1:
                raise ClickException(
                    "'MOBILE_CONVERSION' data should be requested separately.")

    def validate_analytics_entity(self):

        if self.report_type == "ANALYTICS":

            if self.entity == "CARD":
                raise ClickException(
                    f"'ANALYTICS' reports only accept following entities: {list(ENTITY_OBJECTS.keys())}."
                )

    def validate_reach_entity(self):

        if self.report_type == "REACH":

            if self.entity not in ["CAMPAIGN", "FUNDING_INSTRUMENT"]:
                raise ClickException(
                    "'REACH' reports only accept the following entities: CAMPAIGN, FUNDING_INSTRUMENT."
                )

    def validate_entity_attributes(self):

        if self.report_type == "ENTITY":

            if not all([
                    attr in ENTITY_ATTRIBUTES[self.entity]
                    for attr in self.entity_attributes
            ]):
                raise ClickException(
                    f"Available attributes for '{self.entity}' are: {ENTITY_ATTRIBUTES[self.entity]}"
                )

    def get_analytics_report(self, job_ids):
        """
        Get 'ANALYTICS' report through the 'Asynchronous Analytics' endpoint of Twitter Ads API.
        Documentation: https://developer.twitter.com/en/docs/ads/analytics/api-reference/asynchronous
        """

        all_responses = []

        for job_id in job_ids:

            logger.info(f"Processing job_id: {job_id}")

            # job_result = self.get_job_result(job_id)
            # waiting_sec = 2

            # while job_result.status == "PROCESSING":
            #     logger.info(f"Waiting {waiting_sec} seconds for job to be completed")
            #     sleep(waiting_sec)
            #     if waiting_sec > MAX_WAITING_SEC:
            #         raise JobTimeOutError("Waited too long for job to be completed")
            #     waiting_sec *= 2
            #     job_result = self.get_job_result(job_id)

            job_result = self._waiting_for_job_to_complete(job_id)
            raw_analytics_response = self.get_raw_analytics_response(
                job_result)
            all_responses.append(self.parse(raw_analytics_response))

        return chain(*all_responses)

    def get_active_entity_ids(self):
        """
        Step 1 of 'ANALYTICS' report generation process:
        Returns a list containing the ids of active entities over the requested time period
        Documentation: https://developer.twitter.com/en/docs/ads/analytics/api-reference/active-entities
        """

        active_entities = ENTITY_OBJECTS[self.entity].active_entities(
            self.account, self.start_date, self.end_date)
        return [obj["entity_id"] for obj in active_entities]

    def get_job_ids(self, entity_ids):
        """
        Step 2 of 'ANALYTICS' report generation process:
        Create asynchronous analytics jobs and return their ids for progress tracking
        Documentation: https://developer.twitter.com/en/docs/ads/analytics/api-reference/asynchronous
        """

        return [
            ENTITY_OBJECTS[self.entity].queue_async_stats_job(
                self.account,
                chunk_entity_ids,
                self.metric_groups,
                granularity=self.granularity,
                placement=self.placement,
                start_time=self.start_date,
                end_time=self.end_date,
                segmentation_type=self.segmentation_type,
                platform=self.platform,
                country=self.country,
            ).id for chunk_entity_ids in split_list(entity_ids,
                                                    MAX_ENTITY_IDS_PER_JOB)
        ]

    @retry(wait=wait_exponential(multiplier=1, min=60, max=3600),
           stop=stop_after_delay(36000))
    def _waiting_for_job_to_complete(self, job_id):
        """
        Retrying to get job_result until job status is 'COMPLETED'.
        """
        job_result = self.get_job_result(job_id)
        if job_result.status == "PROCESSING":
            raise Exception(f"Job {job_id} is still running.")
        else:
            return job_result

    def get_job_result(self, job_id):
        """
        Step 3 of 'ANALYTICS' report generation process:
        Get job info to track its progress (job_result.status) and download report once completed (job_result.url)
        Documentation: https://developer.twitter.com/en/docs/ads/analytics/api-reference/asynchronous
        """

        return ENTITY_OBJECTS[self.entity].async_stats_job_result(
            self.account, job_ids=[job_id]).first

    def get_raw_analytics_response(self, job_result):
        """
        Step 4 of 'ANALYTICS' report generation process:
        Download raw response from job once completed
        Documentation: https://developer.twitter.com/en/docs/ads/analytics/api-reference/asynchronous
        """

        return ENTITY_OBJECTS[self.entity].async_stats_job_data(
            self.account, url=job_result.url)

    def parse(self, raw_analytics_response):
        """
        Parse a single raw response into a generator of JSON-like records.
        """

        for entity_resp in raw_analytics_response["data"]:
            for entity_data in entity_resp["id_data"]:
                entity_records = [{
                    "id": entity_resp["id"],
                    **{
                        mt: 0 if entity_data["metrics"][mt] is None else entity_data["metrics"][mt][i]
                        for mt in entity_data["metrics"]
                    },
                } for i in range(raw_analytics_response["time_series_length"])]
                entity_records = self.add_daily_timestamps(entity_records)
                entity_records = self.add_segment(entity_records, entity_data)
                yield from entity_records

    def add_daily_timestamps(self, entity_records):
        """
        Add daily timestamps to a list of records, if granularity is 'DAY'.
        """

        if self.granularity == "DAY":
            period_items = self.get_daily_period_items()
            return [{
                **entity_records[i], "date":
                period_items[i].strftime(REP_DATEFORMAT)
            } for i in range(len(entity_records))]
        return entity_records

    def get_daily_period_items(self):
        """
        Returns a list of datetime instances representing each date contained
        in the requested period. Useful when granularity is set to 'DAY'.
        """

        delta = self.end_date - self.start_date
        return [self.start_date + timedelta(days=i) for i in range(delta.days)]

    def add_segment(self, entity_records, entity_data):
        """
        Add segment to a list of records, if a segmentation_type is requested.
        """

        if self.segmentation_type:
            entity_segment = entity_data["segment"]["segment_name"]
            return [{
                **rec, self.segmentation_type.lower(): entity_segment
            } for rec in entity_records]
        return entity_records

    def get_campaign_management_report(self):
        """
        Get 'ENTITY' report through 'Campaign Management' endpoints of Twitter Ads API.
        Supported entities: FUNDING_INSTRUMENT, CAMPAIGN, LINE_ITEM, MEDIA_CREATIVE, PROMOTED_TWEET
        Documentation: https://developer.twitter.com/en/docs/ads/campaign-management/api-reference
        """

        ACCOUNT_CHILD_OBJECTS = {
            "FUNDING_INSTRUMENT": self.account.funding_instruments(),
            "CAMPAIGN": self.account.campaigns(),
            "LINE_ITEM": self.account.line_items(),
            "MEDIA_CREATIVE": self.account.media_creatives(),
            "PROMOTED_TWEET": self.account.promoted_tweets(),
        }

        yield from [{
            attr: getattr(entity_obj, attr, None)
            for attr in self.entity_attributes
        } for entity_obj in ACCOUNT_CHILD_OBJECTS[self.entity]]

    def get_cards_report(self):
        """
        Get 'ENTITY' report through the 'Creatives' endpoint of Twitter Ads API.
        Supported entities: CARD
        Documentation: https://developer.twitter.com/en/docs/ads/creatives/api-reference/
        """
        for tweet in self.get_published_tweets_generator():
            if "card_uri" in tweet:
                card_fetch = self.get_card_fetch(card_uri=tweet["card_uri"])
                card_attributes = {
                    attr: getattr(card_fetch, attr, None)
                    for attr in self.entity_attributes
                }
                record = {
                    "tweet_id": tweet["tweet_id"],
                    "card_uri": tweet["card_uri"],
                    **card_attributes,
                }
                yield record

    @retry(
        wait=wait_exponential(multiplier=60, max=300),
        stop=stop_after_delay(1200),
        retry=retry_if_exception_type(RateLimit),
        before_sleep=before_sleep_log(logger, LEVEL),
    )
    def get_published_tweets_generator(self):
        return self.get_published_tweets()

    def get_published_tweets(self):
        """
        Step 1 of 'ENTITY - CARD' report generation process:
        Returns details on 'PUBLISHED' tweets, as a generator of dictionaries
        Documentation: https://developer.twitter.com/en/docs/ads/creatives/api-reference/tweets
        """

        resource = f"/{API_VERSION}/accounts/{self.account.id}/tweets"
        params = {"tweet_type": "PUBLISHED"}
        request = Request(self.client, "get", resource, params=params)

        yield from Cursor(None, request)

    @retry(
        wait=wait_exponential(multiplier=60, max=600),
        stop=stop_after_delay(1200),
        retry=retry_if_exception_type(RateLimit),
        before_sleep=before_sleep_log(logger, LEVEL),
    )
    def get_card_fetch(self, card_uri):
        """
        Step 2 of 'ENTITY - CARD' report generation process:
        Returns the CartFetch object associated with a specific card_uri
        Documentation: https://developer.twitter.com/en/docs/ads/creatives/api-reference/cards-fetch
        """
        return CardsFetch.load(self.account, card_uris=[card_uri]).first

    @retry(
        wait=wait_exponential(multiplier=60, max=600),
        stop=stop_after_delay(3600),
        before_sleep=before_sleep_log(logger, LEVEL),
    )
    def get_reach_report(self):
        """
        Get 'REACH' report through the 'Reach and Average Frequency' endpoint of Twitter Ads API.
        Documentation: https://developer.twitter.com/en/docs/ads/analytics/api-reference/reach
        """

        resource = f"/{API_VERSION}/stats/accounts/{self.account.id}/reach/{self.entity.lower()}s"
        entity_ids = self.get_active_entity_ids()

        for chunk_entity_ids in split_list(entity_ids, MAX_ENTITY_IDS_PER_JOB):
            try:
                params = {
                    "account_id": self.account.id,
                    f"{self.entity.lower()}_ids": ",".join(entity_ids),
                    "start_time": self.start_date.strftime(API_DATEFORMAT),
                    "end_time": self.end_date.strftime(API_DATEFORMAT),
                }
                request = Request(self.client, "get", resource, params=params)
                yield from Cursor(None, request)
            except Exception:
                ex_type, ex, tb = sys.exc_info()
                logger.warning(
                    f"Failed to ingest post with error: {ex}. Traceback: {traceback.print_tb(tb)}"
                )

    def add_request_or_period_dates(self, record):
        """
        Add request_date, period_start_date and/or period_end_date to a JSON-like record.
        """
        def check_add_period_date_to_report():
            return (self.report_type == "ANALYTICS" and self.granularity
                    == "TOTAL") or self.report_type == "REACH"

        if self.add_request_date_to_report:
            record["request_date"] = datetime.today().strftime(REP_DATEFORMAT)

        if check_add_period_date_to_report():
            record["period_start_date"] = self.start_date.strftime(
                REP_DATEFORMAT)
            record["period_end_date"] = (
                self.end_date - timedelta(days=1)).strftime(REP_DATEFORMAT)

        return record

    def read(self):
        if self.report_type == "ANALYTICS":
            entity_ids = self.get_active_entity_ids()

            total_jobs = (len(entity_ids) // MAX_ENTITY_IDS_PER_JOB) + 1
            logger.info(f"Processing a total of {total_jobs} jobs")

            data = []
            for chunk_entity_ids in split_list(
                    entity_ids, MAX_ENTITY_IDS_PER_JOB * MAX_CONCURRENT_JOBS):
                job_ids = self.get_job_ids(chunk_entity_ids)
                data += self.get_analytics_report(job_ids)

        elif self.report_type == "REACH":
            data = self.get_reach_report()

        elif self.report_type == "ENTITY":
            if self.entity == "CARD":
                data = self.get_cards_report()
            else:
                data = self.get_campaign_management_report()

        def result_generator():
            for record in data:
                yield self.add_request_or_period_dates(record)

        yield JSONStream("results_" + self.account.id, result_generator())
Example #22
0
def home(request):
    Accounts = ['18ce559z5re', '18ce559wc04', '18ce557t3m2', '18ce552xv0y']
    for AccountID in Accounts:
        CONSUMER_KEY = 'HDoSqCGCB3myJNoMP5RziL97w'
        CONSUMER_SECRET = '1WUOTQZsbNxIyVFpjCfSK4NslZqGUsvroYF4UdPFhGIVA4QPsh'
        ACCESS_TOKEN = '786549565717491713-3Qd2klEkIroIHYZ7f78ACd36qutNVHx'
        ACCESS_TOKEN_SECRET = '0aFaWFTpgXnrnhUCB2yZyGbcs8LF48Q1LQJiUt1VSvadn'
        ACCOUNT_ID = AccountID

        # initialize the client
        client = Client(CONSUMER_KEY,
                        CONSUMER_SECRET,
                        ACCESS_TOKEN,
                        ACCESS_TOKEN_SECRET,
                        options={
                            'handle_rate_limit': True,
                            'retry_max': 3,
                            'retry_delay': 10,
                            'retry_on_status': [404, 500, 503]
                        })

        # load the advertiser account instance
        account = client.accounts(ACCOUNT_ID)
        # print(account.name)

        yesterday = ("2020-03-05") + ("T00:00:00+08:00")
        today = ("2020-03-07") + ("T00:00:00+08:00")

        SpendList = []
        DateList = []
        # iterate through campaigns
        for camp in account.campaigns():

            if camp.id:

                resource = f"/8/stats/accounts/" + AccountID + "/"  #Enter Account Id Here
                params = {
                    "entity": ENTITY.CAMPAIGN,
                    "entity_ids": camp.id,
                    "start_time": yesterday,
                    "end_time": today,
                    "granularity": GRANULARITY.TOTAL,
                    "metric_groups": METRIC_GROUP.BILLING,
                    "placement": PLACEMENT.ALL_ON_TWITTER
                }

                req = Request(client=client,
                              method="GET",
                              resource=resource,
                              params=params)

                response = req.perform()
                spend_in_micros_value = response.body["data"][0]["id_data"][0][
                    "metrics"]["billed_charge_local_micro"]

                if spend_in_micros_value != None:
                    spendAll = response.body["data"][0]["id_data"][0][
                        "metrics"]["billed_charge_local_micro"][0]

                    spend = round((spendAll / 1000000), 2)
                    SpendList.append(spend)
                else:
                    spend = 0
                    SpendList.append(spend)

                StartTime = response.body["request"]["params"]["start_time"]
                #           Subtraction one Day
                x = slice(10)
                startTime = (StartTime[x])
                start = datetime.strptime(startTime, "%Y-%m-%d")
                Start = start + timedelta(days=1)

                EndTime = response.body["request"]["params"]["end_time"]

                #           Subtraction one Day
                x = slice(10)
                endTime = (EndTime[x])
                end = datetime.strptime(endTime, "%Y-%m-%d")
                End = end - timedelta(days=0)

                DateList.append(Start)
                DateList.append(End)

            else:
                print("No Camp")

        total = 0
        for OneMonth in range(0, len(SpendList)):
            total = total + SpendList[OneMonth]
        account = (account.name)
        print("Total Spend= ", total)
        StartDate = (DateList[0])
        EndDate = (DateList[1])

        currentDate = datetime.today()
        print("Current Date= ", currentDate)

        DataFrame = DataSet(currentDate=currentDate,
                            account=account,
                            spend=total,
                            StartDate=StartDate,
                            EndDate=EndDate)
        DataFrame.save()
    return render(request, "index.html")
from twitter_ads.client import Client
from twitter_ads.account import Account
from twitter_ads.campaign import Campaign

CONSUMER_KEY = "your consumer key"
CONSUMER_SECRET = "your consumer secret"
ACCESS_TOKEN = "access token"
ACCESS_TOKEN_SECRET = "access token secret"
ACCOUNT_ID = "account id"

# initialize the client
client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

# load the advertiser account instance
account = client.accounts(id=ACCOUNT_ID)

# load and update a specific campaign
campaign = account.campaigns().next()
campaign.name = "updated campaign name"
campaign.paused = True
campaign.save()

# iterate through campaigns
for campaign in account.campaigns():
    print(campaign.id)
    def fetch_tailored_audience(self,
                                data,
                                syncData=False,
                                oauth_token=settings.TW_ACCESS_TOKEN,
                                oauth_token_secret=settings.TW_ACCESS_SECRET):
        res = {}
        res['data'] = []
        res['success'] = False
        account_id = data.get('account_id')

        if isinstance(account_id, (int, long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_token_secret)
        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX
        try:
            account = client.accounts(account_id)
            resource = '/{api_version}/accounts/{account_id}/tailored_audiences?count=1000'.format(
                api_version=settings.TW_API_VERSION, account_id=account_id)
            response = Request(client, 'get', resource).perform()
            tailored_audiences = response.body['data']

            next_cursor = None
            if response.body['next_cursor'] and response.body[
                    'next_cursor'] is not 0:
                next_cursor = response.body['next_cursor']
                while next_cursor is not 0:
                    resource = '/{api_version}/accounts/{account_id}/tailored_audiences?cursor={next_cursor}&count=1000'.format(
                        api_version=settings.TW_API_VERSION,
                        account_id=account_id,
                        next_cursor=next_cursor)
                    response = Request(client, 'get', resource).perform()
                    next_cursor = response.body['next_cursor'] or 0
                    tailored_audiences += response.body['data']

            api_domain = 'https://ads.twitter.com'

            resource = '/accounts/{account_id}/apps.json'.format(
                account_id=account_id)
            response = Request(client, 'get', resource,
                               domain=api_domain).perform()

            apps = response.body.get('apps_info', {})
            app_table = []
            for (k, v) in apps.iteritems():
                app_store_identifier = v.get('app_store_identifier')
                app_name = v.get('title')
                if app_store_identifier and app_name:
                    app_table.append({
                        'id': app_store_identifier,
                        'name': app_name
                    })

            def replace_app_name(app_name):
                for app_info in app_table:
                    app_name = app_name.replace(app_info['id'],
                                                app_info['name'])

                return app_name.replace('_', ' ')

            def human_format(num):
                magnitude = 0
                while abs(num) >= 1000:
                    magnitude += 1
                    num /= 1000.0
                # add more suffixes if you need them
                return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'
                                         ][magnitude])

            for audience in tailored_audiences:
                audience['name'] = replace_app_name(audience['name'])
                if audience['audience_size']:
                    audience['audience_size'] = human_format(
                        audience['audience_size'])
                    audience['name'] = '%s (%s users)' % (
                        audience['name'], audience['audience_size'])

            res['success'] = True
            res['data'] = tailored_audiences

        except Exception as e:
            res = {'data': {}, 'success': False, 'message': str(e)}

        if syncData and res['data'] and res['success']:
            res['sync'] = {}
            if isinstance(res['data'], (list, tuple)):
                sync_success = 0
                sync_fail = 0
                new_count = 0
                existing_count = 0
                for index, audience in enumerate(res['data'], start=0):
                    audience_res = self.sync_tailored_audience(
                        account_id_int, audience)
                    if 'success' in audience_res and audience_res[
                            'success'] is True:
                        if audience_res['type'] == 'existing':
                            existing_count += 1
                        if audience_res['type'] == 'new':
                            new_count += 1
                        sync_success += 1

                    elif 'success' in audience_res and audience_res[
                            'success'] is False:
                        sync_fail += 1

                res['sync']['type'] = {}
                res['sync']['type']['existing'] = existing_count
                res['sync']['type']['new'] = new_count
                res['sync']['total'] = sync_success
                if sync_fail == 0:
                    res['sync']['success'] = True
                else:
                    res['sync']['success'] = False

            elif isinstance(res['data'], dict):
                audience_res = self.sync_tailored_audience(
                    account_id_int, res['data'])

                if 'success' in audience_res and audience_res[
                        'success'] is True:
                    res['data'] = audience_res['data']
                    res['sync']['success'] = audience_res['success']
                    res['sync']['type'] = {}
                    res['sync']['type'][audience_res['type']] = 1
                    res['sync']['total'] = 1

                elif 'success' in audience_res and audience_res[
                        'success'] is False:
                    res['data'] = audience_res['data']
                    res['sync']['success'] = audience_res['success']
                    res['sync']['message'] = audience_res['message']
        return res
    def fetch_campaigns(self,
                        data,
                        syncData=False,
                        oauth_token=settings.TW_ACCESS_TOKEN,
                        oauth_token_secret=settings.TW_ACCESS_SECRET):
        res = {}
        res['data'] = []
        res['success'] = False
        account_id = data.get('account_id')
        campaign_id = data.get('campaign_id')
        tw_campaign_id = data.get('tw_campaign_id')

        if isinstance(account_id, (int, long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)

        if isinstance(tw_campaign_id, (int, long)):
            tw_campaign_id_int = tw_campaign_id
            tw_campaign_id = int_to_base36(tw_campaign_id)

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_token_secret)
        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX
        try:
            account = client.accounts(account_id)
            # If Manage Campaign ID passed, fetch all Campaigns and find Manage Campaign
            if campaign_id:
                resource = '/{api_version}/accounts/{account_id}/campaigns?count=1000&with_deleted=true'.format(
                    api_version=settings.TW_API_VERSION, account_id=account.id)
                response = Request(client, 'get', resource).perform()

                if response.headers[
                        'x-rate-limit-remaining'] == "0" and settings.TW_RATE_LIMIT_ALERT:
                    send_twitter_alert_email({
                        "account_id": account_id,
                        "endpoint": resource
                    })

                for campaign in response.body['data']:
                    campaign_id_match = re.findall(r'\s*{(\d+)}\s*$',
                                                   campaign['name'])[:1]
                    if campaign_id_match and campaign_id_match[0] and int(
                            campaign_id_match[0]) == int(campaign_id):
                        res['data'].append(campaign)
                res['success'] = True
            else:
                if tw_campaign_id:
                    resource = '/{api_version}/accounts/{account_id}/campaigns/{tw_campaign_id}?count=1000&with_deleted=true'.format(
                        api_version=settings.TW_API_VERSION,
                        account_id=account.id,
                        tw_campaign_id=tw_campaign_id)
                else:
                    resource = '/{api_version}/accounts/{account_id}/campaigns?count=1000&with_deleted=true'.format(
                        api_version=settings.TW_API_VERSION,
                        account_id=account.id)

                response = Request(client, 'get', resource).perform()

                if response.headers[
                        'x-rate-limit-remaining'] == "0" and settings.TW_RATE_LIMIT_ALERT:
                    send_twitter_alert_email({
                        "account_id": account_id,
                        "endpoint": resource
                    })

                res['data'] = response.body['data']

                next_cursor = None
                if response.body['next_cursor'] and response.body[
                        'next_cursor'] is not 0:
                    next_cursor = response.body['next_cursor']
                    while next_cursor is not 0:
                        if tw_campaign_id:
                            resource = '/{api_version}/accounts/{account_id}/campaigns/{tw_campaign_id}?cursor={next_cursor}&count=1000&with_deleted=true'.format(
                                api_version=settings.TW_API_VERSION,
                                account_id=account.id,
                                tw_campaign_id=tw_campaign_id,
                                next_cursor=next_cursor)
                        else:
                            resource = '/{api_version}/accounts/{account_id}/campaigns?cursor={next_cursor}&count=1000&with_deleted=true'.format(
                                api_version=settings.TW_API_VERSION,
                                account_id=account.id,
                                next_cursor=next_cursor)

                        response = Request(client, 'get', resource).perform()
                        next_cursor = response.body['next_cursor'] or 0
                        res['data'] += response.body['data']

                res['success'] = True

        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success':
                False,
                'message':
                e.details[0]['message'] if e.details and e.details[0]
                and e.details[0]['message'] else '',
                'errors': {
                    str(code): True
                } if code else {}
            }
        except Exception as e:
            res = {'data': {}, 'success': False, 'message': str(e)}

        if syncData and res['data'] and res['success']:
            res['sync'] = {}
            if isinstance(res['data'], (list, tuple)):
                sync_success = 0
                sync_fail = 0
                new_count = 0
                existing_count = 0
                for index, api_campaign in enumerate(res['data'], start=0):
                    campaign_res = self.sync_campaign(account_id_int,
                                                      api_campaign)
                    if 'success' in campaign_res and campaign_res[
                            'success'] is True:
                        if campaign_res['type'] == 'existing':
                            existing_count += 1
                        if campaign_res['type'] == 'new':
                            new_count += 1
                        sync_success += 1

                    elif 'success' in campaign_res and campaign_res[
                            'success'] is False:
                        sync_fail += 1

                res['os_platform'] = campaign_res['os_platform']
                res['sync']['type'] = {}
                res['sync']['type']['existing'] = existing_count
                res['sync']['type']['new'] = new_count
                res['sync']['total'] = sync_success
                if sync_fail == 0:
                    res['sync']['success'] = True
                else:
                    res['sync']['success'] = False

            elif isinstance(res['data'], dict):
                campaign_res = self.sync_campaign(account_id_int, res['data'])

                if 'success' in campaign_res and campaign_res[
                        'success'] is True:
                    res['data'] = campaign_res['data']
                    res['os_platform'] = campaign_res['os_platform']
                    res['sync']['success'] = campaign_res['success']
                    res['sync']['type'] = {}
                    res['sync']['type'][campaign_res['type']] = 1
                    res['sync']['total'] = 1

                elif 'success' in campaign_res and campaign_res[
                        'success'] is False:
                    res['data'] = campaign_res['data']
                    res['sync']['success'] = campaign_res['success']
                    res['sync']['message'] = campaign_res['message']
        return res
    def batch_create_update_campaign(
            self,
            data,
            account_id,
            oauth_token=settings.TW_ACCESS_TOKEN,
            oauth_token_secret=settings.TW_ACCESS_SECRET,
            request_type="post"):
        res = {}
        res['success'] = False
        campaign_id_int = None

        if isinstance(account_id, (int, long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)

        if account_id is None:
            res = {
                'data': [],
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        if isinstance(data, (list, tuple)):
            post_data = []
            for campaign in data:
                campaign_data = {}
                params = {}
                params['daily_budget_amount_local_micro'] = campaign.get(
                    'daily_budget_amount_local_micro', None)
                params['duration_in_days'] = campaign.get(
                    'duration_in_days', None)
                params['end_time'] = campaign.get('end_time', None)
                params['frequency_cap'] = campaign.get('frequency_cap', None)
                params['funding_instrument_id'] = campaign.get(
                    'funding_instrument_id', None)
                params['name'] = campaign.get('name', None)
                if campaign.get('paused', None) is not None:
                    params['paused'] = 'true' if campaign.get(
                        'paused') else 'false'
                params['standard_delivery'] = str(
                    campaign.get('standard_delivery')).lower() if campaign.get(
                        'standard_delivery') else None
                params['start_time'] = campaign.get('start_time', None)
                params['total_budget_amount_local_micro'] = campaign.get(
                    'total_budget_amount_local_micro', None)

                # total_budget_amount_local_micro = 0 is not permitted
                if not params['total_budget_amount_local_micro']:
                    params['total_budget_amount_local_micro'] = None
                params = dict((k, v) for k, v in params.iteritems()
                              if v is not None and v is not "")

                if request_type == 'post':
                    campaign_data['operation_type'] = 'Create'
                if request_type == 'put':
                    campaign_data['operation_type'] = 'Update'

                campaign_data['params'] = params
                post_data.append(campaign_data)

            client = Client(settings.TW_CONSUMER_KEY,
                            settings.TW_CONSUMER_SECRET, oauth_token,
                            oauth_token_secret)

            if settings.TW_SANDBOX:
                client.sandbox = settings.TW_SANDBOX

            # Split up requests into batches of 20
            batch = []
            batches = []
            for x in range(0, len(post_data), 20):
                batch = post_data[x:x + 20]
                batches.append(batch)

            success_batch = []
            error_batch = []
            error_details = []
            success = False
            error = False

            for batch_post in batches:
                try:
                    account = client.accounts(account_id)
                    headers = {"Content-Type": "application/json"}
                    resource = '/{api_version}/batch/accounts/{account_id}/campaigns'.format(
                        api_version=settings.TW_API_VERSION,
                        account_id=account.id)
                    response = Request(client,
                                       'post',
                                       resource,
                                       body=json.dumps(batch_post),
                                       headers=headers).perform()

                    if response.code == 200 or response.code == 201:
                        success = True
                        success_batch.extend(response.body['data'])

                except Error as e:
                    error = True
                    if e.response.body.get('operation_errors',
                                           None) is not None:
                        for err in e.response.body.get('operation_errors'):
                            if err:
                                if isinstance(err, dict):
                                    err = [err]
                                error_details.extend(err)
                    if e.response.body.get('errors', None) is not None:
                        for err in e.response.body.get('errors'):
                            if err:
                                if isinstance(err, dict):
                                    err = [err]
                                error_details.extend(err)

                    error_batch.extend(batch_post)

                except Exception as e:
                    res = {'data': [], 'success': False, 'message': str(e)}
                    error_batch.extend(batch_post)

            if success_batch and success:
                res['sync'] = {}

                if isinstance(success_batch, dict):
                    success_batch = [success_batch]

                sync_success = 0
                sync_fail = 0
                new_count = 0
                existing_count = 0

                for index, api_campaign in enumerate(success_batch, start=0):
                    campaign_res = self.sync_campaign(account_id_int,
                                                      api_campaign)
                    if 'success' in campaign_res and campaign_res[
                            'success'] is True:
                        if campaign_res['type'] == 'existing':
                            existing_count += 1
                        if campaign_res['type'] == 'new':
                            new_count += 1
                        sync_success += 1

                    elif 'success' in campaign_res and campaign_res[
                            'success'] is False:
                        sync_fail += 1

                res['sync']['type'] = {}
                res['sync']['type']['existing'] = existing_count
                res['sync']['type']['new'] = new_count
                res['sync']['total'] = sync_success

                if sync_fail == 0:
                    res['sync']['success'] = True
                else:
                    res['sync']['success'] = False

            res['success'] = success
            res['count'] = {}
            res['count']['success'] = len(success_batch)
            res['count']['total'] = len(data)
            res['count']['error'] = len(error_batch)
            res['data'] = success_batch

            if error:
                res['success'] = False
                res['error'] = {}
                res['error']['data'] = error_batch
                res['error']['messages'] = filter(None, error_details)

            return res

        elif isinstance(data, dict):
            if request_type == 'post':
                return self.create(data, oauth_token, oauth_token_secret)
            if request_type == 'put':
                return self.update(data, oauth_token, oauth_token_secret)
from twitter_ads.client import Client
from twitter_ads.creative import CardsFetch
from twitter_ads.http import Request


CONSUMER_KEY = ''
CONSUMER_SECRET = ''
ACCESS_TOKEN = ''
ACCESS_TOKEN_SECRET = ''
ACCOUNT_ID = ''

# initialize the client
client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

# load the advertiser account instance
account = client.accounts(ACCOUNT_ID)

# retrieve a Tweet
tweet_id = '973002610033610753' # use one of your own Tweets
resource = '/1.1/statuses/show/{id}.json'.format(id=tweet_id)
domain = 'https://api.twitter.com'
params = {'include_card_uri' : 'true'}
response = Request(client, 'get', resource, domain=domain, params=params).perform()
card_uri = response.body['card_uri'] # Tweet must include a card_uri card

# fetch by card_uri
cf = CardsFetch(account)
card = cf.load(account, card_uri=card_uri)
card.card_type # 'VIDEO_POLLS'
card.id # '5g83p'
    def fetch_tweet(self, data, syncData=False, oauth_token=settings.TW_ACCESS_TOKEN,
                    oauth_secret=settings.TW_ACCESS_SECRET):
        res = {}
        res['success'] = True
        account_id = data.get('account_id')
        tweet_id = data.get('tweet_id')

        if isinstance(account_id,(int,long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)

        if not _cache.get(account_id):
            try:
                tw_account = TwitterAccount.objects_raw.filter(tw_account_id=account_id_int).first()
                if tw_account.promotable_user_id.tw_twitter_user_id:
                    _cache[account_id] = tw_account.promotable_user_id.tw_twitter_user_id
            except TwitterUser.DoesNotExist:
                _cache[account_id] = 0
            except TwitterAccount.DoesNotExist:
                _cache[account_id] = 0

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET, oauth_token, oauth_secret)
        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX
        try:
            api_domain = 'https://api.twitter.com'
            resource = '/{api_version}/statuses/show.json?id={tweet_id}'.format(api_version="1.1", tweet_id=tweet_id)
            response = Request(client, 'get', resource, domain=api_domain).perform()
            entities = response.body['entities']

            #print response.headers['x-rate-limit-remaining']
            if response.headers['x-rate-limit-remaining'] == "0" and settings.TW_RATE_LIMIT_ALERT:
                send_twitter_alert_email({"account_id": account_id, "endpoint": resource})

            expanded_url = None
            if entities and entities['urls'] and entities['urls'][0] and entities['urls'][0]['expanded_url']:
                expanded_url = entities['urls'][0]['expanded_url']

            account = client.accounts(account_id)
            as_user_id = ('?as_user_id=%s' % _cache[account_id]) if _cache[account_id] else ''
            resource = '/{api_version}/accounts/{account_id}/tweet/preview/{tweet_id}{as_user_id}'.format(api_version=settings.TW_API_VERSION, account_id=account.id, tweet_id=tweet_id, as_user_id=as_user_id)
            response = Request(client, 'get', resource).perform()
            res['data'] = response.body['data']
            res['card_url'] = expanded_url

        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success': False,
                'message': e.details[0]['message'] if e.details and e.details[0] and e.details[0]['message'] else '',
                'errors': { str(code): True } if code else {}
            }
        except Exception as e:
            res = {
                'data': {},
                'success': False,
                'message': str(e)
            }
        return res
Example #29
0
    def create_update_promoted_tweet(
            self,
            data,
            oauth_token=settings.TW_ACCESS_TOKEN,
            oauth_token_secret=settings.TW_ACCESS_SECRET,
            request_type="post"):
        res = {}
        res['sync'] = {}
        account_id = data.get('account_id', None)
        line_item_id = data.get('line_item_id', None)
        tweet_ids = data.get('tweet_ids', None)
        promoted_tweet_id = data.get('promoted_tweet_id', None)
        line_item_id_int = None

        line_item_id_int = line_item_id
        line_item_id_base_36 = int_to_base36(line_item_id)
        account_id_int = account_id
        account_id_base36 = int_to_base36(account_id)

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        if request_type == 'put' or request_type == 'delete':
            if promoted_tweet_id is None:
                res = {
                    'data': {},
                    'success': False,
                    'message': "Missing Twitter Promoted Tweet ID"
                }
                return res

        if request_type == 'post':
            if tweet_ids is None:
                res = {
                    'data': {},
                    'success': False,
                    'message': "Missing Twitter Tweet IDs"
                }
                return res

            if line_item_id is None:
                res = {
                    'data': {},
                    'success': False,
                    'message': "Missing Twitter Line Item ID"
                }
                return res

        params = {}
        params['display_properties'] = data.get('display_properties', None)
        params['tweet_ids'] = data.get('tweet_ids', None)
        params['line_item_id'] = line_item_id_base_36
        params = dict((k, v) for k, v in params.iteritems()
                      if v is not None and v is not "")
        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_token_secret)

        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX

        try:
            account = client.accounts(account_id_base36)

            if request_type == 'put' or request_type == 'delete':
                resource = '/{api_version}/accounts/{account_id}/promoted_tweets/{promoted_tweet_id}'.format(
                    api_version=settings.TW_API_VERSION,
                    account_id=account.id,
                    promoted_tweet_id=promoted_tweet_id)

            elif request_type == 'post':
                resource = '/{api_version}/accounts/{account_id}/promoted_tweets'.format(
                    api_version=settings.TW_API_VERSION, account_id=account.id)
            response = Request(client, request_type, resource,
                               params=params).perform()
            if response.code == 200 or response.code == 201:
                res['success'] = True

            res['data'] = response.body['data']

            if res['data'] and res['success']:

                sync_success = 0
                sync_fail = 0
                new_count = 0
                existing_count = 0
                deleted_count = 0
                if request_type == 'delete':
                    res['data'] = [res['data']]
                for index, api_line_item_promoted_tweet in enumerate(
                        res['data'], start=0):
                    line_item_id_int = base36_to_int(
                        api_line_item_promoted_tweet['line_item_id'])
                    api_line_item_promoted_tweet['account_id'] = account_id

                    line_item_promoted_tweet_res = self.sync_promoted_tweet(
                        account_id_int, line_item_id_int,
                        api_line_item_promoted_tweet)

                    if 'success' in line_item_promoted_tweet_res and line_item_promoted_tweet_res[
                            'success'] is True:
                        if 'skip' in line_item_promoted_tweet_res:
                            continue

                        if line_item_promoted_tweet_res['type'] == 'existing':
                            existing_count += 1
                        if line_item_promoted_tweet_res['type'] == 'new':
                            new_count += 1
                        if line_item_promoted_tweet_res['type'] == 'delete':
                            deleted_count += 1
                        sync_success += 1
                    elif 'success' in line_item_promoted_tweet_res and line_item_promoted_tweet_res[
                            'success'] is False:
                        sync_fail += 1

                res['sync']['success'] = sync_fail == 0
                res['sync']['type'] = {}
                res['sync']['type']['existing'] = existing_count
                res['sync']['type']['new'] = new_count
                res['sync']['type']['delete'] = deleted_count

        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success':
                False,
                'message':
                e.details[0]['message'] if e.details and e.details[0]
                and e.details[0]['message'] else '',
                'errors': {
                    str(code): True
                } if code else {}
            }
        except Exception as e:
            res = {'data': {}, 'success': False, 'message': str(e)}

        return res
Example #30
0
    def batch_create_update_line_item(
            self,
            data,
            account_id,
            oauth_token=settings.TW_ACCESS_TOKEN,
            oauth_token_secret=settings.TW_ACCESS_SECRET,
            request_type="post"):
        res = {}
        res['success'] = False
        campaign_id_int = None

        if isinstance(account_id, (int, long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)

        if account_id is None:
            res = {
                'data': [],
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        if isinstance(data, (list, tuple)):
            post_data = []
            for line_item in data:
                line_item_data = {}
                params = {}
                params['bid_amount_local_micro'] = line_item.get(
                    'bid_amount_local_micro', None)
                params['bid_type'] = line_item.get('bid_type', None)
                params['bid_unit'] = line_item.get('bid_unit', None)
                params['campaign_id'] = line_item.get('campaign_id', None)
                params['categories'] = line_item.get('categories', None)
                params['charge_by'] = line_item.get('charge_by', None)
                params['end_time'] = line_item.get('end_time', None)
                params['include_sentiment'] = line_item.get(
                    'include_sentiment', None)
                params['line_item_id'] = line_item.get('line_item_id', None)
                params['name'] = line_item.get('name', None)
                params['objective'] = line_item.get('objective',
                                                    'APP_INSTALLS')
                params['primary_web_event_tag'] = line_item.get(
                    'primary_web_event_tag', None)
                params['optimization'] = line_item.get('optimization', None)
                params['paused'] = str(line_item.get(
                    'paused')).lower() if line_item.get('paused') else None
                params['placements'] = line_item.get('placements',
                                                     'ALL_ON_TWITTER')
                params['product_type'] = line_item.get('product_type',
                                                       'PROMOTED_TWEETS')
                params['start_time'] = line_item.get('start_time', None)
                params['total_budget_amount_local_micro'] = line_item.get(
                    'total_budget_amount_local_micro', None)

                # total_budget_amount_local_micro = 0 is not permitted
                if not params['total_budget_amount_local_micro']:
                    params['total_budget_amount_local_micro'] = None

                params = dict((k, v) for k, v in params.iteritems()
                              if v is not None and v is not "")

                if request_type == 'post':
                    line_item_data['operation_type'] = 'Create'
                if request_type == 'put':
                    line_item_data['operation_type'] = 'Update'
                line_item_data['params'] = params
                post_data.append(line_item_data)

            client = Client(settings.TW_CONSUMER_KEY,
                            settings.TW_CONSUMER_SECRET, oauth_token,
                            oauth_token_secret)

            if settings.TW_SANDBOX:
                client.sandbox = settings.TW_SANDBOX

            # Split up requests into batches of 20
            batch = []
            batches = []
            for x in range(0, len(post_data), 20):
                batch = post_data[x:x + 20]
                batches.append(batch)

            success_batch = []
            error_batch = []
            error_details = []
            success = False
            error = False

            for batch_post in batches:
                try:
                    account = client.accounts(account_id)
                    headers = {"Content-Type": "application/json"}
                    resource = '/{api_version}/batch/accounts/{account_id}/line_items'.format(
                        api_version=settings.TW_API_VERSION,
                        account_id=account.id)
                    response = Request(client,
                                       'post',
                                       resource,
                                       body=json.dumps(batch_post),
                                       headers=headers).perform()

                    if response.code == 200 or response.code == 201:
                        success = True
                        success_batch.extend(response.body['data'])

                except Error as e:
                    error = True
                    if e.response.body.get('operation_errors',
                                           None) is not None:
                        for err in e.response.body.get('operation_errors'):
                            if err:
                                if isinstance(err, dict):
                                    err = [err]
                                error_details.extend(err)
                    if e.response.body.get('errors', None) is not None:
                        for err in e.response.body.get('errors'):
                            if err:
                                if isinstance(err, dict):
                                    err = [err]
                                error_details.extend(err)

                    error_batch.extend(batch_post)

                except Exception as e:
                    res = {'data': [], 'success': False, 'message': str(e)}
                    error_batch.extend(batch_post)

            if success_batch and success:
                res['sync'] = {}

                if isinstance(success_batch, dict):
                    success_batch = [success_batch]

                sync_success = 0
                sync_fail = 0
                new_count = 0
                existing_count = 0

                for index, api_line_item in enumerate(success_batch, start=0):
                    #campaign_id could be different in line item bach
                    campaign_id_int = base36_to_int(
                        api_line_item['campaign_id'])
                    line_item_res = self.sync_line_item(
                        account_id_int, campaign_id_int, api_line_item)
                    if 'success' in line_item_res and line_item_res[
                            'success'] is True:
                        if line_item_res['type'] == 'existing':
                            existing_count += 1
                        if line_item_res['type'] == 'new':
                            new_count += 1
                        sync_success += 1

                    elif 'success' in line_item_res and line_item_res[
                            'success'] is False:
                        sync_fail += 1

                res['sync']['type'] = {}
                res['sync']['type']['existing'] = existing_count
                res['sync']['type']['new'] = new_count
                res['sync']['total'] = sync_success

                if sync_fail == 0:
                    res['sync']['success'] = True
                else:
                    res['sync']['success'] = False

            res['success'] = success
            res['count'] = {}
            res['count']['success'] = len(success_batch)
            res['count']['total'] = len(data)
            res['count']['error'] = len(error_batch)
            res['data'] = success_batch

            if error:
                res['success'] = False
                res['error'] = {}
                res['error']['data'] = error_batch
                res['error']['messages'] = filter(None, error_details)

            return res

        elif isinstance(data, dict):
            if request_type == 'post':
                return self.create(data, oauth_token, oauth_token_secret)
            if request_type == 'put':
                return self.update(data, oauth_token, oauth_token_secret)
Example #31
0
    def create_update_line_item(self,
                                data,
                                oauth_token=settings.TW_ACCESS_TOKEN,
                                oauth_token_secret=settings.TW_ACCESS_SECRET,
                                request_type="post"):
        res = {}
        res['sync'] = {}
        account_id = data.get('account_id', None)
        campaign_id = data.get('campaign_id', None)
        line_item_id = data.get('line_item_id', None)
        campaign_id_int = None

        if isinstance(campaign_id, (int, long)):
            campaign_id_int = campaign_id
            campaign_id = int_to_base36(campaign_id)
            data['campaign_id'] = campaign_id

        if isinstance(line_item_id, (int, long)):
            line_item_id_int = line_item_id
            line_item_id = int_to_base36(line_item_id)

        if isinstance(account_id, (int, long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)

        if account_id is None:
            res = {
                'data': [],
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        if request_type == 'post':
            if campaign_id is None:
                res = {
                    'data': [],
                    'success': False,
                    'message': "Missing Twitter Campaign ID"
                }
                return res

        if request_type == 'put':
            if line_item_id is None:
                res = {
                    'data': [],
                    'success': False,
                    'message': "Missing Twitter Line Item ID"
                }
                return res

        params = {}
        params['advertiser_domain'] = data.get('advertiser_domain', None)
        # automatically_set_bid and bid_type cannot be set in the same request
        # See https://dev.twitter.com/ads/reference/post/accounts/%3Aaccount_id/line_items#api-param-line-item-bid_type
        if data.get('automatically_select_bid', False) is True:
            params['automatically_select_bid'] = str(True).lower()
        else:
            params['bid_type'] = data.get('bid_type', None)
            params['bid_amount_local_micro'] = data.get(
                'bid_amount_local_micro', None)

        params['bid_amount_local_micro'] = data.get('bid_amount_local_micro',
                                                    None)
        params['bid_type'] = data.get('bid_type', None)
        params['bid_unit'] = data.get('bid_unit', None)
        params['campaign_id'] = data.get('campaign_id', None)
        params['categories'] = data.get('categories', None)
        params['charge_by'] = data.get('charge_by', None)
        params['end_time'] = data.get('end_time', None)
        params['include_sentiment'] = data.get('include_sentiment',
                                               'POSITIVE_ONLY')
        params['name'] = data.get('name', None)
        params['objective'] = data.get('objective', 'APP_INSTALLS')
        params['optimization'] = data.get('optimization', None)
        if data.get('paused', None) is not None:
            params['paused'] = 'true' if data.get('paused') else 'false'
        params['placements'] = data.get('placements', 'ALL_ON_TWITTER')
        params['product_type'] = data.get('product_type', 'PROMOTED_TWEETS')
        params['start_time'] = data.get('start_time', None)
        params['total_budget_amount_local_micro'] = data.get(
            'total_budget_amount_local_micro', None)

        # total_budget_amount_local_micro = 0 is not permitted
        if not params['total_budget_amount_local_micro']:
            params['total_budget_amount_local_micro'] = None

        params = dict((k, v) for k, v in params.iteritems()
                      if v is not None and v is not "")

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_token_secret)
        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX

        try:
            account = client.accounts(account_id)

            if request_type == 'put':
                resource = '/{api_version}/accounts/{account_id}/line_items/{line_item_id}'.format(
                    api_version=settings.TW_API_VERSION,
                    account_id=account.id,
                    line_item_id=line_item_id)

            elif request_type == 'post':
                resource = '/{api_version}/accounts/{account_id}/line_items'.format(
                    api_version=settings.TW_API_VERSION, account_id=account.id)

            response = Request(client, request_type, resource,
                               params=params).perform()

            if response.code == 200 or response.code == 201:
                res['success'] = True

            res['data'] = response.body['data']

            if res['data'] and res['success']:
                if campaign_id_int is None and res['data']['campaign_id']:
                    campaign_id_int = base36_to_int(res['data']['campaign_id'])

                line_item_res = self.sync_line_item(account_id_int,
                                                    campaign_id_int,
                                                    res['data'])

                if 'success' in line_item_res and line_item_res[
                        'success'] is True:
                    res['data'] = line_item_res['data']
                    res['sync']['success'] = line_item_res['success']
                    res['sync']['type'] = {}
                    res['sync']['total'] = 1
                    res['sync']['type'][line_item_res['type']] = 1

                elif 'success' in line_item_res and line_item_res[
                        'success'] is False:
                    res['data'] = line_item_res['data']
                    res['sync']['success'] = line_item_res['success']
                    res['sync']['message'] = line_item_res['message']

        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success':
                False,
                'message':
                e.details[0]['message'] if e.details and e.details[0]
                and e.details[0]['message'] else '',
                'errors': {
                    str(code): True
                } if code else {}
            }
        except Exception as e:
            res = {'data': {}, 'success': False, 'message': str(e)}

        return res
Example #32
0
    def get_line_item(self,
                      data,
                      oauth_token=settings.TW_ACCESS_TOKEN,
                      oauth_token_secret=settings.TW_ACCESS_SECRET):
        res = {}
        account_id = data.get('account_id')
        line_item_id = data.get('line_item_id')

        if isinstance(line_item_id, (int, long)):
            line_item_id = int_to_base36(line_item_id)

        if isinstance(account_id, (int, long)):
            account_id = int_to_base36(account_id)

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        if line_item_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Line Item ID"
            }
            return res

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_token_secret)
        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX
        try:
            account = client.accounts(account_id)
            resource = '/{api_version}/accounts/{account_id}/line_items/{line_item_id}?count=1000&with_deleted=true'.format(
                api_version=settings.TW_API_VERSION,
                account_id=account.id,
                line_item_id=line_item_id)
            response = Request(client, 'get', resource).perform()
            res['data'] = response.body['data']
            res['success'] = True
        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success':
                False,
                'message':
                e.details[0]['message'] if e.details and e.details[0]
                and e.details[0]['message'] else '',
                'errors': {
                    str(code): True
                } if code else {}
            }
        except Exception as e:
            res = {'data': {}, 'success': False, 'message': str(e)}
        return res
    def fetch_app_cards(self,
                        data,
                        syncData=False,
                        oauth_token=settings.TW_ACCESS_TOKEN,
                        oauth_secret=settings.TW_ACCESS_SECRET):
        res = {}
        account_id = data.get('account_id')

        if isinstance(account_id, (int, long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)
        else:
            account_id_int = base36_to_int(account_id)

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_secret)
        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX
        try:
            res['data'] = []
            account = client.accounts(account_id)
            resource = '/{api_version}/accounts/{account_id}/cards/app_download'.format(
                api_version=settings.TW_API_VERSION, account_id=account.id)
            response = Request(client, 'get', resource).perform()
            for card in response.body['data']:
                res['data'].append(card)

            resource = '/{api_version}/accounts/{account_id}/cards/image_app_download'.format(
                api_version=settings.TW_API_VERSION, account_id=account.id)
            response = Request(client, 'get', resource).perform()
            for card in response.body['data']:
                res['data'].append(card)

            resource = '/{api_version}/accounts/{account_id}/cards/video_app_download'.format(
                api_version=settings.TW_API_VERSION, account_id=account.id)
            response = Request(client, 'get', resource).perform()

            if response.headers[
                    'x-rate-limit-remaining'] == "0" and settings.TW_RATE_LIMIT_ALERT:
                send_twitter_alert_email({
                    "account_id": account_id,
                    "endpoint": resource
                })

            for card in response.body['data']:
                res['data'].append(card)
            res['success'] = True

        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success':
                False,
                'message':
                e.details[0]['message'] if e.details and e.details[0]
                and e.details[0]['message'] else '',
                'errors': {
                    str(code): True
                } if code else {}
            }
        except Exception as e:
            res = {'data': {}, 'success': False, 'message': str(e)}

        if syncData and res['data'] and res['success']:
            res['sync'] = {}
            if isinstance(res['data'], (list, tuple)):
                sync_success = 0
                sync_fail = 0
                new_count = 0
                existing_count = 0
                for index, api_app_card in enumerate(res['data'], start=0):
                    app_card_res = self.sync_app_card(account_id_int,
                                                      api_app_card)

                    if 'success' in app_card_res and app_card_res[
                            'success'] is True:
                        if app_card_res['type'] == 'existing':
                            existing_count += 1
                        if app_card_res['type'] == 'new':
                            new_count += 1
                        sync_success += 1
                    elif 'success' in app_card_res and app_card_res[
                            'success'] is False:
                        sync_fail += 1

                res['sync']['type'] = {}
                res['sync']['type']['existing'] = existing_count
                res['sync']['type']['new'] = new_count
                res['sync']['total'] = sync_success
                if sync_fail == 0:
                    res['sync']['success'] = True
                else:
                    res['sync']['success'] = False

            elif isinstance(res['data'], dict):
                app_card_res = self.sync_app_card(account_id_int, res['data'])
                if 'success' in app_card_res and app_card_res[
                        'success'] is True:
                    res['data'] = app_card_res['data']
                    res['sync']['success'] = app_card_res['success']
                    res['sync']['type'] = {}
                    res['sync']['total'] = 1
                    res['sync']['type'][app_card_res['type']] = 1
                    # sync_success

                if 'success' in app_card_res and app_card_res[
                        'success'] is False:
                    res['data'] = app_card_res['data']
                    res['sync']['success'] = app_card_res['success']
                    res['sync']['message'] = app_card_res['message']

        return res
Example #34
0
import hashlib
from twitter_ads.client import Client
from twitter_ads.audience import CustomAudience

CONSUMER_KEY = 'your consumer key'
CONSUMER_SECRET = 'your consumer secret'
ACCESS_TOKEN = 'access token'
ACCESS_TOKEN_SECRET = 'access token secret'
ACCOUNT_ID = 'account id'

# initialize the client
client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN,
                ACCESS_TOKEN_SECRET)

# load the advertiser account instance
account = client.accounts(ACCOUNT_ID)

# create a new custom audience
audience = CustomAudience.create(account, 'test CA')

# sample user
# all values musth be sha256 hashed
email_hash = hashlib.sha256("*****@*****.**").hexdigest()

# create payload
user = [{
    "operation_type": "Update",
    "params": {
        "users": [{
            "email": [email_hash]
        }]
Example #35
0
from twitter_ads.cursor import Cursor
from twitter_ads.http import Request
from twitter_ads.error import Error

CONSUMER_KEY = 'your consumer key'
CONSUMER_SECRET = 'your consumer secret'
ACCESS_TOKEN = 'user access token'
ACCESS_TOKEN_SECRET = 'user access token secret'
ADS_ACCOUNT = 'ads account id'

# initialize the twitter ads api client
client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN,
                ACCESS_TOKEN_SECRET)

# load up the account instance
account = client.accounts(ADS_ACCOUNT)

# using the Request object you can manually request any
# twitter ads api resource that you want.

resource = '/' + API_VERSION + '/accounts/{account_id}/features'.format(
    account_id=account.id)
params = {'feature_keys': 'AGE_TARGETING,CPI_CHARGING'}

# try, build and execute the request with error handling
try:
    response = Request(client, 'get', resource, params=params).perform()
    print(response.body['data'][0])
except Error as e:
    # see twitter_ads.error for more details
    print(e.details)
    def create_update_campaign(self,
                               data,
                               oauth_token=settings.TW_ACCESS_TOKEN,
                               oauth_token_secret=settings.TW_ACCESS_SECRET,
                               request_type="post"):
        res = {}
        res['sync'] = {}
        res['success'] = False
        account_id = data.get('account_id')
        campaign_id = data.get('tw_campaign_id')

        if isinstance(campaign_id, (int, long)):
            campaign_id_int = campaign_id
            campaign_id = int_to_base36(campaign_id)

        if isinstance(account_id, (int, long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        if request_type == 'put':
            if campaign_id is None:
                res = {
                    'data': {},
                    'success': False,
                    'message': "Missing Twitter Campaign ID"
                }
                return res
        params = {}
        params['daily_budget_amount_local_micro'] = data.get(
            'daily_budget_amount_local_micro', None)
        params['duration_in_days'] = data.get('duration_in_days', None)
        params['end_time'] = data.get('end_time', None)
        params['frequency_cap'] = data.get('frequency_cap', None)
        params['funding_instrument_id'] = data.get('funding_instrument_id',
                                                   None)
        params['name'] = data.get('name', None)
        if data.get('paused', None) is not None:
            params['paused'] = 'true' if data.get('paused') else 'false'
        params['standard_delivery'] = str(data.get('standard_delivery')).lower(
        ) if data.get('standard_delivery') else None
        params['start_time'] = data.get('start_time', None)
        params['total_budget_amount_local_micro'] = data.get(
            'total_budget_amount_local_micro', None)

        # total_budget_amount_local_micro = 0 is not permitted
        if not params['total_budget_amount_local_micro']:
            params['total_budget_amount_local_micro'] = None

        params = dict((k, v) for k, v in params.iteritems()
                      if v is not None and v is not "")

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_token_secret)

        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX

        try:
            account = client.accounts(account_id)

            if request_type == 'put':
                resource = '/{api_version}/accounts/{account_id}/campaigns/{campaign_id}'.format(
                    api_version=settings.TW_API_VERSION,
                    account_id=account.id,
                    campaign_id=campaign_id)
            elif request_type == 'post':
                resource = '/{api_version}/accounts/{account_id}/campaigns'.format(
                    api_version=settings.TW_API_VERSION, account_id=account.id)

            response = Request(client, request_type, resource,
                               params=params).perform()

            if response.code == 200 or response.code == 201:
                res['success'] = True

            res['data'] = response.body['data']

            if res['data'] and res['success']:
                campaign_res = self.sync_campaign(account_id_int, res['data'])

                if 'success' in campaign_res and campaign_res[
                        'success'] is True:
                    res['data'] = campaign_res['data']
                    res['sync']['success'] = campaign_res['success']
                    res['sync']['type'] = {}
                    res['sync']['type'][campaign_res['type']] = 1
                    res['sync']['total'] = 1

                elif 'success' in campaign_res and campaign_res[
                        'success'] is False:
                    res['data'] = campaign_res['data']
                    res['sync']['success'] = campaign_res['success']
                    res['sync']['message'] = campaign_res['message']

        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success':
                False,
                'message':
                e.details[0]['message'] if e.details and e.details[0]
                and e.details[0]['message'] else '',
                'errors': {
                    str(code): True
                } if code else {}
            }
        except Exception as e:
            res = {'data': {}, 'success': False, 'message': str(e)}
        return res
from twitter_ads.client import Client
from twitter_ads.campaign import Tweet
from twitter_ads.creative import PromotedTweet, WebsiteCard

CONSUMER_KEY = 'your consumer key'
CONSUMER_SECRET = 'your consumer secret'
ACCESS_TOKEN = 'user access token'
ACCESS_TOKEN_SECRET = 'user access token secret'
ADS_ACCOUNT = 'ads account id'

# initialize the twitter ads api client
client = Client(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)

# load up the account instance, campaign and line item
account = client.accounts(ADS_ACCOUNT)
campaign = account.campaigns().next()
line_item = account.line_items(None, campaign_ids=campaign.id).next()

# create request for a simple nullcasted tweet
tweet1 = Tweet.create(account, text='There can be only one...')

# promote the tweet using our line item
promoted_tweet = PromotedTweet(account)
promoted_tweet.line_item_id = line_item.id
promoted_tweet.tweet_id = tweet1['id']
promoted_tweet.save()

# create request for a nullcasted tweet with a website card
website_card = WebsiteCard.all(account).next()
text = "Fine. There can be two. {card_url}".format(card_url=website_card.preview_url)
Example #38
0
    def fetch_line_items(self,
                         data,
                         syncData=False,
                         oauth_token=settings.TW_ACCESS_TOKEN,
                         oauth_token_secret=settings.TW_ACCESS_SECRET):
        res = {}
        res['data'] = []
        res['success'] = False
        account_id = data.get('account_id')
        campaign_id = data.get('campaign_id')
        line_item_id = data.get('line_item_id')
        campaign_id_int = None

        if isinstance(account_id, (int, long)):
            account_id_int = account_id
            account_id = int_to_base36(account_id)

        if isinstance(campaign_id, (int, long)):
            campaign_id_int = campaign_id
            campaign_id = int_to_base36(campaign_id)

        if isinstance(line_item_id, (int, long)):
            line_item_id = int_to_base36(line_item_id)

        if account_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Account ID"
            }
            return res

        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_token_secret)

        if settings.TW_SANDBOX:
            client.sandbox = settings.TW_SANDBOX

        try:
            account = client.accounts(account_id)
            resource = '/{api_version}/accounts/{account_id}/line_items?with_deleted=true'.format(
                api_version=settings.TW_API_VERSION, account_id=account.id)
            if campaign_id is not None:
                resource = '/{api_version}/accounts/{account_id}/line_items?campaign_ids={campaign_id}&count=1000&with_deleted=true'.format(
                    api_version=settings.TW_API_VERSION,
                    account_id=account.id,
                    campaign_id=campaign_id)

            response = Request(client, 'get', resource).perform()

            if response.headers[
                    'x-rate-limit-remaining'] == "0" and settings.TW_RATE_LIMIT_ALERT:
                send_twitter_alert_email({
                    "account_id": account_id,
                    "endpoint": resource
                })

            res['data'] = response.body['data']

            next_cursor = None
            if response.body['next_cursor'] and response.body[
                    'next_cursor'] is not 0:
                next_cursor = response.body['next_cursor']
                while next_cursor is not 0:
                    resource = '/{api_version}/accounts/{account_id}/line_items?cursor={next_cursor}&count=1000&with_deleted=true'.format(
                        api_version=settings.TW_API_VERSION,
                        account_id=account.id,
                        next_cursor=next_cursor)
                    if campaign_id is not None:
                        resource = '/{api_version}/accounts/{account_id}/line_items?campaign_ids={campaign_id}&count=1000&cursor={next_cursor}&with_deleted=true'.format(
                            api_version=settings.TW_API_VERSION,
                            account_id=account.id,
                            campaign_id=campaign_id,
                            next_cursor=next_cursor)

                    response = Request(client, 'get', resource).perform()
                    next_cursor = response.body['next_cursor'] or 0
                    res['data'] += response.body['data']

            res['success'] = True

        except Error as e:
            code = None
            if e.code:
                code = e.code
            elif e.details[0]['code']:
                code = e.details[0]['code']
            res = {
                'data': {},
                'success':
                False,
                'message':
                e.details[0]['message'] if e.details and e.details[0]
                and e.details[0]['message'] else '',
                'errors': {
                    str(code): True
                } if code else {}
            }
        except Exception as e:
            res = {'data': {}, 'success': False, 'message': str(e)}

        if syncData and res['data'] and res['success']:
            res['sync'] = {}
            if isinstance(res['data'], (list, tuple)):
                sync_success = 0
                sync_fail = 0
                new_count = 0
                existing_count = 0
                for index, api_line_item in enumerate(res['data'], start=0):
                    if campaign_id_int is None:
                        campaign_id_int = base36_to_int(
                            api_line_item['campaign_id'])

                    line_item_res = self.sync_line_item(
                        account_id_int, campaign_id_int, api_line_item)
                    if 'success' in line_item_res and line_item_res[
                            'success'] is True:
                        if line_item_res['type'] == 'existing':
                            existing_count += 1
                        if line_item_res['type'] == 'new':
                            new_count += 1
                        sync_success += 1

                    elif 'success' in line_item_res and line_item_res[
                            'success'] is False:
                        sync_fail += 1
                res['sync']['type'] = {}
                res['sync']['type']['existing'] = existing_count
                res['sync']['type']['new'] = new_count
                res['sync']['total'] = sync_success
                if sync_fail == 0:
                    res['sync']['success'] = True
                else:
                    res['sync']['success'] = False

            elif isinstance(res['data'], dict):
                line_item_res = self.sync_line_item(account_id_int,
                                                    campaign_id_int,
                                                    res['data'])

                if 'success' in line_item_res and line_item_res[
                        'success'] is True:
                    res['data'] = line_item_res['data']
                    res['sync']['success'] = line_item_res['success']
                    res['sync']['type'] = {}
                    res['sync']['total'] = 1
                    res['sync']['type'][line_item_res['type']] = 1

                elif 'success' in line_item_res and line_item_res[
                        'success'] is False:
                    res['data'] = line_item_res['data']
                    res['sync']['success'] = line_item_res['success']
                    res['sync']['message'] = line_item_res['message']
        return res