コード例 #1
0
class App(BaseReadonlyModelMixin, BaseModel):
    app_id = models.AutoField(primary_key=True)
    publisher_id = models.ForeignKey(Publisher, db_column='publisher_id')
    app = models.CharField(max_length=255)
    os = models.CharField(max_length=7, choices=OS_CHOICES)  # pylint: disable=invalid-name
    app_url = models.CharField(max_length=255)
    category1 = models.CharField(max_length=255)
    category2 = models.CharField(max_length=255)
    bcat = models.TextField()
    badv = models.TextField()
    battr = models.CharField(max_length=255)
    deleted = models.BooleanField(default=False)
    date_added = DateTimeField()
    date_modified = DateTimeField()
    cost_method = models.CharField(max_length=8,
                                   default=COST_METHOD_REVSHARE,
                                   choices=COST_METHOD_CHOICES)
    cpm = models.FloatField(default=0.0)
    revshare = models.FloatField(default=0.6)
    cost_map = models.TextField()
    bid_floor_map = models.TextField()
    bg_frames = models.TextField()
    video_enabled = models.BooleanField(default=True)
    tier1_approved = models.BooleanField(default=False)

    objects = AppManager()
    objects_raw = models.Manager()

    class Meta:
        managed = True
        db_table = 'app'
        app_label = 'restapi'

    def __unicode__(self):
        return self.os + " - " + self.app
コード例 #2
0
class Zone(BaseModel):
    zone_id = models.AutoField(primary_key=True)
    app_id = models.ForeignKey(App, db_column='app_id')
    zone = models.CharField(max_length=255, default='')
    orientation = models.CharField(max_length=9, choices=ZONE_ORIENTATION_CHOICES, default=ZONE_ORIENTATION_BOTH)
    status = models.CharField(max_length=7, choices=ZONE_STATUS_CHOICES, default=ZONE_STATUS_LIVE)
    deleted = models.BooleanField(default=False)
    date_added = DateTimeField(auto_now_add=True)
    date_modified = DateTimeField(auto_now=True)
    cost_method = models.CharField(max_length=8, choices=COST_METHOD_CHOICES, default=COST_METHOD_BLANK)
    cpm = models.FloatField(default=0.0)
    revshare = models.FloatField(default=0.0)
    cost_map = models.TextField(default="")
    bid_floor_map = models.TextField(default="")
    custom_priority = models.TextField(default="")
    size = models.CharField(max_length=8, choices=ZONE_SIZE_CHOICES, default=ZONE_SIZE_BLANK)
    callback_url = models.CharField(max_length=255, default='')
    ad_type = models.IntegerField(choices=ZONE_AD_TYPE_CHOICES, default=ZONE_AD_TYPE_DISPLAY_VAST_VOXEL)
    security_key = models.CharField(max_length=100, null=True, default='')
    video_type = models.IntegerField(default=0)
    locked = models.BooleanField(default=False)

    objects = ZoneManager()
    objects_raw = models.Manager()


    class Meta:
        managed = True
        db_table = 'zone'
        app_label = 'restapi'

    def __unicode__(self):
        title = u'{0} - {1} ({2})'.format(self.zone, self.orientation, self.app)
        return title.encode('ascii', 'ignore')

    @property
    def encrypted_key(self):
        return encrypt(self.zone_id)

    @property
    # pylint: disable=invalid-name
    def os(self):
        return self.app_id.os

    @property
    def app(self):
        return self.app_id.app

    @property
    def ad_type_title(self):
        return dict(ZONE_AD_TYPE_CHOICES)[self.ad_type]
コード例 #3
0
class TradingDesk(BaseModel):
    trading_desk_id = models.AutoField(primary_key=True)
    trading_desk = models.CharField(max_length=255)
    trading_desk_key = models.CharField(max_length=40,
                                        default=ApiKeyGenerator.key_generator)
    account_manager = models.IntegerField(max_length=10, default=0)
    currency = models.CharField(max_length=3, default=CURRENCY_USD)
    contact = models.CharField(max_length=100)
    address1 = models.CharField(max_length=255, default='', blank=True)
    address2 = models.CharField(max_length=255, default='', blank=True)
    city = models.CharField(max_length=100, default='', blank=True)
    state_prov = models.CharField(max_length=100, default='', blank=True)
    zip = models.CharField(max_length=10, default='', blank=True)
    country = models.CharField(max_length=3,
                               choices=COUNTRIES,
                               default=COUNTRIES[0][0])
    phone = models.CharField(max_length=20, default='', blank=True)
    email = models.CharField(max_length=255, default='', blank=True)
    notes = models.TextField(blank=True, default='')
    status = models.CharField(max_length=8,
                              choices=STATUS_CHOICES,
                              default=STATUS_ENABLED)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TradingDeskManager()
    objects_raw = models.Manager()
    permission_check = True

    def is_own(self):
        # have no sence for new trading desk
        if self.pk is None:
            return True
        else:
            return bool(
                self.trading_desk_userprofiles.filter(user=REGISTRY['user']))

    @property
    def is_manage_trading_desk(self):
        return self.pk == MANAGE_TRADING_DESK_ID

    def __unicode__(self):
        return self.trading_desk

    class Meta:
        # managed=False
        db_table = 'trading_desk'
        app_label = 'restapi'
        ordering = ['trading_desk']
コード例 #4
0
class BidderWhitelistIds(BaseModel):
    id = models.AutoField(primary_key=True, db_column='id')
    placement_type = models.CharField(max_length=4, choices=PLACEMENT_TYPE_CHOICES)
    placement_id = models.CharField(max_length=128)
    tag = models.CharField(max_length=128, default='', blank=True, null=True)
    last_update = DateTimeField(default=None, auto_now=True)
    campaign_id = models.IntegerField(default=0)
    ad_group_id = models.IntegerField(default=0)
    source_id = models.IntegerField(default=0)
    size = SizeCharField(max_length=8, choices=SIZE_CHOICES, null=True, default=None, blank=True)

    objects = BidderWhitelistManager()
    objects_raw = models.Manager()
    permission_check = True

    def is_own(self):
        return PlacementHelper.is_own(self.campaign_id, self.ad_group_id)

    @classmethod
    def get_perm_model_name(self):
        return BidderWhitelist.get_perm_model_name()

    def __unicode__(self):
        return self.placement_id

    class Meta:
        managed = True
        app_label = 'restapi'
        db_table = 'bidder_whitelist'
        ordering = ['-last_update']
        unique_together = ('campaign_id', 'ad_group_id', 'source_id', 'placement_type', 'placement_id')
コード例 #5
0
class BidderWhitelist(BaseModel, BaseReadonlyModelMixin):
    id = models.AutoField(primary_key=True, db_column='id')
    placement_type = models.CharField(max_length=4, choices=PLACEMENT_TYPE_CHOICES)
    placement_id = models.CharField(max_length=128)
    tag = models.CharField(max_length=128, default='', blank=True, null=True)
    last_update = DateTimeField(default=None, auto_now=True)
    advertiser_id = models.IntegerField()
    campaign_id = models.IntegerField()
    campaign = models.CharField(max_length=255)
    ad_group_id = models.IntegerField()
    ad_group = models.CharField(max_length=255)
    source_id = models.IntegerField()
    source = models.CharField(max_length=255)
    size = SizeCharField(max_length=8, choices=SIZE_CHOICES, null=True, default=None, blank=True)

    objects = BidderWhitelistManager()
    objects_raw = models.Manager()
    permission_check = True

    def is_own(self):
        return PlacementHelper.is_own(self.campaign_id, self.ad_group_id)

    def autopopulate_by_ownership(self):
        pass

    def __unicode__(self):
        return self.placement_id

    class Meta:
        managed = False
        app_label = 'restapi'
        db_table = 'bidder_whitelist_view'
        ordering = ['-last_update']
        unique_together = ('campaign_id', 'ad_group_id', 'source_id', 'placement_type', 'placement_id')
コード例 #6
0
class TwitterRevmap(BaseModel):
    revmap_id = models.AutoField(primary_key=True, db_column='id')
    campaign_id = models.OneToOneField(Campaign,
                                       db_column='campaign_id',
                                       related_name='revmap')
    tw_campaign_id = models.ForeignKey(TwitterCampaign.TwitterCampaign,
                                       default=0,
                                       db_constraint=False,
                                       db_column='tw_campaign_id')
    tw_line_item_id = models.ForeignKey(TwitterLineItem.TwitterLineItem,
                                        default=0,
                                        db_constraint=False,
                                        db_column='tw_line_item_id')
    opt_type = models.CharField(max_length=10,
                                blank=True,
                                choices=OPT_TYPE_CHOICES,
                                default=OPT_TYPE_CHOICES[3][0])
    opt_value = models.DecimalField(max_digits=9, decimal_places=4, default=0)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TwitterRevmapManager()
    objects_raw = models.Manager()

    def __unicode__(self):
        return self.campaign_id

    class Meta:
        managed = True
        db_table = 'tw_revmap'
        app_label = 'restapi'
        unique_together = ('campaign_id', 'tw_campaign_id', 'tw_line_item_id')
コード例 #7
0
class TwitterUser(BaseModel):
    tw_twitter_user_id = models.BigIntegerField(primary_key=True)
    name = models.CharField(max_length=255)
    timezone = models.CharField(max_length=255)
    oauth_token = models.CharField(max_length=255)
    oauth_secret = models.CharField(max_length=255)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TwitterUserManager()
    objects_raw = models.Manager()
    # permission_check = True

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'tw_twitter_user'
        app_label = 'restapi'
コード例 #8
0
class DiscretePricing(BaseModel):
    id = models.AutoField(primary_key=True)
    placement_type = models.CharField(max_length=4,
                                      choices=PLACEMENT_TYPE_CHOICES,
                                      default=PLACEMENT_TYPE_ALL)
    placement_id = models.CharField(max_length=128, default='all')
    tag = models.CharField(max_length=128, blank=True, null=True, default='')
    size = models.CharField(max_length=8,
                            choices=DISCRETE_PRICING_SIZE_CHOICES,
                            default=SIZE_ALL)
    rev_value = models.FloatField()
    created_at = DateTimeField(default=None, auto_now_add=True)
    last_update = DateTimeField(default=None, auto_now=True)
    advertiser_id = models.IntegerField()
    campaign_id = models.IntegerField()
    campaign = models.CharField(max_length=255)
    ad_group_id = models.IntegerField()
    ad_group = models.CharField(max_length=255)
    source_id = models.IntegerField()
    source = models.CharField(max_length=255)

    objects = DiscretePricingManager()
    objects_raw = models.Manager()
    permission_check = False

    def __unicode__(self):
        return self.placement_id

    def is_own(self):
        return PlacementHelper.is_own(self.campaign_id, self.ad_group_id)

    def autopopulate_by_ownership(self):
        pass

    class Meta:
        managed = False
        db_table = 'discrete_pricing_view'
        app_label = 'restapi'
        ordering = ['-last_update']
        unique_together = ('campaign_id', 'ad_group_id', 'source_id',
                           'placement_type', 'placement_id')
コード例 #9
0
class CustomHintIds(BaseModel):
    id = models.AutoField(primary_key=True)
    size = models.CharField(max_length=8,
                            choices=CUSTOM_HINT_SIZE_CHOICES,
                            default=SIZE_ALL)
    placement_type = models.CharField(max_length=4,
                                      choices=PLACEMENT_TYPE_CHOICES,
                                      default=PLACEMENT_TYPE_ALL)
    placement_id = models.CharField(max_length=128, default='all')
    inflator_type = models.CharField(max_length=8,
                                     choices=INFLATOR_TYPE_CHOICES,
                                     null=True,
                                     default=None)
    inflator = models.DecimalField(max_digits=9,
                                   decimal_places=6,
                                   null=True,
                                   default=None)
    priority = models.IntegerField(default=0)
    max_frequency = models.IntegerField(default=0)
    frequency_interval = models.IntegerField(default=0)
    start_date = WideRangeDateTimeField(default=timezone(
        settings.TIME_ZONE).localize(datetime(datetime.now().year, 1, 1)))
    end_date = WideRangeDateTimeField(default=timezone(
        settings.TIME_ZONE).localize(datetime(datetime.now().year, 12, 31)))
    tag = models.CharField(max_length=128, blank=True, null=True, default=None)
    last_update = DateTimeField(default=None, auto_now=True)
    campaign_id = models.IntegerField(default=0)
    ad_group_id = models.IntegerField(default=0)
    ad_id = models.IntegerField(default=0)
    source_id = models.IntegerField(default=0)

    objects = CustomHintManager()
    objects_raw = models.Manager()
    permission_check = True

    def __unicode__(self):
        return self.placement_id

    @classmethod
    def get_perm_model_name(self):
        return CustomHint.get_perm_model_name()

    def is_own(self):
        return PlacementHelper.is_own(self.campaign_id, self.ad_group_id)

    class Meta:
        managed = True
        db_table = 'custom_hint'
        app_label = 'restapi'
        ordering = ['-last_update']
        unique_together = ('campaign_id', 'ad_group_id', 'ad_id', 'source_id',
                           'size', 'placement_type', 'placement_id')
