twitterdev/twitter-python-ads-sdk

View on GitHub
twitter_ads/campaign.py

Summary

Maintainability
F
5 days
Test Coverage
# Copyright (C) 2015 Twitter, Inc.

"""Container for all campaign management logic used by the Ads API SDK."""

from twitter_ads.enum import TRANSFORM
from twitter_ads.analytics import Analytics
from twitter_ads.resource import resource_property, Resource, Persistence, Batch
from twitter_ads.http import Request
from twitter_ads.cursor import Cursor
from twitter_ads.utils import FlattenParams
from twitter_ads import API_VERSION


class TargetingCriteria(Resource, Persistence, Batch):

    PROPERTIES = {}

    BATCH_RESOURCE_COLLECTION = '/' + API_VERSION + '/batch/accounts/{account_id}/\
targeting_criteria'
    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/targeting_criteria'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/targeting_criteria/{id}'
    RESOURCE_OPTIONS = '/' + API_VERSION + '/targeting_criteria/'

    @classmethod
    @FlattenParams
    def all(klass, account, **kwargs):
        """Returns a Cursor instance for a given resource."""
        resource = klass.RESOURCE_COLLECTION.format(account_id=account.id)
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(klass, request, init_with=[account])

    @classmethod
    def app_store_categories(klass, account, **kwargs):
        """Returns a list of supported app store categories"""
        resource = klass.RESOURCE_OPTIONS + 'app_store_categories'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def behavior_taxonomies(klass, account, **kwargs):
        """Returns a list of supported behavior taxonomies"""
        resource = klass.RESOURCE_OPTIONS + 'behavior_taxonomies'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def behaviors(klass, account, **kwargs):
        """Returns a list of supported behaviors"""
        resource = klass.RESOURCE_OPTIONS + 'behaviors'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def conversations(klass, account, **kwargs):
        """Returns a list of supported conversations"""
        resource = klass.RESOURCE_OPTIONS + 'conversations'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def devices(klass, account, **kwargs):
        """Returns a list of supported devices"""
        resource = klass.RESOURCE_OPTIONS + 'devices'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def events(klass, account, **kwargs):
        """Returns a list of supported events"""
        resource = klass.RESOURCE_OPTIONS + 'events'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def interests(klass, account, **kwargs):
        """Returns a list of supported interests"""
        resource = klass.RESOURCE_OPTIONS + 'interests'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def languages(klass, account, **kwargs):
        """Returns a list of supported languages"""
        resource = klass.RESOURCE_OPTIONS + 'languages'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def locations(klass, account, **kwargs):
        """Returns a list of supported locations"""
        resource = klass.RESOURCE_OPTIONS + 'locations'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def network_operators(klass, account, **kwargs):
        """Returns a list of supported network operators"""
        resource = klass.RESOURCE_OPTIONS + 'network_operators'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def platforms(klass, account, **kwargs):
        """Returns a list of supported platforms"""
        resource = klass.RESOURCE_OPTIONS + 'platforms'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def platform_versions(klass, account, **kwargs):
        """Returns a list of supported platform versions"""
        resource = klass.RESOURCE_OPTIONS + 'platform_versions'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def tv_markets(klass, account, **kwargs):
        """Returns a list of supported TV markets"""
        resource = klass.RESOURCE_OPTIONS + 'tv_markets'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)

    @classmethod
    def tv_shows(klass, account, **kwargs):
        """Returns a list of supported TV shows"""
        resource = klass.RESOURCE_OPTIONS + 'tv_shows'
        request = Request(account.client, 'get', resource, params=kwargs)
        return Cursor(None, request)