コード例 #10
0
class Revmap(BaseModel):
    revmap_id = models.AutoField(primary_key=True, db_column='id')
    ad_group_id = models.OneToOneField(AdGroup, db_column='ad_group_id', related_name='revmap')
    ad_group = models.CharField(max_length=255)
    campaign_id = models.IntegerField(blank=False, null=False, default=None)
    campaign = models.CharField(max_length=255)
    opt_type = models.CharField(max_length=10,
                                blank=True,
                                choices=OPT_TYPE_CHOICES,
                                default=OPT_TYPE_CHOICES[3][0])
    opt_value = models.DecimalField(max_digits=9, decimal_places=4, default=0)
    rev_type = models.CharField(max_length=10,
                                blank=True,
                                choices=OPT_TYPE_CHOICES,
                                default=OPT_TYPE_CHOICES[3][0])
    rev_value = models.DecimalField(max_digits=9, decimal_places=4, default=0)
    target_type = models.CharField(max_length=10,
                                   blank=True,
                                   choices=OPT_TYPE_CHOICES,
                                   default=OPT_TYPE_CHOICES[3][0])
    target_value = models.DecimalField(max_digits=9, decimal_places=4, default=0)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = RevmapManager()
    objects_raw = models.Manager()

    def __unicode__(self):
        return self.ad_group

    def make_copy(self):
        rejected_fields = lambda x: x.__class__ is models.AutoField or x.name == 'pk'
        values = [
            (f.name, getattr(self, f.name)) for f in self._meta.fields if not rejected_fields(f)
        ]
        initials = dict([(k, v) for k, v in values if v is not None])
        # pylint: disable=invalid-name
        m = self.__class__(**initials)
        # pylint: disable=invalid-name
        m.pk = None
        return m

    class Meta:
        managed = True
        db_table = 'revmap'
        app_label = 'restapi'
コード例 #11
0
class ManageUser(BaseModel):
    user_id = models.AutoField(primary_key=True)
    role_id = models.ForeignKey(Role, db_column='role_id')
    full_name = models.CharField(max_length=255, blank=True)
    email = models.CharField(max_length=255, blank=True)
    password_salt = models.BinaryField(max_length=16, blank=True)
    password_hash = models.BinaryField(max_length=20, blank=True)
    create_time = DateTimeField(null=True, default=None)
    last_log_in_time = ZeroDateTimeField(default=None, null=True, blank=True)

    objects = ManageUserManager()
    objects_raw = models.Manager()

    def __unicode__(self):
        return self.email

    class Meta:
        managed = True
        unique_together = ('full_name', 'email')
        db_table = 'user'
        app_label = 'restapi'
コード例 #12
0
ファイル: Ad.py プロジェクト: webcomet/python_django_restapi
class Ad(BaseModel):
    ad_id = models.AutoField(primary_key=True)
    ad_group_id = models.ForeignKey(AdGroup, db_column='ad_group_id')
    creative_id = models.IntegerField(blank=True, null=True)
    ad = models.CharField(max_length=255)  # pylint: disable=invalid-name
    size = models.CharField(max_length=10, choices=AD_SIZE_CHOICES)
    html = models.TextField(blank=True)
    preview_html = models.TextField(blank=True)
    bid = models.DecimalField(max_digits=9,
                              decimal_places=6,
                              blank=True,
                              default=0)
    targeting = models.TextField(blank=True)
    categories = models.TextField(blank=True)
    attrs = models.CharField(max_length=255, blank=True)
    inflator_text = models.TextField(blank=True)
    domain = models.CharField(max_length=255, blank=True)
    redirect_url = models.CharField(max_length=1024, blank=True)

    status = models.CharField(max_length=8,
                              choices=STATUS_CHOICES,
                              default=STATUS_CHOICES[1][0])

    adx_status = models.CharField(max_length=11,
                                  choices=AD_STATUS_CHOICES,
                                  default=AD_STATUS_CHOICES[0][0])

    appnexus_status = models.CharField(max_length=11,
                                       choices=AD_STATUS_CHOICES,
                                       default=AD_STATUS_CHOICES[0][0])

    a9_status = models.CharField(max_length=11,
                                 choices=A9_STATUS_CHOICES,
                                 default=A9_STATUS_PASSED)

    external_args = models.TextField(blank=True)
    ad_type = models.IntegerField(default=1)
    adx_sensitive_categories = models.TextField(blank=True)
    adx_product_categories = models.TextField(blank=True)
    i_url = models.CharField(max_length=1024, blank=True, null=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)
    created_time = DateTimeField(auto_now_add=True)

    adx_attrs = models.CharField(max_length=255, default='', blank=True)
    tag = models.CharField(max_length=255, default='', blank=True)

    objects = AdManager()
    objects_raw = models.Manager()
    permission_check = True

    actions = ('bulk', 'bulk_re_submit_to_adx', 'export')

    search_args = ('ad_id', )

    @property
    def search_result(self):
        return {
            'level': 'ad',
            'ad': self.ad,
            'ad_id': self.ad_id,
            'ad_type': self.ad_type,
            'ad_group_id': self.ad_group_id.pk,
            'campaign_id': self.campaign_id,
            'advertiser_id': self.ad_group_id.campaign_id.advertiser_id.pk,
            'creative_id': self.creative_id,
            'bid': self.bid,
            'last_update': self.last_update
        }

    def is_own(self):
        """Returns True if ad entity belongs to the current user."""
        advertiser_ids = REGISTRY.get('user_advertiser_ids')
        if advertiser_ids and Ad.objects.filter(
                ad_group_id__campaign_id__advertiser_id__in=advertiser_ids,
                ad_id=self.ad_id).exists():
            return True

        agency_ids = REGISTRY.get('user_agency_ids')
        if agency_ids and Ad.objects.filter(
                ad_group_id__campaign_id__advertiser_id__agency_id__in=
                agency_ids,
                ad_id=self.ad_id).exists():
            return True

        trading_desk_ids = REGISTRY.get('user_trading_desk_ids')
        if trading_desk_ids and Ad.objects.filter(
                ad_group_id__campaign_id__advertiser_id__agency_id__trading_desk_id__in
                =trading_desk_ids,
                ad_id=self.ad_id).exists():
            return True

        return False

    def autopopulate_by_ownership(self):
        pass

    @property
    def ad_group(self):
        return self.ad_group_id.ad_group

    @property
    def campaign_id(self):
        return self.ad_group_id.campaign_id.campaign_id

    @property
    def campaign(self):
        return self.ad_group_id.campaign_id.campaign

    @property
    def advertiser_id(self):
        return self.ad_group_id.campaign_id.advertiser_id.advertiser_id

    @property
    def advertiser(self):
        return self.ad_group_id.campaign_id.advertiser_id.advertiser

    @property
    def agency(self):
        return self.ad_group_id.campaign_id.advertiser_id.agency_id.agency

    @property
    def agency_id(self):
        return self.ad_group_id.campaign_id.advertiser_id.agency_id.agency_id

    @property
    def trading_desk(self):
        return self.ad_group_id.campaign_id.advertiser_id.agency_id.trading_desk_id.trading_desk

    @property
    def trading_desk_id(self):
        return self.ad_group_id.campaign_id.advertiser_id.agency_id.trading_desk_id.trading_desk_id

    @property
    def encrypted_ad_id(self):
        from mng.commons.crypto import encrypt
        return encrypt(self.ad_id)

    def __unicode__(self):
        return self.ad

    def make_copy(self):
        # pylint: disable=invalid-name
        m = deepcopy(self)
        m.pk = None
        m.ad_id = None
        m.creative_id = None
        m.ad_group_id_id = None
        m.domain = ''
        m.targeting = ''
        m.categories = ''
        m.status = STATUS_PAUSED  # 'paused'
        m.adx_status = 'new'
        m.appnexus_status = 'new'
        m.a9_status = 'passed'
        m.adx_attrs = ''
        m.adx_sensitive_categories = ''
        m.adx_product_categories = ''
        return m

    class Meta:
        managed = True
        unique_together = ('ad_group_id', 'ad')
        db_table = 'ad'
        app_label = 'restapi'
コード例 #13
0
class AuditLog(BaseModel):
    audit_log_id = models.AutoField(primary_key=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             related_name='djangouser',
                             db_constraint=False)
    audit_type = models.IntegerField()
    audit_action = models.IntegerField()
    item_id = models.IntegerField()
    old_data = models.TextField(blank=True)
    new_data = models.TextField(blank=True)
    created = DateTimeField(null=True, default=None, auto_now_add=True)

    objects = AuditLogManager()
    objects_raw = models.Manager()
    permission_check = True

    def is_own(self):
        from restapi.models.User import User
        own_users = list(
            User.objects_raw.filter(
                profile__trading_desk__trading_desk_userprofiles__user=
                REGISTRY['user']))
        value = False
        try:
            value = self.user in own_users
        except ObjectDoesNotExist:
            pass
        return value

    def save(self, *args, **kwargs):
        now = datetime.now()
        self.created = now - timedelta(hours=PacificTimeShift.get(now))
        super(AuditLog, self).save(*args, **kwargs)

    @property
    def diff_field(self):
        diff = {}
        if self.old_data != 'null' and self.new_data != 'null':
            try:
                old = json.loads(self.old_data)
            except ValueError:
                old = eval(self.old_data)

            try:
                new = json.loads(self.new_data)
            except ValueError:
                new = eval(self.new_data)

            keys = old.viewkeys() | new.viewkeys()

            for key in keys:
                if self.audit_action == AUDIT_ACTION_ADD and key in new:
                    diff[key] = unicode(' ') + ' => ' + unicode(new.get(key))

                elif self.audit_action == AUDIT_ACTION_UPDATE and key in old and key in new and old[
                        key] != new[key]:
                    diff[key] = unicode(old.get(key)) + ' => ' + unicode(
                        new.get(key))

                elif self.audit_action == AUDIT_ACTION_DELETE:
                    if key in old and key in new and old[key] != new[key]:
                        diff[key] = unicode(old.get(key)) + ' => ' + unicode(
                            new.get(key))

                    elif key in old and not new:
                        diff[key] = unicode(
                            old.get(key)) + ' => ' + unicode(' ')

        return diff

    @property
    def item(self):
        from restapi.audit_logger import AuditLogger
        model = AuditLogger.get_model_by_audit_type(self.audit_type)
        instance = None
        if model is not None:
            qs = model.objects.filter(pk=self.item_id)
            if qs.exists():
                instance = qs.first()
            else:
                try:
                    old_data = json.loads(self.old_data)
                except ValueError:
                    old_data = None

                if old_data:
                    instance = model()
                    for key in old_data:
                        try:
                            setattr(instance, key, old_data[key])
                        except (ValueError, TypeError):
                            pass
        return instance

    @property
    def item_name(self):
        instance = None
        try:
            instance = self.item
        except PermissionDeniedException:
            pass
        return unicode(instance) if instance is not None else None

    class Meta:
        managed = True
        db_table = 'audit_log'
        app_label = 'restapi'
        ordering = ['-audit_log_id']

    def __unicode__(self):
        return self.audit_log_id
コード例 #14
0
class AdGroup(BasePausedAtModelMixin, BaseModel):
    ad_group_id = models.AutoField(primary_key=True)
    campaign_id = models.ForeignKey(Campaign, db_column='campaign_id')
    ad_group = models.CharField(max_length=255)
    ad_group_type = models.IntegerField(blank=True, choices=AD_GROUP_TYPE_CHOICES, default=AD_GROUP_TYPE_CHOICES[0][0])
    targeting = models.TextField(blank=True, default='', db_column='targeting')
    categories = models.TextField(blank=True)
    domain = models.CharField(max_length=255, blank=True)
    notes = models.TextField(blank=True)
    redirect_url = models.CharField(max_length=1024, blank=True)
    destination_url = models.CharField(max_length=511, blank=True, default='')
    viewthrough_url = models.CharField(max_length=1024, blank=True, default='')
    inflator_text = models.CharField(max_length=1024, blank=True)
    frequency_map = OrderedJSONField(blank=True, default='', cmp=cmp_asterisk_last, default_json=str)
    priority = models.IntegerField(blank=True, default=0)
    daily_budget_type = models.CharField(max_length=10,
                                         blank=True,
                                         choices=BUDGET_TYPES_CHOICES,
                                         default=BUDGET_TYPES_CHOICES[0][0])
    daily_budget_value = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    daily_spend = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    capped = models.BooleanField(default=False, blank=True)
    hourly_capped = models.BooleanField(default=False, blank=True)
    status = models.CharField(max_length=8, choices=STATUS_CHOICES, default=STATUS_CHOICES[1][0])
    tag = models.CharField(max_length=255, blank=True, null=True)
    flight_start_date = ZeroDateTimeField(default=None, null=True, blank=True)
    flight_end_date = ZeroDateTimeField(default=None, null=True, blank=True)
    flight_budget_type = models.CharField(max_length=10,
                                          blank=True,
                                          choices=BUDGET_TYPES_CHOICES,
                                          default=BUDGET_TYPES_CHOICES[0][0])
    flight_budget_value = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    sampling_rate = models.DecimalField(max_digits=9, decimal_places=8, blank=True, null=True)
    throttling_rate = models.DecimalField(max_digits=9, decimal_places=8, blank=True, null=True)
    max_frequency = models.IntegerField(blank=True, null=True, default=None)
    frequency_interval = models.IntegerField(blank=True, null=True, default=None)
    event_args = models.TextField(blank=True)
    bidder_args = models.TextField(blank=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)
    paused_at = ZeroDateTimeField(default=None, null=True, blank=True)
    overridden = models.BooleanField(default=False, blank=True)

    ignore_fatigue_segment = models.NullBooleanField(default=None, blank=True, null=True)
    ignore_suppression_segment = models.NullBooleanField(default=None, blank=True, null=True)

    distribution_app_sha1_android_id = models.NullBooleanField(default=None, blank=True, null=True)
    distribution_app_ifa = models.NullBooleanField(default=None, blank=True, null=True)
    distribution_web = models.NullBooleanField(default=None, blank=True, null=True)

    total_cost_cap = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    daily_cost_cap = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    total_loss_cap = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    daily_loss_cap = models.DecimalField(max_digits=9, decimal_places=2, default=0)

    revmap_rev_type = revmap_field('rev_type')
    revmap_rev_value = revmap_field('rev_value')
    revmap_opt_type = revmap_field('opt_type')
    revmap_opt_value = revmap_field('opt_value')
    revmap_target_type = revmap_field('target_type')
    revmap_target_value = revmap_field('target_value')

    _revmap = None

    objects = AdGroupManager()
    objects_raw = models.Manager()
    permission_check = True

    actions = ('bulk', 'import', 'export', 'rates', 'limits', 'targeting_json_read', 'targeting_json_update')

    @property
    def campaign(self):
        return self.campaign_id.campaign

    @property
    def advertiser_id(self):
        return self.campaign_id.advertiser_id.advertiser_id

    @property
    def advertiser(self):
        return self.campaign_id.advertiser_id.advertiser

    @property
    def agency(self):
        return self.campaign_id.advertiser_id.agency_id.agency

    @property
    def agency_id(self):
        return self.campaign_id.advertiser_id.agency_id.agency_id

    @property
    def trading_desk(self):
        return self.campaign_id.advertiser_id.agency_id.trading_desk_id.trading_desk

    @property
    def trading_desk_id(self):
        return self.campaign_id.advertiser_id.agency_id.trading_desk_id.trading_desk_id

    @property
    def app_install(self):
        return self.campaign_id.app_install

    def is_own(self):
        """Returns True if ad group entity belongs to the current user."""
        advertiser_ids = REGISTRY.get('user_advertiser_ids')
        if advertiser_ids and AdGroup.objects.filter(campaign_id__advertiser_id__in=advertiser_ids,
                                                     ad_group_id=self.ad_group_id).exists():
            return True

        agency_ids = REGISTRY.get('user_agency_ids')
        if agency_ids and AdGroup.objects.filter(campaign_id__advertiser_id__agency_id__in=agency_ids,
                                                 ad_group_id=self.ad_group_id).exists():
            return True

        trading_desk_ids = REGISTRY.get('user_trading_desk_ids')
        if trading_desk_ids and AdGroup.objects.filter(
                campaign_id__advertiser_id__agency_id__trading_desk_id__in=trading_desk_ids,
                ad_group_id=self.ad_group_id).exists():
            return True

        return False

    def autopopulate_by_ownership(self):
        pass

    @property
    def ads_enabled(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id=self.pk, status=STATUS_ENABLED)

    @property
    def ads_disapproved(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id=self.pk,
                                      adx_status=AD_STATUS_DISAPPROVED,
                                      status=STATUS_ENABLED)

    @property
    def a9_pending(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id=self.pk,
                                      a9_status=A9_STATUS_PENDING,
                                      status=STATUS_ENABLED)

    @property
    def a9_failed(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id=self.pk,
                                      a9_status=A9_STATUS_FAILED,
                                      status=STATUS_ENABLED)

    @property
    def ads_total(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id=self.pk)

    @property
    def black_lists_total(self):
        from restapi.models.BidderBlacklist import BidderBlacklistIds as model
        return model.objects.getCount(ad_group_id=self.pk)

    @property
    def white_lists_total(self):
        from restapi.models.BidderWhitelist import BidderWhitelistIds as model
        return model.objects.getCount(ad_group_id=self.pk)

    @property
    def custom_hints_total(self):
        from restapi.models.CustomHint import CustomHintIds as model
        return model.objects.getCount(ad_group_id=self.pk)

    @property
    def discrete_pricing_total(self):
        from restapi.models.DiscretePricing import DiscretePricingIds as model
        return model.objects.getCount(ad_group_id=self.pk)

    @property
    def ads_to_pause(self):
        """Returns a number of ads recommended to pause."""
        from restapi.models.CreativePruning import CreativePruning
        return CreativePruning.objects.getCount(ad_id__ad_group_id=self.pk, action='pause')

    @property
    def ads_to_delete(self):
        """Returns a number of ads recommended to delete."""
        from restapi.models.CreativePruning import CreativePruning
        return CreativePruning.objects.getCount(ad_id__ad_group_id=self.pk, action='delete')

    search_args = ('ad_group_id', 'ad_group__icontains')

    @property
    def search_result(self):
        campaign = self.campaign_id
        advertiser = campaign.advertiser_id
        agency = advertiser.agency_id
        result = {'level': 'adgroup',
                  'ad_group': self.ad_group,
                  'ad_group_id': self.ad_group_id,
                  'campaign': campaign.campaign,
                  'campaign_id': campaign.campaign_id,
                  'advertiser': advertiser.advertiser,
                  'advertiser_id': advertiser.advertiser_id,
                  'agency': agency.agency,
                  'agency_id': agency.agency_id,
                  'last_update': self.last_update}
        return result

    def __unicode__(self):
        return self.ad_group

    def get_fields_for_copy(self):
        rejected_fields = lambda x: x.__class__ is models.AutoField or x.name == 'pk'
        extra_fields = ['revmap_rev_type',
                        'revmap_rev_value',
                        'revmap_opt_type',
                        'revmap_opt_value',
                        'revmap_target_type',
                        'revmap_target_value']
        fields = [f.name for f in self._meta.fields if not rejected_fields(f)]
        return fields + extra_fields

    def make_copy(self):
        values = [(f, getattr(self, f)) for f in self.get_fields_for_copy()]

        initials = dict([(k, v) for k, v in values if v is not None])
        # pylint: disable=invalid-name
        m = self.__class__(**initials)
        # pylint: disable=invalid-name
        m.pk = None
        m.ad_group_id = None
        m.status = STATUS_PAUSED  # 'paused'
        return m

    @property
    def parent_name(self):
        return self.campaign_id.campaign

    def save(self, *args, **kwargs):
        from restapi.audit_logger import AuditLogger
        AuditLogger.skip_next_write = True
        super(AdGroup, self).save(*args, **kwargs)

        if self._revmap is not None:
            from restapi.models.Revmap import Revmap
            revmap_qs = Revmap.objects.filter(ad_group_id=self)

            is_updated = False
            if revmap_qs.exists():
                revmap = revmap_qs.first()

            else:
                revmap = Revmap(ad_group_id=self,
                                ad_group=self.ad_group,
                                campaign_id=self.campaign_id.pk,
                                campaign=self.campaign_id.campaign)
                is_updated = True

            for field in self._revmap:
                old_value = getattr(revmap, field)
                new_value = self._revmap[field]
                if isinstance(new_value, Decimal):
                    new_value = float(new_value)

                setattr(revmap, field, self._revmap[field])
                if old_value != new_value:
                    is_updated = True

            if is_updated:
                revmap.save()

        return super(AdGroup, self).save(*args, **kwargs)

    def as_dict(self):
        data = super(AdGroup, self).as_dict()
        for field in ('revmap_rev_type', 'revmap_rev_value', 'revmap_opt_type', 'revmap_opt_value',
                      'revmap_target_type', 'revmap_target_value'):
            data[field] = getattr(self, field)
        return data

    class Meta:
        managed = True
        unique_together = ('campaign_id', 'ad_group')
        db_table = 'ad_group'
        app_label = 'restapi'
        ordering = ('ad_group',)
コード例 #15
0
class Advertiser(BaseModel):
    advertiser_id = models.AutoField(primary_key=True)
    advertiser = models.CharField(max_length=255)
    advertiser_key = models.CharField(max_length=40,
                                      default=ApiKeyGenerator.key_generator)
    agency_id = models.ForeignKey(Agency,
                                  db_column='agency_id',
                                  related_name='agency_advertisers')
    account_manager = models.IntegerField(max_length=10, default=0)
    notes = models.TextField(blank=True)
    encryption_key = models.BinaryField(
        max_length=16,
        blank=True,
        null=True,
        default=ApiKeyGenerator.random_string_16)
    encryption_iv = models.BinaryField(
        max_length=16,
        blank=True,
        null=True,
        default=ApiKeyGenerator.random_string_16)
    encryption_suffix = models.BinaryField(
        max_length=4,
        blank=True,
        null=True,
        default=ApiKeyGenerator.random_string_4)
    deleted = models.BooleanField(default=False, blank=True)
    status = models.CharField(max_length=8,
                              choices=STATUS_CHOICES,
                              default=STATUS_ENABLED)
    zip = models.CharField(max_length=10, default='', blank=True)
    contact = models.CharField(max_length=100)
    address1 = models.CharField(max_length=255, default='', blank=True)
    address2 = models.CharField(max_length=255, default='', blank=True)
    city = models.CharField(max_length=100, default='', blank=True)
    state_prov = models.CharField(max_length=100, default='', blank=True)
    country = models.CharField(max_length=3,
                               choices=COUNTRIES,
                               default=COUNTRIES[0][0])
    phone = models.CharField(max_length=20, default='', blank=True)
    email = models.CharField(max_length=255, default='', blank=True)
    flight_start_date = ZeroDateField(default=None, null=True, blank=True)
    flight_budget = models.DecimalField(max_digits=9,
                                        decimal_places=2,
                                        default=0)
    sampling_rate = models.DecimalField(max_digits=9,
                                        decimal_places=8,
                                        blank=True,
                                        null=True)
    throttling_rate = models.DecimalField(max_digits=9,
                                          decimal_places=8,
                                          blank=True,
                                          null=True)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)
    currency = models.CharField(max_length=3, default=CURRENCY_USD)
    twitter_margin = models.FloatField(default=0.15)
    discount = models.DecimalField(max_digits=9, decimal_places=2, default=0)

    objects = AdvertiserManager()
    objects_raw = models.Manager()
    permission_check = True

    actions = ('filter_by_trading_desk', )

    def is_own(self):
        """Returns True if advertiser entity belongs to the current user."""
        user_advertiser_ids = REGISTRY.get('user_advertiser_ids')
        if user_advertiser_ids and self.advertiser_id in user_advertiser_ids:
            return True

        user_agency_ids = REGISTRY.get('user_agency_ids')
        if user_agency_ids and self.agency_id_id in user_agency_ids:
            return True

        user_trading_desk_ids = REGISTRY.get('user_trading_desk_ids')
        if user_trading_desk_ids and Advertiser.objects.filter(
                agency_id__trading_desk_id__in=user_trading_desk_ids,
                advertiser_id=self.advertiser_id).exists():
            return True

        return False

    def autopopulate_by_ownership(self):
        pass

    search_args = ('advertiser_id', 'advertiser__icontains')

    @property
    def search_result(self):
        return {
            'level': 'advertiser',
            'advertiser': self.advertiser,
            'advertiser_id': self.advertiser_id,
            'agency': self.agency_id.agency,
            'agency_id': self.agency_id.agency_id,
            'last_update': self.last_update
        }

    @property
    def agency(self):
        return self.agency_id.agency

    @property
    def trading_desk_id(self):
        return self.agency_id.trading_desk_id.trading_desk_id

    @property
    def trading_desk(self):
        return self.agency_id.trading_desk_id.trading_desk

    def __unicode__(self):
        return self.advertiser

    class Meta:
        # managed=False
        unique_together = ('agency_id', 'advertiser')
        db_table = 'advertiser'
        app_label = 'restapi'
        ordering = ('advertiser', )