# targeting criteria properties
# read-only
resource_property(TargetingCriteria, 'id', readonly=True)
resource_property(TargetingCriteria, 'name', readonly=True)
resource_property(TargetingCriteria, 'localized_name', readonly=True)
resource_property(TargetingCriteria, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TargetingCriteria, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TargetingCriteria, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
# writable
resource_property(TargetingCriteria, 'line_item_id')
resource_property(TargetingCriteria, 'operator_type')
resource_property(TargetingCriteria, 'targeting_type')
resource_property(TargetingCriteria, 'targeting_value')
# sdk-only
resource_property(TargetingCriteria, 'to_delete', transform=TRANSFORM.BOOL)


class FundingInstrument(Analytics, Resource, Persistence):

    PROPERTIES = {}

    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/funding_instruments'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/funding_instruments/{id}'


# funding instrument properties
# read-only
resource_property(FundingInstrument, 'id', readonly=True)
resource_property(FundingInstrument, 'name', readonly=True)
resource_property(FundingInstrument, 'credit_limit_local_micro', readonly=True)
resource_property(FundingInstrument, 'currency', readonly=True)
resource_property(FundingInstrument, 'description', readonly=True)
resource_property(FundingInstrument, 'funded_amount_local_micro', readonly=True)
resource_property(FundingInstrument, 'type', readonly=True)
resource_property(FundingInstrument, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(FundingInstrument, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(FundingInstrument, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(FundingInstrument, 'able_to_fund', readonly=True, transform=TRANSFORM.BOOL)
resource_property(FundingInstrument, 'entity_status', readonly=True)
resource_property(FundingInstrument, 'io_header', readonly=True)
resource_property(FundingInstrument, 'reasons_not_able_to_fund', readonly=True,
                  transform=TRANSFORM.LIST)
resource_property(FundingInstrument, 'start_time', readonly=True)
resource_property(FundingInstrument, 'end_time', readonly=True)
resource_property(FundingInstrument, 'credit_remaining_local_micro', readonly=True)


class PromotableUser(Resource):

    PROPERTIES = {}

    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/promotable_users'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/promotable_users/{id}'


# promotable user properties
# read-only
resource_property(PromotableUser, 'id', readonly=True)
resource_property(PromotableUser, 'promotable_user_type', readonly=True)
resource_property(PromotableUser, 'user_id', readonly=True)
resource_property(PromotableUser, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(PromotableUser, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(PromotableUser, 'deleted', readonly=True, transform=TRANSFORM.BOOL)


class AppList(Resource, Persistence):

    PROPERTIES = {}

    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/app_lists'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/app_lists/{id}'

    def apps(self):
        if self.id and not hasattr(self, '_apps'):
            self.reload()
        return self._apps


# app list properties
# read-only
resource_property(AppList, 'id', readonly=True)
resource_property(AppList, 'name', readonly=True)
resource_property(AppList, 'apps', readonly=True)


class Campaign(Analytics, Resource, Persistence, Batch):

    PROPERTIES = {}

    BATCH_RESOURCE_COLLECTION = '/' + API_VERSION + '/batch/accounts/{account_id}/campaigns'
    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/campaigns'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/campaigns/{id}'


# campaign properties
# read-only
resource_property(Campaign, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(Campaign, 'currency', readonly=True)
resource_property(Campaign, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(Campaign, 'effective_status', readonly=True)
resource_property(Campaign, 'id', readonly=True)
resource_property(Campaign, 'reasons_not_servable', readonly=True)
resource_property(Campaign, 'servable', readonly=True, transform=TRANSFORM.BOOL)
resource_property(Campaign, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
# writable
resource_property(Campaign, 'daily_budget_amount_local_micro')
resource_property(Campaign, 'duration_in_days', transform=TRANSFORM.INT)
resource_property(Campaign, 'entity_status')
resource_property(Campaign, 'frequency_cap', transform=TRANSFORM.INT)
resource_property(Campaign, 'funding_instrument_id')
resource_property(Campaign, 'name')
resource_property(Campaign, 'standard_delivery', transform=TRANSFORM.BOOL)
resource_property(Campaign, 'total_budget_amount_local_micro')
resource_property(Campaign, 'budget_optimization')
# sdk-only
resource_property(Campaign, 'to_delete', transform=TRANSFORM.BOOL)


class LineItem(Analytics, Resource, Persistence, Batch):

    PROPERTIES = {}

    BATCH_RESOURCE_COLLECTION = '/' + API_VERSION + '/batch/accounts/{account_id}/line_items'
    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/line_items'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/line_items/{id}'

    def targeting_criteria(self, id=None, **kwargs):
        """
        Returns a collection of targeting criteria available to the
        current line item.
        """
        self._validate_loaded()
        if id is None:
            return TargetingCriteria.all(self.account, line_item_ids=[self.id], **kwargs)
        else:
            return TargetingCriteria.load(self.account, id, **kwargs)

    def save(self):
        super(LineItem, self).save()


# line item properties
# read-only
resource_property(LineItem, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(LineItem, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(LineItem, 'id', readonly=True)
resource_property(LineItem, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(LineItem, 'creative_source', readonly=True)
resource_property(LineItem, 'currency', readonly=True)
resource_property(LineItem, 'target_cpa_local_micro', readonly=True)
# writable
resource_property(LineItem, 'advertiser_domain')
resource_property(LineItem, 'advertiser_user_id')
resource_property(LineItem, 'bid_amount_local_micro')
resource_property(LineItem, 'bid_strategy')
resource_property(LineItem, 'campaign_id')
resource_property(LineItem, 'categories', transform=TRANSFORM.LIST)
resource_property(LineItem, 'end_time', transform=TRANSFORM.TIME)
resource_property(LineItem, 'entity_status')
resource_property(LineItem, 'goal')
resource_property(LineItem, 'ios_app_store_identifier')
resource_property(LineItem, 'android_app_store_identifier')
resource_property(LineItem, 'audience_expansion')
resource_property(LineItem, 'name')
resource_property(LineItem, 'objective')
resource_property(LineItem, 'pay_by')
resource_property(LineItem, 'placements', transform=TRANSFORM.LIST)
resource_property(LineItem, 'primary_web_event_tag')
resource_property(LineItem, 'product_type')
resource_property(LineItem, 'start_time', transform=TRANSFORM.TIME)
resource_property(LineItem, 'total_budget_amount_local_micro')
resource_property(LineItem, 'tracking_tags')
resource_property(Campaign, 'standard_delivery', transform=TRANSFORM.BOOL)
# sdk-only
resource_property(LineItem, 'to_delete', transform=TRANSFORM.BOOL)


class LineItemApps(Resource, Persistence):

    PROPERTIES = {}

    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/line_item_apps'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/line_item_apps/{id}'


resource_property(LineItemApps, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(LineItemApps, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(LineItemApps, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(LineItemApps, 'id', readonly=True)
resource_property(LineItemApps, 'os_type', readonly=True)
resource_property(LineItemApps, 'app_store_identifier', readonly=True)
resource_property(LineItemApps, 'line_item_id', readonly=True)


class LineItemPlacements(Resource):

    PROPERTIES = {}
    RESOURCE_COLLECTION = '/' + API_VERSION + '/line_items/placements'


resource_property(LineItemPlacements, 'product_type', readonly=True)
resource_property(LineItemPlacements, 'placements', readonly=True)


class ScheduledPromotedTweet(Resource, Persistence):

    PROPERTIES = {}

    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/scheduled_promoted_tweets'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/scheduled_promoted_tweets/{id}'


# scheduled promoted tweets properties
# read-only
resource_property(ScheduledPromotedTweet, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(ScheduledPromotedTweet, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(ScheduledPromotedTweet, 'id', readonly=True)
resource_property(ScheduledPromotedTweet, 'tweet_id', readonly=True)
resource_property(ScheduledPromotedTweet, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
# writable
resource_property(ScheduledPromotedTweet, 'line_item_id')
resource_property(ScheduledPromotedTweet, 'scheduled_tweet_id')


class TrackingTags(Resource, Persistence):

    PROPERTIES = {}

    RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/tracking_tags'
    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/tracking_tags/{id}'


# tracking tags properties
# read-only
resource_property(TrackingTags, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(TrackingTags, 'id', readonly=True)
resource_property(TrackingTags, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(TrackingTags, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
# writable
resource_property(TrackingTags, 'line_item_id')
resource_property(TrackingTags, 'tracking_tag_type')
resource_property(TrackingTags, 'tracking_tag_url')


class Tweet(object):

    TWEET_CREATE = '/' + API_VERSION + '/accounts/{account_id}/tweet'

    def __init__(self):
        raise NotImplementedError(
            'Error! {name} cannot be instantiated.'.format(name=self.__class__.__name__))

    @classmethod
    @FlattenParams
    def create(klass, account, **kwargs):
        """
        Creates a "Promoted-Only" Tweet using the specialized Ads API end point.
        """
        resource = klass.TWEET_CREATE.format(account_id=account.id)
        response = Request(account.client, 'post', resource, params=kwargs).perform()
        return response.body['data']


class UserSettings(Resource, Persistence):

    PROPERTIES = {}

    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/user_settings/{id}'


# user settings properties
# writable
resource_property(UserSettings, 'notification_email')
resource_property(UserSettings, 'contact_phone')
resource_property(UserSettings, 'contact_phone_extension')
resource_property(UserSettings, 'subscribed_email_types')
resource_property(UserSettings, 'user_id')


class TaxSettings(Resource, Persistence):

    PROPERTIES = {}

    RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/tax_settings'

    @classmethod
    def load(self, account):
        """
        Returns an object instance for a given account.
        """
        resource = self.RESOURCE.format(account_id=account.id)
        response = Request(account.client, 'get', resource).perform()
        return self(account).from_response(response.body['data'])

    def save(self):
        """
        Update the current object instance.
        """
        resource = self.RESOURCE.format(account_id=self.account.id)
        response = Request(
            self.account.client, 'put',
            resource, params=self.to_params()).perform()
        return self.from_response(response.body['data'])


# tax settings properties
# writable
resource_property(TaxSettings, 'address_city')
resource_property(TaxSettings, 'address_country')
resource_property(TaxSettings, 'address_email')
resource_property(TaxSettings, 'address_first_name')
resource_property(TaxSettings, 'address_last_name')
resource_property(TaxSettings, 'address_name')
resource_property(TaxSettings, 'address_postal_code')
resource_property(TaxSettings, 'address_region')
resource_property(TaxSettings, 'address_street1')
resource_property(TaxSettings, 'address_street2')
resource_property(TaxSettings, 'bill_to')
resource_property(TaxSettings, 'business_relationship')
resource_property(TaxSettings, 'client_address_city')
resource_property(TaxSettings, 'client_address_country')
resource_property(TaxSettings, 'client_address_email')
resource_property(TaxSettings, 'client_address_first_name')
resource_property(TaxSettings, 'client_address_last_name')
resource_property(TaxSettings, 'client_address_name')
resource_property(TaxSettings, 'client_address_postal_code')
resource_property(TaxSettings, 'client_address_region')
resource_property(TaxSettings, 'client_address_street1')
resource_property(TaxSettings, 'client_address_street2')
resource_property(TaxSettings, 'invoice_jurisdiction')
resource_property(TaxSettings, 'tax_category')
resource_property(TaxSettings, 'tax_exemption_id')
resource_property(TaxSettings, 'tax_id')


class ContentCategories(Resource):

    PROPERTIES = {}
    RESOURCE_COLLECTION = '/' + API_VERSION + '/content_categories'


resource_property(ContentCategories, 'id', readonly=True)
resource_property(ContentCategories, 'name', readonly=True)
resource_property(ContentCategories, 'iab_categories', readonly=True)


class IabCategories(Resource):

    PROPERTIES = {}
    RESOURCE_COLLECTION = '/' + API_VERSION + '/iab_categories'


resource_property(IabCategories, 'id', readonly=True)
resource_property(IabCategories, 'name', readonly=True)
resource_property(IabCategories, 'parent_id', readonly=True)


class AdvertiserBusinessCategories(Resource):

    PROPERTIES = {}
    RESOURCE_COLLECTION = '/' + API_VERSION + '/advertiser_business_categories'


resource_property(ContentCategories, 'id', readonly=True)
resource_property(ContentCategories, 'name', readonly=True)
resource_property(ContentCategories, 'iab_categories', readonly=True)