コード例 #16
0
class TwitterTailoredAudience(BaseModel):
    tw_targeting_id = models.BigIntegerField(primary_key=True)
    tw_account_id = models.ForeignKey(TwitterAccount,
                                      db_column='tw_account_id')
    name = models.CharField(max_length=255)
    audience_size = models.CharField(max_length=255)
    targetable_types = models.TextField(blank=True)
    audience_type = models.CharField(max_length=255)
    targetable = models.NullBooleanField()
    list_type = models.CharField(max_length=255)
    reasons_not_targetable = models.TextField(blank=True)
    partner_source = models.CharField(max_length=255)
    is_owner = models.NullBooleanField()
    permission_level = models.CharField(max_length=255)
    status = models.CharField(max_length=8,
                              choices=STATUS_CHOICES,
                              default=STATUS_ENABLED)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None)

    objects = TwitterTailoredAudienceManager()
    objects_raw = models.Manager()
    # permission_check = True

    search_args = (
        'name',
        'tw_account_id',
    )

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'tw_tailored_audience'
        app_label = 'restapi'

    @classmethod
    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

    @classmethod
    def sync_tailored_audience(self,
                               tw_account_id,
                               data,
                               manage_campaign_id=None):
        res = {}
        res['data'] = data
        res['success'] = False
        res['os_platform'] = 'web'
        tailored_audience_id_int = base36_to_int(data['id'])

        if isinstance(tw_account_id, TwitterAccount):
            m_tw_account = tw_account_id
        else:
            m_tw_account = TwitterAccount.objects_raw.get(
                tw_account_id=tw_account_id)

        if m_tw_account is None:
            res = {
                'data': {},
                'success':
                False,
                'message':
                "Error syncing Twitter Campaign Cannot find Twitter Account"
            }
            return res

        try:
            res['type'] = 'existing'
            m_tw_tailored_audience = TwitterTailoredAudience.objects_raw.get(
                tw_account_id=m_tw_account,
                tw_targeting_id=tailored_audience_id_int)
        except TwitterTailoredAudience.DoesNotExist:
            res['type'] = 'new'
            m_tw_tailored_audience = TwitterTailoredAudience(
                tw_account_id=m_tw_account,
                tw_targeting_id=tailored_audience_id_int)

        if m_tw_tailored_audience is None:
            res = {
                'data': {},
                'success': False,
                'message': "Error syncing Twitter Tailored Audience"
            }
            return res

        m_tw_tailored_audience.name = data['name']
        m_tw_tailored_audience.targetable = data['targetable']
        m_tw_tailored_audience.audience_size = data['audience_size']
        m_tw_tailored_audience.targetable_types = json.dumps(
            data['targetable_types'])
        m_tw_tailored_audience.audience_type = data['audience_type']
        m_tw_tailored_audience.targetable = data['targetable']
        m_tw_tailored_audience.list_type = data['list_type']
        m_tw_tailored_audience.reasons_not_targetable = json.dumps(
            data['reasons_not_targetable'])
        m_tw_tailored_audience.partner_source = data['partner_source']
        m_tw_tailored_audience.is_owner = data['is_owner']
        m_tw_tailored_audience.permission_level = data['permission_level']
        m_tw_tailored_audience.last_update = data['updated_at']

        if data['deleted'] == True:
            m_tw_tailored_audience.status = STATUS_ARCHIVED

        m_tw_tailored_audience.save_raw()
        res['success'] = True
        return res
コード例 #17
0
class TwitterCampaign(BaseModel):
    tw_campaign_id = models.BigIntegerField(primary_key=True)
    tw_account_id = models.ForeignKey(TwitterAccount,
                                      db_column='tw_account_id')
    campaign_id = models.ForeignKey(Campaign, db_column='campaign_id')
    name = models.CharField(max_length=255)
    funding_instrument_id = models.CharField(max_length=255)
    start_time = ZeroDateTimeField(default=None, null=True, blank=True)
    end_time = ZeroDateTimeField(default=None, null=True, blank=True)
    standard_delivery = models.NullBooleanField()
    frequency_cap = models.IntegerField()
    duration_in_days = models.CharField(max_length=8,
                                        choices=[(1, 1), (7, 7), (30, 30)],
                                        default=7)
    total_budget_amount_local_micro = models.BigIntegerField(max_length=20)
    daily_budget_amount_local_micro = models.BigIntegerField(max_length=20)
    status = models.CharField(max_length=8,
                              choices=STATUS_CHOICES,
                              default=STATUS_ENABLED)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TwitterCampaignManager()
    objects_raw = models.Manager()
    # permission_check = True

    search_args = (
        'name__icontains',
        'tw_campaign_id',
    )

    @property
    def search_result(self):
        advertiser = self.campaign_id.advertiser_id
        result = {
            'level': 'twittercampaign',
            'campaign': self.campaign_id.campaign,
            'campaign_id': self.campaign_id.campaign_id,
            'tw_campaign': "%s / %s" % (self.tw_account_id.name, self.name),
            'tw_campaign_id': self.tw_campaign_id,
            'advertiser': advertiser.advertiser,
            'advertiser_id': advertiser.advertiser_id,
            'last_update': self.last_update
        }
        return result

    @property
    def _advertiser_id(self):
        return self.campaign_id.advertiser_id.advertiser_id

    @property
    def _campaign_id(self):
        return self.campaign_id.campaign_id

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'tw_campaign'
        app_label = 'restapi'

    @classmethod
    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

    @classmethod
    def create_campaign(self,
                        data,
                        oauth_token=settings.TW_ACCESS_TOKEN,
                        oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.create_update_campaign(data, oauth_token,
                                           oauth_token_secret, "post")

    @classmethod
    def update_campaign(self,
                        data,
                        oauth_token=settings.TW_ACCESS_TOKEN,
                        oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.create_update_campaign(data, oauth_token,
                                           oauth_token_secret, "put")

    @classmethod
    def create(self,
               data,
               oauth_token=settings.TW_ACCESS_TOKEN,
               oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.create_campaign(data, oauth_token, oauth_token_secret)

    @classmethod
    def update(self,
               data,
               oauth_token=settings.TW_ACCESS_TOKEN,
               oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.update_campaign(data, oauth_token, oauth_token_secret)

    @classmethod
    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

    @classmethod
    def batch_create(self,
                     data,
                     account_id,
                     oauth_token=settings.TW_ACCESS_TOKEN,
                     oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.batch_create_update_campaign(data, account_id, oauth_token,
                                                 oauth_token_secret, "post")

    @classmethod
    def batch_update(self,
                     data,
                     account_id,
                     oauth_token=settings.TW_ACCESS_TOKEN,
                     oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.batch_create_update_campaign(data, account_id, oauth_token,
                                                 oauth_token_secret, "put")

    @classmethod
    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)

    @classmethod
    def sync_campaign(self, tw_account_id, data, manage_campaign_id=None):
        res = {}
        res['data'] = data
        res['success'] = False
        res['os_platform'] = 'web'
        campaign_id_int = base36_to_int(data['id'])

        if isinstance(tw_account_id, TwitterAccount):
            m_tw_account = tw_account_id
        else:
            m_tw_account = TwitterAccount.objects_raw.get(
                tw_account_id=tw_account_id)

        if m_tw_account is None:
            res = {
                'data': {},
                'success':
                False,
                'message':
                "Error syncing Twitter Campaign Cannot find Twitter Account"
            }
            return res

        try:
            res['type'] = 'existing'
            m_tw_campaign = TwitterCampaign.objects_raw.get(
                tw_account_id=m_tw_account, tw_campaign_id=campaign_id_int)
        except TwitterCampaign.DoesNotExist:
            res['type'] = 'new'
            m_tw_campaign = TwitterCampaign(tw_account_id=m_tw_account,
                                            tw_campaign_id=campaign_id_int)

        if m_tw_campaign is None:
            res = {
                'data': {},
                'success': False,
                'message': "Error syncing Twitter Campaign"
            }
            return res

        # Get Manage Campaign ID from Twitter Campaign Name
        if manage_campaign_id is None:
            campaign_id_match = re.findall(r'\s*{(\d+)}\s*$', data['name'])[:1]
            if campaign_id_match and campaign_id_match[0]:
                manage_campaign_id = campaign_id_match[0]

        if manage_campaign_id:
            try:
                m_campaign = Campaign.objects_raw.get(
                    campaign_id=manage_campaign_id)
            except Campaign.DoesNotExist:
                m_campaign = None

            if m_campaign is not None:
                m_tw_campaign.campaign_id = m_campaign
                res['data']['manage_campaign_id'] = manage_campaign_id
                if m_campaign.targeting:
                    targeting = json.loads(m_campaign.targeting)
                    if targeting and 'os' in targeting and targeting['os']:
                        os_platform = targeting['os']
                        if os_platform == 'iOS':
                            os_platform = 'iphone'
                        res['os_platform'] = os_platform

                m_tw_campaign.name = data['name']
                m_tw_campaign.funding_instrument_id = data[
                    'funding_instrument_id']
                m_tw_campaign.total_budget_amount_local_micro = data[
                    'total_budget_amount_local_micro']
                m_tw_campaign.daily_budget_amount_local_micro = data[
                    'daily_budget_amount_local_micro']
                m_tw_campaign.duration_in_days = data['duration_in_days']
                m_tw_campaign.standard_delivery = data['standard_delivery']

                if data['start_time'] is not None:
                    m_tw_campaign.start_time = data['start_time']
                if data['end_time'] is not None:
                    m_tw_campaign.end_time = data['end_time']
                if data['paused'] == True or data['servable'] is False:
                    m_tw_campaign.status = STATUS_PAUSED
                elif data['paused'] == False or data['servable'] is True:
                    m_tw_campaign.status = STATUS_ENABLED
                if data['deleted'] == True:
                    m_tw_campaign.status = STATUS_ARCHIVED
                if data['duration_in_days'] is not None:
                    m_tw_campaign.duration_in_days = data['duration_in_days']
                if data['frequency_cap'] is not None:
                    m_tw_campaign.frequency_cap = data['frequency_cap']

                m_tw_campaign.save_raw()
                res['success'] = True
        else:
            res['success'] = False
            res['message'] = 'Missing Manage Campaign ID'

        return res
コード例 #18
0
class TwitterAppCard(BaseModel):
    tw_app_card_id = models.BigIntegerField(primary_key=True)
    tw_account_id = models.ForeignKey(TwitterAccount,
                                      db_column='tw_account_id')
    name = models.CharField(max_length=255)
    card_type = models.CharField(max_length=20,
                                 choices=TW_CARD_TYPE,
                                 default='app_card')
    preview_url = models.CharField(max_length=255)
    app_country_code = models.CharField(max_length=255)
    iphone_app_id = models.CharField(max_length=255)
    ipad_app_id = models.CharField(max_length=255)
    googleplay_app_id = models.CharField(max_length=255)
    deep_link = models.CharField(max_length=255)
    custom_cta = models.CharField(max_length=255, choices=TW_CUSTOM_CTA)
    custom_icon_media_id = models.CharField(max_length=255)
    custom_app_description = models.CharField(max_length=255)
    image_media_id = models.CharField(max_length=255)
    wide_app_image = models.CharField(max_length=255)
    wide_app_image_media_id = models.CharField(max_length=255)
    video_id = models.CharField(max_length=255)
    video_url = models.CharField(max_length=255)
    video_poster_url = models.CharField(max_length=255)
    status = models.CharField(max_length=8,
                              choices=STATUS_CHOICES,
                              default=STATUS_ENABLED)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TwitterAppCardManager()
    objects_raw = models.Manager()

    # permission_check = True

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'tw_app_card'
        app_label = 'restapi'

    @classmethod
    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

    @classmethod
    def sync_app_card(self, tw_account_id, data):
        res = {}
        res['data'] = data
        res['success'] = False
        appcard_id_int = base36_to_int(data['id'])

        if isinstance(tw_account_id, TwitterAccount):
            m_tw_account = tw_account_id
        else:
            m_tw_account = TwitterAccount.objects_raw.filter(
                tw_account_id=tw_account_id).first()

        if m_tw_account is None:
            res = {
                'data': {},
                'success':
                False,
                'message':
                "Error syncing Twitter AppCard. Cannot find Twitter Account"
            }
            return res

        try:
            res['type'] = 'existing'
            m_tw_appcard = TwitterAppCard.objects_raw.get(
                tw_account_id=m_tw_account, tw_app_card_id=appcard_id_int)
        except TwitterAppCard.DoesNotExist:
            res['type'] = 'new'
            m_tw_appcard = TwitterAppCard(tw_account_id=m_tw_account,
                                          tw_app_card_id=appcard_id_int)

        if m_tw_appcard is None:
            res = {
                'data': {},
                'success': False,
                'message': "Error syncing Twitter AppCard"
            }
            return res

        if data['name']:
            m_tw_appcard.name = data['name']

        if data['card_type'] == 'IMAGE_APP_DOWNLOAD':
            m_tw_appcard.card_type = 'image'
        elif data['card_type'] == 'APP_DOWNLOAD':
            m_tw_appcard.card_type = 'app_card'
        elif data['card_type'] == 'VIDEO_APP_DOWNLOAD':
            m_tw_appcard.card_type = 'video'
            if data['video_url']:
                m_tw_appcard.video_url = data['video_url']

        if data['preview_url']:
            m_tw_appcard.preview_url = data['preview_url']
        if data['app_country_code']:
            m_tw_appcard.app_country_code = data['app_country_code']

        if 'iphone_app_id' in data and data['iphone_app_id']:
            m_tw_appcard.iphone_app_id = data['iphone_app_id']
        if 'ipad_app_id' in data and data['ipad_app_id']:
            m_tw_appcard.iphone_app_id = data['ipad_app_id']
        if 'googleplay_app_id' in data and data['googleplay_app_id']:
            m_tw_appcard.iphone_app_id = data['googleplay_app_id']
        if 'deep_link' in data and data['deep_link']:
            m_tw_appcard.deep_link = data['deep_link']
        if 'app_cta' in data and data['app_cta']:
            m_tw_appcard.custom_cta = data['app_cta']

        if 'custom_icon_media_id' in data and data['custom_icon_media_id']:
            m_tw_appcard.custom_icon_media_id = data['custom_icon_media_id']
        if 'custom_app_description' in data and data['custom_app_description']:
            m_tw_appcard.custom_app_description = data[
                'custom_app_description']
        if 'image_media_id' in data and data['image_media_id']:
            m_tw_appcard.image_media_id = data['image_media_id']
        if 'wide_app_image_media_id' in data and data[
                'wide_app_image_media_id']:
            m_tw_appcard.wide_app_image_media_id = data[
                'wide_app_image_media_id']
        if 'wide_app_image' in data and data['wide_app_image']:
            m_tw_appcard.wide_app_image = data['wide_app_image']
        if 'video_id' in data and data['video_id']:
            m_tw_appcard.video_id = data['video_id']
        if 'video_url' in data and data['video_url']:
            m_tw_appcard.video_url = data['video_url']
        if 'video_poster_url' in data and data['video_poster_url']:
            m_tw_appcard.video_poster_url = data['video_poster_url']

        if data['deleted'] == False:
            m_tw_appcard.status = STATUS_ENABLED
        if data['deleted'] == True:
            m_tw_appcard.status = STATUS_ARCHIVED

        m_tw_appcard.save_raw()

        res['success'] = True
        return res
コード例 #19
0
class Agency(BaseModel):
    agency_id = models.AutoField(primary_key=True)
    trading_desk_id = models.ForeignKey(TradingDesk, db_column='trading_desk_id', related_name='trading_desk_agencies')
    agency = models.CharField(max_length=255)
    agency_key = models.CharField(max_length=40, default=ApiKeyGenerator.key_generator)
    account_manager = models.IntegerField(max_length=10, default=0)
    currency = models.CharField(max_length=3, default=CURRENCY_USD)
    contact = models.CharField(max_length=100)
    address1 = models.CharField(max_length=255, default='', blank=True)
    address2 = models.CharField(max_length=255, default='', blank=True)
    city = models.CharField(max_length=100, default='', blank=True)
    state_prov = models.CharField(max_length=100, default='', blank=True)
    zip = models.CharField(max_length=10, default='', blank=True)
    country = models.CharField(max_length=3, choices=COUNTRIES, default=COUNTRIES[0][0])
    phone = models.CharField(max_length=20, default='', blank=True)
    email = models.CharField(max_length=255, default='', blank=True)
    notes = models.TextField(blank=True, default='')
    status = models.CharField(max_length=8, choices=STATUS_CHOICES, default=STATUS_CHOICES[1][0])
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = AgencyManager()
    objects_raw = models.Manager()
    permission_check = True

    actions = ('filter_by_trading_desk',)

    def is_own(self):
        """Returns True if agency entity belongs to the current user."""
        user_advertiser_ids = REGISTRY.get('user_advertiser_ids')
        if user_advertiser_ids and Agency.objects.filter(agency_advertisers__advertiser_id__in=user_advertiser_ids,
                                                         agency_id=self.agency_id).exists():
            return True

        user_agency_ids = REGISTRY.get('user_agency_ids')
        if user_agency_ids and self.agency_id in user_agency_ids:
            return True

        user_trading_desk_ids = REGISTRY.get('user_trading_desk_ids')
        if user_trading_desk_ids and self.trading_desk_id in user_trading_desk_ids:
            return True

        return False

    def autopopulate_by_ownership(self):
        trading_desk = REGISTRY['user'].profile.trading_desk.first()
        self.trading_desk_id = trading_desk
        self.currency = trading_desk.currency

    def __unicode__(self):
        return self.agency

    search_args = ('agency_id', 'agency__icontains')

    @property
    def trading_desk(self):
        return self.trading_desk_id.trading_desk

    @property
    def search_result(self):
        return {
            'level': 'agency',
            'agency': self.agency,
            'agency_id': self.agency_id,
            'trading_desk_id': self.trading_desk_id.pk,
            'last_update': self.last_update
        }

    class Meta:
        # managed=False
        unique_together = ('trading_desk_id', 'agency')
        db_table = 'agency'
        app_label = 'restapi'
        ordering = ('agency',)
コード例 #20
0
class CustomHint(BaseModel):
    id = models.AutoField(primary_key=True)
    size = models.CharField(max_length=8,
                            choices=CUSTOM_HINT_SIZE_CHOICES,
                            default=SIZE_ALL)
    placement_type = models.CharField(max_length=4,
                                      choices=PLACEMENT_TYPE_CHOICES,
                                      default=PLACEMENT_TYPE_ALL)
    placement_id = models.CharField(max_length=128, default='all')
    inflator_type = models.CharField(max_length=8,
                                     choices=INFLATOR_TYPE_CHOICES,
                                     null=True,
                                     default=None)
    inflator = models.DecimalField(max_digits=9,
                                   decimal_places=6,
                                   null=True,
                                   default=None)
    priority = models.IntegerField(default=0)
    max_frequency = models.IntegerField(default=0)
    frequency_interval = models.IntegerField(default=0)
    start_date = WideRangeDateTimeField(default=timezone(
        settings.TIME_ZONE).localize(datetime(datetime.now().year, 1, 1)))
    end_date = WideRangeDateTimeField(default=timezone(
        settings.TIME_ZONE).localize(datetime(datetime.now().year, 12, 31)))
    tag = models.CharField(max_length=128, blank=True, null=True, default=None)
    last_update = DateTimeField(default=None, auto_now=True)
    advertiser_id = models.IntegerField()
    campaign_id = models.ForeignKey(Campaign,
                                    db_column='campaign_id',
                                    null=True,
                                    db_constraint=False,
                                    on_delete=models.DO_NOTHING)
    campaign = models.CharField(max_length=255)
    ad_group_id = models.ForeignKey(AdGroup,
                                    db_column='ad_group_id',
                                    null=True,
                                    db_constraint=False,
                                    on_delete=models.DO_NOTHING)
    ad_group = models.CharField(max_length=255)
    ad_id = models.IntegerField()
    # pylint: disable=invalid-name
    ad = models.CharField(max_length=255)
    source_id = models.IntegerField()
    source = models.CharField(max_length=255)

    objects = CustomHintManager()
    objects_raw = models.Manager()
    permission_check = True

    def __unicode__(self):
        return self.placement_id

    def is_own(self):
        return PlacementHelper.is_own(self.campaign_id, self.ad_group_id)

    def autopopulate_by_ownership(self):
        pass

    class Meta:
        managed = False
        db_table = 'custom_hint_view'
        app_label = 'restapi'
        ordering = ['-last_update']
        unique_together = ('campaign_id', 'ad_group_id', 'ad_id', 'source_id',
                           'size', 'placement_type', 'placement_id')
コード例 #21
0
class User(BaseModel, UserPermissionsMixin, PermissionsMixin):
    user_id = models.AutoField(primary_key=True, db_column='id')
    username = models.CharField(max_length=75, blank=False, unique=True)
    first_name = models.CharField(max_length=30, blank=True)
    last_name = models.CharField(max_length=30, blank=True)
    email = models.CharField(max_length=75, blank=False)
    is_staff = models.BooleanField(default=1)
    is_active = models.BooleanField(default=1)
    date_joined = DateTimeField(auto_now_add=True, null=True, default=None)
    password = models.CharField(max_length=128)
    last_login = models.DateTimeField(null=True)

    objects = UserManager()
    objects_raw = UserDefaultManager()
    permission_check = True

    actions = ['filter_by_trading_desk']

    # dummy field for UserSerializer.reset_password_url
    reset_password_url = None

    def is_own(self):
        if self.pk is None:
            return True
        user = REGISTRY.get('user')
        if not user:
            return False
        trading_desk = self.profile.trading_desk.first()
        advertiser = self.profile.advertisers.first()
        if not advertiser and trading_desk:
            user_trading_desk = user.trading_desk.first()
            return user_trading_desk and trading_desk.pk == user_trading_desk.pk
        return user.pk == self.pk

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ('email', )

    def __unicode__(self):
        return self.email

    @property
    def user_in_groups(self):
        return [x.name for x in self.groups.all()]

    @property
    def user_in_trading_desks(self):
        profile = self.profile
        trading_desks = TradingDesk.objects_raw.filter(
            trading_desk_userprofiles=profile)
        return [x.trading_desk for x in trading_desks]

    @property
    def full_name(self):
        return ('%s %s' % (self.first_name, self.last_name)).strip()

    @property
    def trading_desk(self):
        trading_desks = self.profile.trading_desk
        td = trading_desks.first()
        if td is not None:
            return td.trading_desk
        else:
            return None

    @property
    def trading_desk_id(self):
        trading_desks = self.profile.trading_desk
        td = trading_desks.first()
        if td is not None:
            return td.trading_desk_id
        else:
            return None

    @property
    def trading_desk_key(self):
        trading_desks = self.profile.trading_desk
        td = trading_desks.first()
        if td is not None:
            return td.trading_desk_key
        else:
            return None

    @property
    def is_manage_user(self):
        """Returns True if user is Manage.com user."""
        try:
            return self.profile.trading_desk.filter(
                pk=MANAGE_TRADING_DESK_ID).exists()
        except base.PermissionDeniedException:
            return False

    def get_short_name(self):
        return self.username

    def get_username(self):
        """Returns the identifying username for this User."""
        return getattr(self, self.USERNAME_FIELD)

    def __str__(self):
        return self.get_username()

    def natural_key(self):
        return (self.get_username(), )

    def is_anonymous(self):
        """
        Always returns False. This is a way of comparing User objects to
        anonymous users.
        """
        return False

    def is_authenticated(self):
        """
        Always return True. This is a way to tell if the user has been
        authenticated in templates.
        """
        return True

    def set_password(self, raw_password):
        self.password = make_password(raw_password)

    def check_password(self, raw_password):
        """
        Returns a boolean of whether the raw_password was correct. Handles
        hashing formats behind the scenes.
        """
        def setter(raw_password):
            self.set_password(raw_password)
            self.save(update_fields=["password"])

        return check_password(raw_password, self.password, setter)

    def set_unusable_password(self):
        # Sets a value that will never be a valid hash
        self.password = make_password(None)

    def has_usable_password(self):
        return is_password_usable(self.password)

    def get_session_auth_hash(self):
        """
        Returns an HMAC of the password field.
        """
        key_salt = "django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash"
        return salted_hmac(key_salt, self.password).hexdigest()

    def get_reset_password_hash(self):
        key_salt = self.trading_desk_key
        data = "%s:%s:%s" % (self.pk, self.password, self.is_active)
        return salted_hmac(key_salt, data).hexdigest()

    def as_dict(self, difference_from=None):
        data = super(User, self).as_dict()
        del data['last_login']
        del data['date_joined']
        data['user_in_groups'] = self.user_in_groups
        data['user_in_trading_desks'] = self.user_in_trading_desks
        return data

    class Meta:
        swappable = 'AUTH_USER_MODEL'
        db_table = 'auth_user'
        app_label = 'restapi'
コード例 #22
0
class CreativePruning(BaseModel):
    ad_id = models.ForeignKey(Ad, db_column='ad_id', primary_key=True)
    reason = models.CharField(max_length=255)
    action = models.CharField(max_length=40,
                              choices=CREATIVE_PRUNING_STATUS_CHOICES,
                              default='pause')
    ibid = models.FloatField()
    impression = models.FloatField(help_text=_(
        'Number of times an actual ad was served to the publisher.'))
    win_rate = models.FloatField()
    click = models.FloatField()
    ctr = models.FloatField(verbose_name=_('CTR'))
    install = models.FloatField()
    # Install rate.
    ir = models.FloatField(
        verbose_name=_('IR'),
        help_text=_('Install rate = (Installs / Impressions) * 100'))
    ipm = models.FloatField()
    cpm = models.FloatField()
    rpm = models.FloatField(verbose_name=_('RPM'))
    ppm = models.FloatField(verbose_name=_('PPM'))
    cpi = models.FloatField()
    rpi = models.FloatField()
    cost = models.FloatField()
    revenue = models.FloatField()
    profit = models.FloatField()
    margin = models.FloatField()
    status = models.CharField(max_length=63)
    # Install rank.
    install_rank = models.FloatField()
    ir_rank = models.FloatField()
    rpm_rank = models.FloatField()
    ctr_rank = models.FloatField()
    ibid_rank = models.FloatField()
    # IPM rank.
    ipm_rank = models.FloatField(help_text='IPM Rank', verbose_name='IPM Rank')
    revenue_rank = models.FloatField()
    profit_rank = models.FloatField()
    # Impression rank.
    impression_rank = models.FloatField(help_text='Impression Rank')
    days = models.BigIntegerField(max_length=20)
    days_w_impression = models.BigIntegerField(
        max_length=20, verbose_name=_('Days with impression'))
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = CreativePruningManager()
    objects_raw = models.Manager()

    # permission_check = True

    def __unicode__(self):
        return unicode(self.ad_id)

    class Meta:
        db_table = 'creative_pruning'
        app_label = 'restapi'

    @property
    def ad(self):
        return self.ad_id

    @property
    def ad_group_id(self):
        return self.ad_id.ad_group_id.ad_group_id

    @property
    def ad_group(self):
        return self.ad_id.ad_group_id.ad_group

    @property
    def campaign_id(self):
        return self.ad_id.ad_group_id.campaign_id.campaign_id

    @property
    def campaign(self):
        return self.ad_id.ad_group_id.campaign_id.campaign

    @property
    def advertiser_id(self):
        return self.ad_id.ad_group_id.campaign_id.advertiser_id.advertiser_id

    @property
    def advertiser(self):
        return self.ad_id.ad_group_id.campaign_id.advertiser_id.advertiser
コード例 #23
0
class Event(BaseModel):
    event_id = models.AutoField(primary_key=True)
    campaign_id = models.ForeignKey(Campaign,
                                    db_column='campaign_id',
                                    related_name='events')
    event = models.CharField(max_length=255)
    description = models.TextField(blank=True, default='')
    default_args = models.TextField(blank=True, default='')
    base_event_id = models.IntegerField(blank=True, default=0)
    deleted = models.BooleanField(default=False, blank=True)
    max_frequency = models.IntegerField(blank=True, null=True)
    show_in_stats = models.BooleanField(default=True)
    frequency_interval = models.IntegerField(blank=True, null=True)
    accept_unencrypted = models.BooleanField(default=False, blank=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = EventManager()
    objects_raw = models.Manager()
    permission_check = True

    def is_own(self):
        """Returns True if event entity belongs to the current user."""
        advertiser_ids = REGISTRY.get('user_advertiser_ids')
        if advertiser_ids and Event.objects.filter(
                campaign_id__advertiser_id__in=advertiser_ids,
                event_id=self.event_id).exists():
            return True

        agency_ids = REGISTRY.get('user_agency_ids')
        if agency_ids and Event.objects.filter(
                campaign_id__advertiser_id__agency_id__in=agency_ids,
                event_id=self.event_id).exists():
            return True

        trading_desk_ids = REGISTRY.get('user_trading_desk_ids')
        if trading_desk_ids and Event.objects.filter(
                campaign_id__advertiser_id__agency_id__trading_desk_id__in=
                trading_desk_ids,
                event_id=self.event_id).exists():
            return True

        return False

    def autopopulate_by_ownership(self):
        pass

    @property
    def campaign(self):
        return self.campaign_id.campaign

    @property
    def advertiser_id(self):
        return self.campaign_id.advertiser_id.advertiser_id

    @property
    def advertiser(self):
        return self.campaign_id.advertiser_id.advertiser

    @property
    def agency(self):
        return self.campaign_id.advertiser_id.agency_id.agency

    @property
    def agency_id(self):
        return self.campaign_id.advertiser_id.agency_id.agency_id

    @property
    def trading_desk(self):
        return self.campaign_id.advertiser_id.agency_id.trading_desk_id.trading_desk

    @property
    def trading_desk_id(self):
        return self.campaign_id.advertiser_id.agency_id.trading_desk_id.trading_desk_id

    def __unicode__(self):
        return self.event

    @property
    def encrypted_event_id(self):
        from mng.commons.crypto import encrypt
        return encrypt(self.event_id)

    search_args = ('event_id', )

    @property
    def search_result(self):
        return {
            'level': 'event',
            'event': self.event,
            'event_id': self.event_id,
            'campaign_id': self.campaign_id.pk,
            'advertiser_id': self.campaign_id.advertiser_id.pk,
            'description': self.description,
            'last_update': self.last_update
        }

    class Meta:
        # managed = False
        unique_together = ('campaign_id', 'event')
        db_table = 'event'
        app_label = 'restapi'
コード例 #24
0
class TwitterTweet(BaseModel):
    tw_tweet_id = models.BigIntegerField(primary_key=True)
    tw_twitter_user_id  = models.BigIntegerField()
    text = models.TextField(blank=True)

    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TwitterTweetManager()
    objects_raw = models.Manager()
    # permission_check = True

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'tw_tweet'
        app_label = 'restapi'

    @classmethod
    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
コード例 #25
0
class TwitterLineItem(BaseModel):
    tw_line_item_id = models.BigIntegerField(primary_key=True)
    tw_campaign_id = models.ForeignKey(TwitterCampaign,
                                       db_column='tw_campaign_id')
    name = models.CharField(max_length=255)
    currency = models.CharField(max_length=255, default='USD')
    start_time = DateTimeField()
    end_time = DateTimeField()
    product_type = models.CharField(max_length=40,
                                    choices=TW_PRODUCT_TYPES,
                                    default='PROMOTED_TWEETS')
    placements = models.TextField(blank=True)
    primary_web_event_tag = models.CharField(max_length=255)
    objective = models.CharField(max_length=40,
                                 choices=TW_OBJECTIVES,
                                 default='APP_INSTALLS')

    bid_amount_local_micro = models.BigIntegerField(max_length=20)
    bid_amount_computed_reason = models.TextField(default='')
    bid_amount_computed = models.BigIntegerField(max_length=20)
    bid_override = models.NullBooleanField()

    bid_type = models.CharField(max_length=40,
                                choices=TW_BID_TYPES,
                                default='AUTO')
    bid_unit = models.CharField(max_length=40,
                                choices=TW_BID_UNITS,
                                default='APP_INSTALL')
    optimization = models.CharField(max_length=40,
                                    choices=TW_OPTIMIZATIONS,
                                    default='APP_INSTALL')
    charge_by = models.CharField(max_length=40,
                                 choices=TW_CHARGE_BYS,
                                 default='APP_INSTALL')
    categories = models.TextField(blank=True)
    tracking_tags = models.TextField(blank=True)
    automatically_select_bid = models.NullBooleanField()
    total_budget_amount_local_micro = models.BigIntegerField(max_length=20)
    status = models.CharField(max_length=8,
                              choices=STATUS_CHOICES,
                              default=STATUS_ENABLED)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TwitterLineItemManager()
    objects_raw = models.Manager()
    # permission_check = True

    search_args = (
        'name__icontains',
        'tw_line_item_id',
    )

    @property
    def search_result(self):
        tw_campaign = self.tw_campaign_id
        campaign = tw_campaign.campaign_id
        advertiser = campaign.advertiser_id
        result = {
            'level': 'twitterlineitem',
            'campaign': campaign.campaign,
            'campaign_id': campaign.campaign_id,
            'tw_campaign': tw_campaign.name,
            'tw_campaign_id': tw_campaign.tw_campaign_id,
            'tw_line_item': "%s / %s" % (campaign.campaign, self.name),
            'tw_line_item_id': self.tw_line_item_id,
            'advertiser': advertiser.advertiser,
            'advertiser_id': advertiser.advertiser_id,
            'last_update': self.last_update
        }
        return result

    @property
    def _advertiser_id(self):
        return self.tw_campaign_id.campaign_id.advertiser_id.advertiser_id

    @property
    def _campaign_id(self):
        return self.tw_campaign_id.campaign_id.campaign_id

    @property
    def _tw_campaign_id(self):
        return self.tw_campaign_id.tw_campaign_id

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'tw_line_item'
        app_label = 'restapi'

    def is_own(self):
        return bool(
            self.campaign_id.advertiser_id.agency_id.trading_desk_id.
            trading_desk_userprofiles.filter(user=REGISTRY['user']))

    @classmethod
    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

    @classmethod
    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

    @classmethod
    def create(self,
               data,
               oauth_token=settings.TW_ACCESS_TOKEN,
               oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.create_update_line_item(data, oauth_token,
                                            oauth_token_secret, "post")

    @classmethod
    def update(self,
               data,
               oauth_token=settings.TW_ACCESS_TOKEN,
               oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.create_update_line_item(data, oauth_token,
                                            oauth_token_secret, "put")

    @classmethod
    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

    @classmethod
    def batch_create(self,
                     data,
                     account_id,
                     oauth_token=settings.TW_ACCESS_TOKEN,
                     oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.batch_create_update_line_item(data, account_id,
                                                  oauth_token,
                                                  oauth_token_secret, "post")

    @classmethod
    def batch_update(self,
                     data,
                     account_id,
                     oauth_token=settings.TW_ACCESS_TOKEN,
                     oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.batch_create_update_line_item(data, account_id,
                                                  oauth_token,
                                                  oauth_token_secret, "put")

    @classmethod
    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)

    @classmethod
    def sync_line_item(self, tw_account_id, tw_campaign_id, data):
        res = {}
        res['data'] = data
        res['success'] = False
        line_item_id_int = base36_to_int(data['id'])
        m_tw_campaign = None
        if isinstance(tw_campaign_id, TwitterCampaign):
            m_tw_campaign = tw_campaign_id
        else:
            try:
                m_tw_campaign = TwitterCampaign.objects_raw.get(
                    tw_campaign_id=tw_campaign_id)
            except TwitterCampaign.DoesNotExist:
                m_tw_campaign = None

        if m_tw_campaign is None:
            res = {
                'data': {},
                'success':
                False,
                'message':
                "Error syncing Twitter Line Item. Cannot find Twitter Campaign"
            }
            return res

        try:
            res['type'] = 'existing'
            m_tw_line_item = TwitterLineItem.objects_raw.get(
                tw_campaign_id=m_tw_campaign, tw_line_item_id=line_item_id_int)
        except TwitterLineItem.DoesNotExist:
            res['type'] = 'new'
            m_tw_line_item = TwitterLineItem(tw_campaign_id=m_tw_campaign,
                                             tw_line_item_id=line_item_id_int)
            m_tw_line_item.bid_amount_computed = data['bid_amount_local_micro']

        if m_tw_line_item is None:
            res = {
                'data': {},
                'success': False,
                'message': "Error syncing Twitter Line Item"
            }
            return res

        m_tw_line_item.name = data['name']
        m_tw_line_item.product_type = data['product_type']
        m_tw_line_item.objective = data['objective']
        m_tw_line_item.placements = json.dumps(data['placements'])
        m_tw_line_item.primary_web_event_tag = data['primary_web_event_tag']
        m_tw_line_item.bid_amount_local_micro = data['bid_amount_local_micro']
        m_tw_line_item.bid_type = data['bid_type']
        m_tw_line_item.bid_unit = data['bid_unit']
        m_tw_line_item.optimization = data['optimization']
        m_tw_line_item.charge_by = data['charge_by']
        m_tw_line_item.categories = json.dumps(data['categories'])
        m_tw_line_item.automatically_select_bid = data[
            'automatically_select_bid']
        m_tw_line_item.total_budget_amount_local_micro = data[
            'total_budget_amount_local_micro']
        m_tw_line_item.tracking_tags = json.dumps(data['tracking_tags'])

        if data['start_time'] is not None:
            m_tw_line_item.start_time = data['start_time']
        if data['end_time'] is not None:
            m_tw_line_item.end_time = data['end_time']
        if data['paused'] == True:
            m_tw_line_item.status = STATUS_PAUSED
        elif data['paused'] == False:
            m_tw_line_item.status = STATUS_ENABLED
        if data['deleted'] == True:
            m_tw_line_item.status = STATUS_ARCHIVED

        m_tw_line_item.save_raw()
        res['success'] = True

        return res
コード例 #26
0
class TwitterPromotedTweet(BaseModel):
    tw_promoted_tweet_id = models.BigIntegerField(primary_key=True)
    tw_line_item_id = models.ForeignKey(TwitterLineItem,
                                        db_column='tw_line_item_id')
    tw_tweet_id = models.BigIntegerField()
    tw_app_card_id = models.BigIntegerField()

    status = models.CharField(max_length=8,
                              choices=STATUS_CHOICES,
                              default=STATUS_ENABLED)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TwitterPromotedTweetManager()
    objects_raw = models.Manager()

    # permission_check = True

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'tw_promoted_tweet'
        app_label = 'restapi'

    @property
    def _advertiser_id(self):
        return self.tw_line_item_id.tw_campaign_id.campaign_id.advertiser_id.advertiser_id

    @property
    def _campaign_id(self):
        return self.tw_line_item_id.tw_campaign_id.campaign_id.campaign_id

    @property
    def _tw_campaign_id(self):
        return self.tw_line_item_id.tw_campaign_id.tw_campaign_id

    @property
    def _tw_line_item_id(self):
        return self.tw_line_item_id.tw_line_item_id

    @classmethod
    def fetch_promoted_tweet(self,
                             data,
                             syncData=False,
                             oauth_token=settings.TW_ACCESS_TOKEN,
                             oauth_token_secret=settings.TW_ACCESS_SECRET):
        res = {}
        res['data'] = []
        res['success'] = False
        error_codes = {}
        account_id = data.get('account_id')
        line_item_id = data.get('line_item_id')
        os_platform = data.get('os_platform')
        line_item_id_int = None

        if isinstance(line_item_id, six.string_types):
            line_item_id_int = base36_to_int(line_item_id)

        if isinstance(line_item_id, (int, long)):
            line_item_id_int = line_item_id
            line_item_id = int_to_base36(line_item_id)
        else:
            line_item_id_int = base36_to_int(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 line_item_id is None:
            res = {
                'data': {},
                'success': False,
                'message': "Missing Twitter Line Item ID"
            }
            return res

        if line_item_id_int 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}/promoted_tweets?line_item_id={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()

            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}/promoted_tweets?line_item_id={line_item_id}&count=1000&cursor={next_cursor}&with_deleted=true'.format(
                        api_version=settings.TW_API_VERSION,
                        account_id=account.id,
                        line_item_id=line_item_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_promoted_tweet in enumerate(
                        res['data'], start=0):

                    line_item_promoted_tweet_res = self.sync_promoted_tweet(
                        account_id_int, line_item_id_int,
                        api_line_item_promoted_tweet, os_platform)
                    if 'success' in line_item_promoted_tweet_res and line_item_promoted_tweet_res[
                            'success'] is True:
                        if line_item_promoted_tweet_res['type'] == 'existing':
                            existing_count += 1
                        if line_item_promoted_tweet_res['type'] == 'new':
                            new_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
                        if line_item_promoted_tweet_res.get('errors', None):
                            error_codes.update(
                                line_item_promoted_tweet_res['errors'])

                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['errors'] = error_codes

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

                elif 'success' in line_item_promoted_tweet_res and line_item_promoted_tweet_res[
                        'success'] is False:
                    res['data'] = line_item_promoted_tweet_res['data']
                    res['sync']['success'] = line_item_promoted_tweet_res[
                        'success']
                    res['sync']['message'] = line_item_promoted_tweet_res[
                        'message']
                    if line_item_promoted_tweet_res.get('errors', None):
                        error_codes.update(
                            line_item_promoted_tweet_res['errors'])
                    res['errors'] = error_codes

        return res

    @classmethod
    def set_promoted_tweet(self,
                           data,
                           account_id,
                           oauth_token=settings.TW_ACCESS_TOKEN,
                           oauth_token_secret=settings.TW_ACCESS_SECRET):
        res = {}
        res['success'] = True
        line_item_id = data.get('line_item_id', None)
        tweet_ids = data.get('tweet_ids', None)

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

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

        tweet_ids_list = map(lambda s: s.strip(), tweet_ids.split(','))

        try:
            m_tw_line_item_promoted_tweet = TwitterPromotedTweet.objects_raw.filter(
                tw_line_item_id=line_item_id).exclude(
                    status=STATUS_ARCHIVED).values()
        except TwitterPromotedTweet.DoesNotExist:
            m_tw_line_item_promoted_tweet = None

        m_tw_line_item_promoted_tweet_list = list(
            m_tw_line_item_promoted_tweet
        )  # converts ValuesQuerySet into Python list

        new_list = []

        for item in tweet_ids_list:
            matching_item = False
            for m_item in m_tw_line_item_promoted_tweet_list:
                if int(item) == int(m_item['tw_tweet_id']):
                    # Remove matching existing item from list
                    m_tw_line_item_promoted_tweet_list.remove(m_item)
                    matching_item = True
                    break

            if matching_item is False:
                new_list.append(item)

        delete_list = m_tw_line_item_promoted_tweet_list
        new_res = None
        delete_res = None

        if new_list:
            data_post = {
                "account_id": account_id_int,
                "line_item_id": line_item_id_int,
                "tweet_ids": ",".join(new_list),
            }
            new_res = self.create(data_post,
                                  oauth_token=settings.TW_ACCESS_TOKEN,
                                  oauth_token_secret=settings.TW_ACCESS_SECRET)

        if delete_list:
            for item in delete_list:
                data_post = {
                    "account_id":
                    account_id_int,
                    "line_item_id":
                    line_item_id_int,
                    "promoted_tweet_id":
                    int_to_base36(item['tw_promoted_tweet_id']),
                }
                delete_res = self.delete(
                    data_post,
                    oauth_token=settings.TW_ACCESS_TOKEN,
                    oauth_token_secret=settings.TW_ACCESS_SECRET)

        if new_res:
            if new_res['success'] is False:
                res['success'] = False

        if delete_res:
            if delete_res['success'] is False:
                res['success'] = False

        # res['data'] = new_res['data']
        # res['sync'] = new_res['sync']
        return res

    @classmethod
    def create(self,
               data,
               oauth_token=settings.TW_ACCESS_TOKEN,
               oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.create_update_promoted_tweet(data, oauth_token,
                                                 oauth_token_secret, "post")

    @classmethod
    def update(self,
               data,
               oauth_token=settings.TW_ACCESS_TOKEN,
               oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.create_update_promoted_tweet(data, oauth_token,
                                                 oauth_token_secret, "put")

    @classmethod
    def delete(self,
               data,
               oauth_token=settings.TW_ACCESS_TOKEN,
               oauth_token_secret=settings.TW_ACCESS_SECRET):
        return self.create_update_promoted_tweet(data, oauth_token,
                                                 oauth_token_secret, "delete")

    @classmethod
    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

    @classmethod
    def sync_promoted_tweet(self,
                            tw_account_id,
                            tw_line_item_id,
                            data,
                            os_platform=None):
        from restapi.models.twitter.TwitterTweet import TwitterTweet
        res = {}
        res['data'] = data
        res['success'] = True
        promoted_tweet_id_int = base36_to_int(data['id'])
        m_tw_line_item_promoted_tweet = None

        if isinstance(tw_line_item_id, TwitterLineItem):
            m_tw_line_item = tw_line_item_id
        else:
            m_tw_line_item = TwitterLineItem.objects_raw.filter(
                tw_line_item_id=tw_line_item_id).first()

        if m_tw_line_item is None:
            res = {
                'data': {},
                'success':
                False,
                'message':
                "Error syncing Twitter Line Item Targeting. Cannot find Twitter Line Item"
            }
            return res

        if 'os_platform' not in data:
            os_platform = 'web'
            manage_campaign = m_tw_line_item.tw_campaign_id.campaign_id
            if manage_campaign and manage_campaign.targeting:
                targeting = json.loads(manage_campaign.targeting)
                if targeting and 'os' in targeting:
                    os_platform = targeting['os']
                    if os_platform == 'iOS':
                        os_platform = 'iphone'

        try:
            res['type'] = 'existing'
            m_tw_line_item_promoted_tweet = TwitterPromotedTweet.objects_raw.get(
                tw_line_item_id=m_tw_line_item,
                tw_promoted_tweet_id=promoted_tweet_id_int)
        except TwitterPromotedTweet.DoesNotExist:
            res['type'] = 'new'
            m_tw_line_item_promoted_tweet = TwitterPromotedTweet(
                tw_line_item_id=m_tw_line_item,
                tw_promoted_tweet_id=promoted_tweet_id_int)

        sync_tweet = True
        if m_tw_line_item_promoted_tweet.tw_app_card_id is not None:
            sync_tweet = False

        if m_tw_line_item_promoted_tweet is None:
            res = {
                'data': {},
                'success':
                False,
                'message':
                "Error syncing Twitter Line Item Promoted Tweet. Cannot find Twitter Promoted Tweet"
            }
            return res

        if data['paused'] == True:
            m_tw_line_item_promoted_tweet.status = STATUS_PAUSED
        elif data['paused'] == False:
            m_tw_line_item_promoted_tweet.status = STATUS_ENABLED
        if data['deleted'] == True:
            res['type'] = 'delete'
            m_tw_line_item_promoted_tweet.status = STATUS_ARCHIVED
        m_tw_line_item_promoted_tweet.save()

        m_tw_line_item_promoted_tweet.tw_tweet_id = data['tweet_id']

        try:
            m_tw_line_item_tweet = TwitterTweet.objects_raw.get(
                tw_tweet_id=data['tweet_id'])
            sync_tweet = False
        except TwitterTweet.DoesNotExist:
            m_tw_line_item_tweet = TwitterTweet(tw_tweet_id=data['tweet_id'])

        if m_tw_line_item_tweet is None:
            res = {
                'data': {},
                'success':
                False,
                'message':
                "Error syncing Twitter Line Item Tweet. Cannot find Twitter Tweet"
            }
            return res

        # Don't fetch tweet data if we already have tw_promoted_tweet.tw_app_card_id and tw_tweet.tw_tweet_id
        # https://managewiki.atlassian.net/browse/ADP-138
        if sync_tweet:
            api_tweet_details_data = TwitterTweet.fetch_tweet(
                dict(account_id=tw_account_id, tweet_id=data['tweet_id']))
            if api_tweet_details_data['success'] is False:
                res['success'] = False
                res['message'] = api_tweet_details_data[
                    'message'] if 'message' in api_tweet_details_data else ''
                res['errors'] = api_tweet_details_data[
                    'errors'] if 'errors' in api_tweet_details_data else {}

            # Check if App Card in Tweeet
            api_tweet_app_card = api_tweet_details_data.get('card_url')
            tweet_app_card = None
            if api_tweet_app_card is not None:
                try:
                    tweet_app_card = TwitterAppCard.objects_raw.get(
                        preview_url=api_tweet_app_card)
                except TwitterAppCard.DoesNotExist:
                    tweet_app_card = None

                if tweet_app_card:
                    m_tw_line_item_promoted_tweet.tw_app_card_id = tweet_app_card.tw_app_card_id

            if m_tw_line_item_tweet:
                api_tweet_details = api_tweet_details_data['data']
                for api_tweet_detail in api_tweet_details:
                    if api_tweet_detail['platform'] == os_platform.lower():
                        m_tw_line_item_tweet.text = api_tweet_detail['preview']
                        m_tw_line_item_tweet.save_raw()
                        continue
        try:
            m_tw_line_item_promoted_tweet.save_raw()
            res['success'] = True
        except _mysql_exceptions.Warning, e:
            res = {
                'data': {},
                'success': False,
                'message': "Error syncing Twitter Line Item Targeting"
            }

        return res
コード例 #27
0
ファイル: Campaign.py プロジェクト: louiskdev/restapi-drf
class Campaign(BasePausedAtModelMixin, BaseModel):
    campaign_id = models.AutoField(primary_key=True)
    advertiser_id = models.ForeignKey(Advertiser, db_column='advertiser_id')
    campaign = models.CharField(max_length=255)
    notes = models.TextField(blank=True)
    sampling_rate = models.DecimalField(max_digits=9, decimal_places=8, blank=True, null=True)
    throttling_rate = models.DecimalField(max_digits=9, decimal_places=8, blank=True, null=True)
    domain = models.CharField(max_length=255)
    redirect_url = models.CharField(max_length=1024, blank=True)
    destination_url = models.CharField(max_length=511)
    viewthrough_url = models.CharField(max_length=1024, blank=True, default='')
    tracking_provider_id = models.ForeignKey(TrackingProvider, db_column='tracking_provider_id', null=True)
    inflator_text = models.CharField(max_length=1024, blank=True)
    frequency_map = OrderedJSONField(blank=True, default='', cmp=cmp_asterisk_last, default_json=str)
    priority = models.IntegerField(blank=True, default=0)
    daily_budget_type = models.CharField(max_length=10,
                                         blank=True,
                                         choices=BUDGET_TYPES_CHOICES,
                                         default=BUDGET_TYPES_CHOICES[0][0])
    daily_budget_value = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    daily_spend = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    status = models.CharField(max_length=8, choices=STATUS_CHOICES, default=STATUS_CHOICES[1][0])
    distribution_app_sha1_mac = models.BooleanField(default=False, blank=True)
    distribution_app_sha1_udid = models.BooleanField(default=False, blank=True)
    distribution_app_sha1_android_id = models.BooleanField(default=False, blank=True)  # pylint: disable=invalid-name
    distribution_app_ifa = models.BooleanField(default=False, blank=True)
    distribution_app_md5_ifa = models.BooleanField(default=False, blank=True)
    distribution_app_xid = models.BooleanField(default=False, blank=True)
    distribution_web = models.BooleanField(default=False, blank=True)
    flight_start_date = ZeroDateTimeField(default=None, null=True, blank=True)
    flight_end_date = ZeroDateTimeField(default=None, null=True, blank=True)
    flight_budget_type = models.CharField(max_length=10,
                                          blank=True,
                                          choices=BUDGET_TYPES_CHOICES,
                                          default=BUDGET_TYPES_CHOICES[0][0])
    flight_budget_value = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    attribution_window = models.IntegerField(blank=True, null=True)
    genre = models.IntegerField()
    capped = models.IntegerField(blank=True, default=0)
    hourly_capped = models.IntegerField(blank=True, default=0)
    is_test = models.IntegerField(blank=True, default=0)
    bidder_args = models.CharField(max_length=255, blank=True, default='')
    last_update = DateTimeField(null=True, default=None, auto_now=True)
    paused_at = ZeroDateTimeField(default=None, null=True, blank=True)

    external_id = models.CharField(max_length=100, blank=True, null=True)
    categories = models.TextField(blank=True)
    targeting = models.TextField(blank=True, default='')
    os = models.IntegerField(blank=True, default=1)
    overridden = models.BooleanField(default=False, blank=True)

    ignore_fatigue_segment = models.BooleanField(default=False, blank=True)
    ignore_suppression_segment = models.BooleanField(default=False, blank=True)

    total_cost_cap = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    daily_cost_cap = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    total_loss_cap = models.DecimalField(max_digits=9, decimal_places=2, default=0)
    daily_loss_cap = models.DecimalField(max_digits=9, decimal_places=2, default=0)

    app_install = models.BooleanField(default=False, blank=True)

    source_type = models.IntegerField(max_length=3, default=1)

    actions = ('filter_by_trading_desk', 'targeting_json_read', 'targeting_json_update')

    objects = CampaignManager()
    objects_raw = models.Manager()
    permission_check = True

    def is_own(self):
        """Returns True if campaign entity belongs to the current user."""
        advertiser_ids = REGISTRY.get('user_advertiser_ids')
        if advertiser_ids and self.advertiser_id_id in advertiser_ids:
            return True

        agency_ids = REGISTRY.get('user_agency_ids')
        if agency_ids and Campaign.objects.filter(advertiser_id__agency_id__in=agency_ids,
                                                  campaign_id=self.campaign_id).exists():
            return True

        trading_desk_ids = REGISTRY.get('user_trading_desk_ids')
        if trading_desk_ids and Campaign.objects.filter(advertiser_id__agency_id__trading_desk_id__in=trading_desk_ids,
                                                        campaign_id=self.campaign_id).exists():
            return True

        return False

    def autopopulate_by_ownership(self):
        pass

    search_args = ('campaign_id', 'campaign__icontains')

    @property
    def search_result(self):
        advertiser = self.advertiser_id
        agency = self.advertiser_id.agency_id
        result = {'level': 'campaign',
                  'campaign': self.campaign,
                  'campaign_id': self.campaign_id,
                  'advertiser': advertiser.advertiser,
                  'advertiser_id': advertiser.advertiser_id,
                  'agency': agency.agency,
                  'agency_id': agency.agency_id,
                  'last_update': self.last_update}
        return result

    @property
    def other_iab_classification(self):
        classification = []
        if self.categories is not None:
            for category in self.categories.split(" "):
                if category in dict(OTHER_IAB_CATEGORIES):
                    classification.append(category)
        return classification

    @property
    def manage_classification(self):
        classification = []
        if self.categories is not None:
            for category in self.categories.split(" "):
                if category in dict(MANAGE_CATEGORIES):
                    classification.append(category)
        return classification

    @property
    def iab_classification(self):
        classification = []
        if self.categories is not None:
            for category in self.categories.split(" "):
                if category in dict(IAB_CATEGORIES):
                    classification.append(category)
        return classification

    @property
    def parent_name(self):
        return self.advertiser_id.advertiser

    @property
    def agency_name(self):
        return self.advertiser_id.agency_id.agency

    @property
    def trading_desk_name(self):
        return self.advertiser_id.agency_id.trading_desk_id.trading_desk

    @property
    def advertiser(self):
        return self.advertiser_id.advertiser

    @property
    def agency(self):
        return self.advertiser_id.agency_id.agency

    @property
    def agency_id(self):
        return self.advertiser_id.agency_id.agency_id

    @property
    def _advertiser_id(self):
        return self.advertiser_id.advertiser_id

    @property
    def trading_desk(self):
        return self.advertiser_id.agency_id.trading_desk_id.trading_desk

    @property
    def trading_desk_id(self):
        return self.advertiser_id.agency_id.trading_desk_id.trading_desk_id

    @property
    def ad_groups_enabled(self):
        from restapi.models.AdGroup import AdGroup as model
        return model.objects.getCount(campaign_id=self.pk, status=STATUS_ENABLED)

    @property
    def ad_groups_total(self):
        from restapi.models.AdGroup import AdGroup as model
        return model.objects.getCount(campaign_id=self.pk)

    @property
    def ads_enabled(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id__campaign_id=self.pk, status=STATUS_ENABLED)

    @property
    def ads_disapproved(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id__campaign_id=self.pk,
                                      adx_status=AD_STATUS_DISAPPROVED,
                                      status=STATUS_ENABLED)

    @property
    def a9_pending(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id__campaign_id=self.pk,
                                      a9_status=A9_STATUS_PENDING,
                                      status=STATUS_ENABLED)

    @property
    def a9_failed(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id__campaign_id=self.pk,
                                      a9_status=A9_STATUS_FAILED,
                                      status=STATUS_ENABLED)

    @property
    def ads_total(self):
        from restapi.models.Ad import Ad as model
        return model.objects.getCount(ad_group_id__campaign_id=self.pk)

    @property
    def black_lists_total(self):
        from restapi.models.BidderBlacklist import BidderBlacklistIds as model
        return model.objects.getCount(campaign_id=self.pk)

    @property
    def black_lists_campaign(self):
        from restapi.models.BidderBlacklist import BidderBlacklistIds as model
        return model.objects.getCount(campaign_id=self.pk, ad_group_id=0)

    @property
    def black_lists_ad_group(self):
        from restapi.models.BidderBlacklist import BidderBlacklistIds as model
        return model.objects.getCount(campaign_id=self.pk, ad_group_id__gt=0)

    @property
    def white_lists_total(self):
        from restapi.models.BidderWhitelist import BidderWhitelistIds as model
        return model.objects.getCount(campaign_id=self.pk)

    @property
    def white_lists_campaign(self):
        from restapi.models.BidderWhitelist import BidderWhitelistIds as model
        return model.objects.getCount(campaign_id=self.pk, ad_group_id=0)

    @property
    def white_lists_ad_group(self):
        from restapi.models.BidderWhitelist import BidderWhitelistIds as model
        return model.objects.getCount(campaign_id=self.pk, ad_group_id__gt=0)

    @property
    def custom_hints_total(self):
        from restapi.models.CustomHint import CustomHintIds as model
        return model.objects.getCount(campaign_id=self.pk)

    @property
    def custom_hints_campaign(self):
        from restapi.models.CustomHint import CustomHintIds as model
        return model.objects.getCount(campaign_id=self.pk, ad_group_id=0)

    @property
    def custom_hints_ad_group(self):
        from restapi.models.CustomHint import CustomHintIds as model
        return model.objects.getCount(campaign_id=self.pk, ad_group_id__gt=0)

    @property
    def discrete_pricing_total(self):
        from restapi.models.DiscretePricing import DiscretePricingIds as model
        return model.objects.getCount(campaign_id=self.pk)

    @property
    def discrete_pricing_campaign(self):
        from restapi.models.DiscretePricing import DiscretePricingIds as model
        return model.objects.getCount(campaign_id=self.pk, ad_group_id=0)

    @property
    def discrete_pricing_ad_group(self):
        from restapi.models.DiscretePricing import DiscretePricingIds as model
        return model.objects.getCount(campaign_id=self.pk, ad_group_id__gt=0)

    @property
    def ads_to_pause(self):
        """Returns a number of ads recommended to pause."""
        from restapi.models.CreativePruning import CreativePruning
        return CreativePruning.objects.getCount(ad_id__ad_group_id__campaign_id=self.pk, action='pause')

    @property
    def ads_to_delete(self):
        """Returns a number of ads recommended to delete."""
        from restapi.models.CreativePruning import CreativePruning
        return CreativePruning.objects.getCount(ad_id__ad_group_id__campaign_id=self.pk, action='delete')

    def __unicode__(self):
        return self.campaign

    class Meta:
        managed = True
        unique_together = ('advertiser_id', 'campaign')
        db_table = 'campaign'
        app_label = 'restapi'
        ordering = ('campaign',)
コード例 #28
0
class TwitterAccount(BaseModel):
    tw_account_id = models.BigIntegerField(primary_key=True)
    tw_twitter_user_id =  models.ForeignKey(TwitterUser, db_column='tw_twitter_user_id', related_name="tw_account_tw_twitter_user")
    promotable_user_id = models.ForeignKey(TwitterUser, db_column='promotable_user_id', related_name="tw_account_tw_promotable_user")
    advertiser_id = models.ForeignKey(Advertiser, db_column='advertiser_id')
    is_manage = models.BooleanField(default=False)
    name = models.CharField(max_length=255)
    status = models.CharField(max_length=8, choices=STATUS_CHOICES, default=STATUS_ENABLED)
    created_at = DateTimeField(auto_now_add=True)
    last_update = DateTimeField(null=True, default=None, auto_now=True)

    objects = TwitterAccountManager()
    objects_raw = models.Manager()
    # permission_check = True

    def __unicode__(self):
        return self.name

    class Meta:
        db_table = 'tw_account'
        app_label = 'restapi'


    @classmethod
    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