Example #1
0
    def GET_promote_inventory(self, start, end, sr_name, collection_name):
        if not start or not end:
            start = promote.promo_datetime_now(offset=1).date()
            end = promote.promo_datetime_now(offset=8).date()
            c.errors.remove((errors.BAD_DATE, 'startdate'))
            c.errors.remove((errors.BAD_DATE, 'enddate'))

        target = Target(Frontpage.name)
        if sr_name:
            try:
                sr = Subreddit._by_name(sr_name)
                target = Target(sr.name)
            except NotFound:
                c.errors.add(errors.SUBREDDIT_NOEXIST, field='sr_name')
        elif collection_name:
            collection = Collection.by_name(collection_name)
            if not collection:
                c.errors.add(errors.COLLECTION_NOEXIST, field='collection_name')
            else:
                target = Target(collection)

        content = PromoteInventory(start, end, target)

        if c.render_style == 'csv':
            return content.as_csv()
        else:
            return PromotePage(title=_("sponsored link inventory"),
                               content=content).render()
Example #2
0
    def GET_promote_inventory(self, start, end, sr_name, collection_name):
        if not start or not end:
            start = promote.promo_datetime_now(offset=1).date()
            end = promote.promo_datetime_now(offset=8).date()
            c.errors.remove((errors.BAD_DATE, 'startdate'))
            c.errors.remove((errors.BAD_DATE, 'enddate'))

        target = Target(Frontpage.name)
        if sr_name:
            try:
                sr = Subreddit._by_name(sr_name)
                target = Target(sr.name)
            except NotFound:
                c.errors.add(errors.SUBREDDIT_NOEXIST, field='sr_name')
        elif collection_name:
            collection = Collection.by_name(collection_name)
            if not collection:
                c.errors.add(errors.COLLECTION_NOEXIST,
                             field='collection_name')
            else:
                target = Target(collection)

        content = PromoteInventory(start, end, target)
        return PromotePage(title=_("sponsored link inventory"),
                           content=content).render()
Example #3
0
    def GET_promote_inventory(self, start, end, sr_name):
        if not start or not end:
            start = promote.promo_datetime_now(offset=1).date()
            end = promote.promo_datetime_now(offset=8).date()
            c.errors.remove((errors.BAD_DATE, 'startdate'))
            c.errors.remove((errors.BAD_DATE, 'enddate'))

        sr = Frontpage
        if sr_name:
            try:
                sr = Subreddit._by_name(sr_name)
            except NotFound:
                c.errors.add(errors.SUBREDDIT_NOEXIST, field='sr_name')

        content = PromoteInventory(start, end, sr)
        return PromotePage("promote_inventory", content=content).render()
Example #4
0
    def get_traffic(cls, thing, start, end):
        """Retrieve traffic by interval for a Promoted Link or PromoCampaign."""
        history = get_promo_traffic(thing, start, end)
        interval = cls.get_interval(thing)
        needs_hour_adjustment = _use_adserver_reporting(thing)
        promote_hour = promote.promo_datetime_now().hour

        computed_history = []
        for date, data in history:
            imps = data[0]
            clicks = data[1]
            spent = None if len(data) == 2 else data[2]
            ctr = _clickthrough_rate(imps, clicks)

            # replace hour to ensure that adserver dates appear correct
            # since we store them without the promotion hour.
            if needs_hour_adjustment:
                date = date.replace(hour=promote_hour)

            date = date.replace(tzinfo=pytz.utc)
            date = date.astimezone(pytz.timezone("EST"))
            datestr = format_datetime(
                date,
                locale=c.locale,
                format=cls.date_format_by_interval.get(interval),
            )
            values = ((imps, format_number(imps)), (clicks, format_number(clicks)), (ctr, format_number(ctr)))
            if spent is not None:
                values = ((spent, format_currency(spent, 'USD', locale=c.locale)),) + values
            computed_history.append((date, datestr, values))
        return computed_history
Example #5
0
    def GET_promote_inventory(self, start, end, sr_name):
        if not start or not end:
            start = promote.promo_datetime_now(offset=1).date()
            end = promote.promo_datetime_now(offset=8).date()
            c.errors.remove((errors.BAD_DATE, 'startdate'))
            c.errors.remove((errors.BAD_DATE, 'enddate'))

        sr = Frontpage
        if sr_name:
            try:
                sr = Subreddit._by_name(sr_name)
            except NotFound:
                c.errors.add(errors.SUBREDDIT_NOEXIST, field='sr_name')

        content = PromoteInventory(start, end, sr)
        return PromotePage("promote_inventory", content=content).render()
Example #6
0
    def get_traffic(cls, thing, start, end):
        """Retrieve traffic by interval for a Promoted Link or PromoCampaign."""
        history = get_promo_traffic(thing, start, end)
        interval = cls.get_interval(thing)
        needs_hour_adjustment = _use_adserver_reporting(thing)
        promote_hour = promote.promo_datetime_now().hour

        computed_history = []
        for date, data in history:
            imps = data[0]
            clicks = data[1]
            spent = None if len(data) == 2 else data[2]
            ctr = _clickthrough_rate(imps, clicks)

            # replace hour to ensure that adserver dates appear correct
            # since we store them without the promotion hour.
            if needs_hour_adjustment:
                date = date.replace(hour=promote_hour)

            date = date.replace(tzinfo=pytz.utc)
            date = date.astimezone(pytz.timezone("EST"))
            datestr = format_datetime(
                date,
                locale=c.locale,
                format=cls.date_format_by_interval.get(interval),
            )
            values = ((imps, format_number(imps)), (clicks,
                                                    format_number(clicks)),
                      (ctr, format_number(ctr)))
            if spent is not None:
                values = ((spent, format_currency(
                    spent, 'USD', locale=c.locale)), ) + values
            computed_history.append((date, datestr, values))
        return computed_history
Example #7
0
def _check_dates(dates):
    params = ('startdate', 'enddate')
    error_types = (errors.BAD_DATE, errors.BAD_FUTURE_DATE,
                   errors.BAD_PAST_DATE, errors.BAD_DATE_RANGE,
                   errors.DATE_RANGE_TOO_LARGE)
    for error_case in itertools.product(error_types, params):
        if error_case in c.errors:
            bad_dates = dates
            start, end = None, None
            break
    else:
        bad_dates = None
        start, end = dates
    if not start or not end:
        start = promote.promo_datetime_now(offset=-7).date()
        end = promote.promo_datetime_now(offset=6).date()
    return start, end, bad_dates
Example #8
0
 def get_house_campaigns(cls):
     now = promote.promo_datetime_now()
     pws = PromotionWeights.get_campaigns(now)
     campaign_ids = {pw.promo_idx for pw in pws}
     campaigns = PromoCampaign._byID(campaign_ids, data=True,
                                     return_dict=False)
     campaigns = [camp for camp in campaigns if not camp.priority.cpm]
     return campaigns
Example #9
0
 def get_house_link_names(cls):
     now = promote.promo_datetime_now()
     pws = PromotionWeights.get_campaigns(now)
     campaign_ids = {pw.promo_idx for pw in pws}
     q = PromoCampaign._query(PromoCampaign.c._id.in_(campaign_ids),
                              PromoCampaign.c.priority_name == 'house',
                              data=True)
     return [Link._fullname_from_id36(to36(camp.link_id)) for camp in q]
Example #10
0
 def get_house_link_names(cls):
     now = promote.promo_datetime_now()
     pws = PromotionWeights.get_campaigns(now)
     campaign_ids = {pw.promo_idx for pw in pws}
     q = PromoCampaign._query(PromoCampaign.c._id.in_(campaign_ids),
                              PromoCampaign.c.priority_name == 'house',
                              data=True)
     return [Link._fullname_from_id36(to36(camp.link_id)) for camp in q]
Example #11
0
    def GET_report(self, start, end, grouping, link_text=None, owner=None):
        now = datetime.now(g.tz).replace(hour=0,
                                         minute=0,
                                         second=0,
                                         microsecond=0)
        if not start or not end:
            start = promote.promo_datetime_now(offset=1).date()
            end = promote.promo_datetime_now(offset=8).date()
            c.errors.remove((errors.BAD_DATE, 'startdate'))
            c.errors.remove((errors.BAD_DATE, 'enddate'))
        end = end or now - timedelta(days=1)
        start = start or end - timedelta(days=7)

        links = []
        bad_links = []
        owner_name = owner.name if owner else ''

        if owner:
            campaign_ids = PromotionWeights.get_campaign_ids(
                start, end, author_id=owner._id)
            campaigns = PromoCampaign._byID(campaign_ids, data=True)
            link_ids = {camp.link_id for camp in campaigns.itervalues()}
            links.extend(Link._byID(link_ids, data=True, return_dict=False))

        if link_text is not None:
            id36s = link_text.replace(',', ' ').split()
            try:
                links_from_text = Link._byID36(id36s, data=True)
            except NotFound:
                links_from_text = {}

            bad_links = [id36 for id36 in id36s if id36 not in links_from_text]
            links.extend(links_from_text.values())

        content = PromoteReport(links,
                                link_text,
                                owner_name,
                                bad_links,
                                start,
                                end,
                                group_by_date=grouping == "day")
        if c.render_style == 'csv':
            return content.as_csv()
        else:
            return PromotePage(title=_("sponsored link report"),
                               content=content).render()
Example #12
0
 def get_house_link_names(cls):
     now = promote.promo_datetime_now()
     campaign_ids = PromotionWeights.get_campaign_ids(now)
     q = PromoCampaign._query(PromoCampaign.c._id.in_(campaign_ids),
                              PromoCampaign.c.priority_name == 'house',
                              data=True)
     link_names = {Link._fullname_from_id36(to36(camp.link_id))
                   for camp in q}
     return sorted(link_names, reverse=True)
Example #13
0
    def POST_update_pay(self, form, jquery, link, campaign, customer_id,
                        pay_id, edit, address, creditcard):
        if not g.authorizenetapi:
            return

        if not link or not campaign or link._id != campaign.link_id:
            return abort(404, 'not found')

        # Check inventory
        if campaign_has_oversold_error(form, campaign):
            return

        # check that start is not so late that authorization hold will expire
        max_start = promote.get_max_startdate()
        if campaign.start_date > max_start:
            msg = _("please change campaign start date to %(date)s or earlier")
            date = format_date(max_start, format="short", locale=c.locale)
            msg %= {'date': date}
            form.set_text(".status", msg)
            return

        # check the campaign start date is still valid (user may have created
        # the campaign a few days ago)
        now = promote.promo_datetime_now()
        min_start = now + timedelta(days=g.min_promote_future)
        if campaign.start_date.date() < min_start.date():
            msg = _("please change campaign start date to %(date)s or later")
            date = format_date(min_start, format="short", locale=c.locale)
            msg %= {'date': date}
            form.set_text(".status", msg)
            return

        address_modified = not pay_id or edit
        if address_modified:
            address_fields = [
                "firstName", "lastName", "company", "address", "city", "state",
                "zip", "country", "phoneNumber"
            ]
            card_fields = ["cardNumber", "expirationDate", "cardCode"]

            if (form.has_errors(address_fields, errors.BAD_ADDRESS)
                    or form.has_errors(card_fields, errors.BAD_CARD)):
                return

            pay_id = edit_profile(c.user, address, creditcard, pay_id)

        reason = None
        if pay_id:
            success, reason = promote.auth_campaign(link, campaign, c.user,
                                                    pay_id)

            if success:
                form.redirect(promote.promo_edit_url(link))
                return

        msg = reason or _("failed to authenticate card. sorry.")
        form.set_text(".status", msg)
Example #14
0
 def get_house_link_names(cls):
     now = promote.promo_datetime_now()
     campaign_ids = PromotionWeights.get_campaign_ids(now)
     q = PromoCampaign._query(PromoCampaign.c._id.in_(campaign_ids),
                              PromoCampaign.c.priority_name == 'house',
                              data=True)
     link_names = {Link._fullname_from_id36(to36(camp.link_id))
                   for camp in q}
     return sorted(link_names, reverse=True)
Example #15
0
 def get_house_campaigns(cls):
     now = promote.promo_datetime_now()
     pws = PromotionWeights.get_campaigns(now)
     campaign_ids = {pw.promo_idx for pw in pws}
     campaigns = PromoCampaign._byID(campaign_ids,
                                     data=True,
                                     return_dict=False)
     campaigns = [camp for camp in campaigns if not camp.priority.cpm]
     return campaigns
Example #16
0
def _check_dates(dates):
    params = ('startdate', 'enddate')
    error_types = (errors.BAD_DATE,
                   errors.BAD_FUTURE_DATE,
                   errors.BAD_PAST_DATE,
                   errors.BAD_DATE_RANGE,
                   errors.DATE_RANGE_TOO_LARGE)
    for error_case in itertools.product(error_types, params):
        if error_case in c.errors:
            bad_dates = dates
            start, end = None, None
            break
    else:
        bad_dates = None
        start, end = dates
    if not start or not end:
        start = promote.promo_datetime_now(offset=-7).date()
        end = promote.promo_datetime_now(offset=6).date()
    return start, end, bad_dates
Example #17
0
    def POST_update_pay(self, form, jquery, link, campaign, customer_id, pay_id,
                        edit, address, creditcard):
        if not g.authorizenetapi:
            return

        if not link or not campaign or link._id != campaign.link_id:
            return abort(404, 'not found')

        # Check inventory
        if campaign_has_oversold_error(form, campaign):
            return

        # check that start is not so late that authorization hold will expire
        max_start = promote.get_max_startdate()
        if campaign.start_date > max_start:
            msg = _("please change campaign start date to %(date)s or earlier")
            date = format_date(max_start, format="short", locale=c.locale)
            msg %= {'date': date}
            form.set_html(".status", msg)
            return

        # check the campaign start date is still valid (user may have created
        # the campaign a few days ago)
        now = promote.promo_datetime_now()
        min_start = now + timedelta(days=g.min_promote_future)
        if campaign.start_date.date() < min_start.date():
            msg = _("please change campaign start date to %(date)s or later")
            date = format_date(min_start, format="short", locale=c.locale)
            msg %= {'date': date}
            form.set_html(".status", msg)
            return

        address_modified = not pay_id or edit
        if address_modified:
            address_fields = ["firstName", "lastName", "company", "address",
                              "city", "state", "zip", "country", "phoneNumber"]
            card_fields = ["cardNumber", "expirationDate", "cardCode"]

            if (form.has_errors(address_fields, errors.BAD_ADDRESS) or
                    form.has_errors(card_fields, errors.BAD_CARD)):
                return

            pay_id = edit_profile(c.user, address, creditcard, pay_id)

        reason = None
        if pay_id:
            success, reason = promote.auth_campaign(link, campaign, c.user,
                                                    pay_id)

            if success:
                form.redirect(promote.promo_edit_url(link))
                return

        msg = reason or _("failed to authenticate card. sorry.")
        form.set_html(".status", msg)
Example #18
0
    def GET_report(self, start, end, link_text=None, owner=None):
        now = datetime.now(g.tz).replace(hour=0, minute=0, second=0,
                                         microsecond=0)
        if not start or not end:
            start = promote.promo_datetime_now(offset=1).date()
            end = promote.promo_datetime_now(offset=8).date()
            c.errors.remove((errors.BAD_DATE, 'startdate'))
            c.errors.remove((errors.BAD_DATE, 'enddate'))
        end = end or now - timedelta(days=1)
        start = start or end - timedelta(days=7)

        links = []
        bad_links = []
        owner_name = owner.name if owner else ''

        if owner:
            promo_weights = PromotionWeights.get_campaigns(start, end,
                                                           author_id=owner._id)
            campaign_ids = [pw.promo_idx for pw in promo_weights]
            campaigns = PromoCampaign._byID(campaign_ids, data=True)
            link_ids = {camp.link_id for camp in campaigns.itervalues()}
            links.extend(Link._byID(link_ids, data=True, return_dict=False))

        if link_text is not None:
            id36s = link_text.replace(',', ' ').split()
            try:
                links_from_text = Link._byID36(id36s, data=True)
            except NotFound:
                links_from_text = {}

            bad_links = [id36 for id36 in id36s if id36 not in links_from_text]
            links.extend(links_from_text.values())

        content = PromoteReport(links, link_text, owner_name, bad_links, start,
                                end)
        if c.render_style == 'csv':
            return content.as_csv()
        else:
            return PromotePage(title=_("sponsored link report"),
                               content=content).render()
Example #19
0
 def GET_inventory(self, sr_name):
     '''
     Return available inventory data as json for use in ajax calls
     '''
     inv_start_date = promote.promo_datetime_now()
     inv_end_date = inv_start_date + timedelta(60)
     inventory = promote.get_available_impressions(sr_name,
                                                   inv_start_date,
                                                   inv_end_date,
                                                   fuzzed=(not c.user_is_admin))
     dates = []
     impressions = []
     max_imps = 0
     for date, imps in inventory.iteritems():
         dates.append(date.strftime("%m/%d/%Y"))
         impressions.append(imps)
         max_imps = max(max_imps, imps)
     return json.dumps({'sr':sr_name,
                        'dates': dates,
                        'imps':impressions,
                        'max_imps':max_imps})
Example #20
0
 def GET_inventory(self, sr_name):
     '''
     Return available inventory data as json for use in ajax calls
     '''
     inv_start_date = promote.promo_datetime_now()
     inv_end_date = inv_start_date + timedelta(60)
     inventory = promote.get_available_impressions(
         sr_name,
         inv_start_date,
         inv_end_date,
         fuzzed=(not c.user_is_admin)
     )
     dates = []
     impressions = []
     max_imps = 0
     for date, imps in inventory.iteritems():
         dates.append(date.strftime("%m/%d/%Y"))
         impressions.append(imps)
         max_imps = max(max_imps, imps)
     return json.dumps({'sr':sr_name,
                        'dates': dates,
                        'imps':impressions,
                        'max_imps':max_imps})
Example #21
0
    def POST_update_pay(self, form, jquery, link, campaign, customer_id, pay_id,
                        edit, address, creditcard):
        if not g.authorizenetapi:
            return

        if not link or not campaign or link._id != campaign.link_id:
            return abort(404, 'not found')

        # Check inventory
        if campaign_has_oversold_error(form, campaign):
            return

        # check that start is not so late that authorization hold will expire
        max_start = promote.get_max_startdate()
        if campaign.start_date > max_start:
            msg = _("please change campaign start date to %(date)s or earlier")
            date = format_date(max_start, format="short", locale=c.locale)
            msg %= {'date': date}
            form.set_text(".status", msg)
            return

        # check the campaign start date is still valid (user may have created
        # the campaign a few days ago)
        now = promote.promo_datetime_now()
        min_start = now + timedelta(days=g.min_promote_future)
        if campaign.start_date.date() < min_start.date():
            msg = _("please change campaign start date to %(date)s or later")
            date = format_date(min_start, format="short", locale=c.locale)
            msg %= {'date': date}
            form.set_text(".status", msg)
            return

        new_payment = not pay_id

        address_modified = new_payment or edit
        if address_modified:
            address_fields = ["firstName", "lastName", "company", "address",
                              "city", "state", "zip", "country", "phoneNumber"]
            card_fields = ["cardNumber", "expirationDate", "cardCode"]

            if (form.has_errors(address_fields, errors.BAD_ADDRESS) or
                    form.has_errors(card_fields, errors.BAD_CARD)):
                return

            pay_id = edit_profile(c.user, address, creditcard, pay_id)

            if pay_id:
                promote.new_payment_method(user=c.user, ip=request.ip, address=address, link=link)

        if pay_id:
            success, reason = promote.auth_campaign(link, campaign, c.user,
                                                    pay_id)

            if success:
                hooks.get_hook("promote.campaign_paid").call(link=link, campaign=campaign)
                if not address and g.authorizenetapi:
                    profiles = get_account_info(c.user).paymentProfiles
                    profile = {p.customerPaymentProfileId: p for p in profiles}[pay_id]

                    address = profile.billTo

                promote.successful_payment(link, campaign, request.ip, address)

                jquery.payment_redirect(promote.promo_edit_url(link), new_payment, campaign.bid)
                return
            else:
                promote.failed_payment_method(c.user, link)
                msg = reason or _("failed to authenticate card. sorry.")
                form.set_text(".status", msg)
        else:
            promote.failed_payment_method(c.user, link)
            form.set_text(".status", _("failed to authenticate card. sorry."))
Example #22
0
    def POST_edit_campaign(self, form, jquery, link, campaign_id36, dates, bid, sr, targeting):
        if not link:
            return

        start, end = dates or (None, None)

        author = Account._byID(link.author_id, data=True)
        cpm = author.cpm_selfserve_pennies

        if start and end and not promote.is_accepted(link) and not c.user_is_sponsor:
            # if the ad is not approved already, ensure the start date
            # is at least 2 days in the future
            start = start.date()
            end = end.date()
            now = promote.promo_datetime_now()
            future = make_offset_date(now, g.min_promote_future, business_days=True)
            if start < future.date():
                c.errors.add(errors.BAD_FUTURE_DATE, msg_params=dict(day=g.min_promote_future), field="startdate")

        if form.has_errors("startdate", errors.BAD_DATE, errors.BAD_FUTURE_DATE) or form.has_errors(
            "enddate", errors.BAD_DATE, errors.BAD_FUTURE_DATE, errors.BAD_DATE_RANGE
        ):
            return

        # Limit the number of PromoCampaigns a Link can have
        # Note that the front end should prevent the user from getting
        # this far
        existing_campaigns = list(PromoCampaign._by_link(link._id))
        if len(existing_campaigns) > g.MAX_CAMPAIGNS_PER_LINK:
            c.errors.add(errors.TOO_MANY_CAMPAIGNS, msg_params={"count": g.MAX_CAMPAIGNS_PER_LINK}, field="title")
            form.has_errors("title", errors.TOO_MANY_CAMPAIGNS)
            return

        if form.has_errors("bid", errors.BAD_BID):
            return

        if campaign_id36:
            # you cannot edit the bid of a live ad unless it's a freebie
            try:
                campaign = PromoCampaign._byID36(campaign_id36)
                if bid != campaign.bid and campaign.start_date < datetime.now(g.tz) and not campaign.is_freebie():
                    c.errors.add(errors.BID_LIVE, field="bid")
                    form.has_errors("bid", errors.BID_LIVE)
                    return
            except NotFound:
                pass

        min_bid = 0 if c.user_is_sponsor else g.min_promote_bid
        if bid is None or bid < min_bid:
            c.errors.add(errors.BAD_BID, field="bid", msg_params={"min": min_bid, "max": g.max_promote_bid})
            form.has_errors("bid", errors.BAD_BID)
            return

        if targeting == "one":
            if form.has_errors("sr", errors.SUBREDDIT_NOEXIST, errors.SUBREDDIT_NOTALLOWED, errors.SUBREDDIT_REQUIRED):
                # checking to get the error set in the form, but we can't
                # check for rate-limiting if there's no subreddit
                return

            roadblock = PromotedLinkRoadblock.is_roadblocked(sr, start, end)
            if roadblock and not c.user_is_sponsor:
                msg_params = {"start": roadblock[0].strftime("%m/%d/%Y"), "end": roadblock[1].strftime("%m/%d/%Y")}
                c.errors.add(errors.OVERSOLD, field="sr", msg_params=msg_params)
                form.has_errors("sr", errors.OVERSOLD)
                return

        elif targeting == "none":
            sr = None

        # Check inventory
        campaign_id = campaign._id if campaign_id36 else None
        if has_oversold_error(form, campaign_id, start, end, bid, cpm, sr):
            return

        if campaign_id36 is not None:
            campaign = PromoCampaign._byID36(campaign_id36)
            promote.edit_campaign(link, campaign, dates, bid, cpm, sr)
            r = promote.get_renderable_campaigns(link, campaign)
            jquery.update_campaign(
                r.campaign_id36, r.start_date, r.end_date, r.duration, r.bid, r.spent, r.cpm, r.sr, r.status
            )
        else:
            campaign = promote.new_campaign(link, dates, bid, cpm, sr)
            r = promote.get_renderable_campaigns(link, campaign)
            jquery.new_campaign(
                r.campaign_id36, r.start_date, r.end_date, r.duration, r.bid, r.spent, r.cpm, r.sr, r.status
            )
Example #23
0
    def POST_edit_campaign(self, form, jquery, l, campaign_id36,
                          dates, bid, sr, targeting):
        if not l:
            return

        start, end = dates or (None, None)

        if (start and end and not promote.is_accepted(l) and
            not c.user_is_sponsor):
            # if the ad is not approved already, ensure the start date
            # is at least 2 days in the future
            start = start.date()
            end = end.date()
            now = promote.promo_datetime_now()
            future = make_offset_date(now, g.min_promote_future,
                                      business_days=True)
            if start < future.date():
                c.errors.add(errors.BAD_FUTURE_DATE,
                             msg_params=dict(day=g.min_promote_future),
                             field="startdate")


        if (form.has_errors('startdate', errors.BAD_DATE,
                            errors.BAD_FUTURE_DATE) or
            form.has_errors('enddate', errors.BAD_DATE,
                            errors.BAD_FUTURE_DATE, errors.BAD_DATE_RANGE)):
            return

        # Limit the number of PromoCampaigns a Link can have
        # Note that the front end should prevent the user from getting
        # this far
        existing_campaigns = list(PromoCampaign._by_link(l._id))
        if len(existing_campaigns) > g.MAX_CAMPAIGNS_PER_LINK:
            c.errors.add(errors.TOO_MANY_CAMPAIGNS,
                         msg_params={'count': g.MAX_CAMPAIGNS_PER_LINK},
                         field='title')
            form.has_errors('title', errors.TOO_MANY_CAMPAIGNS)
            return

        duration = max((end - start).days, 1)

        if form.has_errors('bid', errors.BAD_BID):
            return

        # minimum bid depends on user privilege and targeting, checked here
        # instead of in the validator b/c current duration is needed
        if c.user_is_sponsor:
            min_daily_bid = 0
        elif targeting == 'one':
            min_daily_bid = g.min_promote_bid * 1.5
        else:
            min_daily_bid = g.min_promote_bid

        if campaign_id36:
            # you cannot edit the bid of a live ad unless it's a freebie
            try:
                campaign = PromoCampaign._byID36(campaign_id36)
                if (bid != campaign.bid and
                    campaign.start_date < datetime.now(g.tz)
                    and not campaign.is_freebie()):
                    c.errors.add(errors.BID_LIVE, field='bid')
                    form.has_errors('bid', errors.BID_LIVE)
                    return
            except NotFound:
                pass

        if bid is None or bid / duration < min_daily_bid:
            c.errors.add(errors.BAD_BID, field='bid',
                         msg_params={'min': min_daily_bid,
                                       'max': g.max_promote_bid})
            form.has_errors('bid', errors.BAD_BID)
            return

        if targeting == 'one':
            if form.has_errors('sr', errors.SUBREDDIT_NOEXIST,
                               errors.SUBREDDIT_NOTALLOWED,
                               errors.SUBREDDIT_REQUIRED):
                # checking to get the error set in the form, but we can't
                # check for rate-limiting if there's no subreddit
                return
            oversold = promote.is_roadblocked(sr.name, start, end)
            if oversold and not c.user_is_sponsor:
                msg_params = {"start": oversold[0].strftime('%m/%d/%Y'),
                              "end": oversold[1].strftime('%m/%d/%Y')}
                c.errors.add(errors.OVERSOLD, field='sr',
                             msg_params=msg_params)
                form.has_errors('sr', errors.OVERSOLD)
                return
        if targeting == 'none':
            sr = None

        if campaign_id36 is not None:
            campaign = PromoCampaign._byID36(campaign_id36)
            promote.edit_campaign(l, campaign, dates, bid, sr)
            r = promote.get_renderable_campaigns(l, campaign)
            jquery.update_campaign(r.campaign_id36, r.start_date, r.end_date,
                                   r.duration, r.bid, r.sr, r.status)
        else:
            campaign = promote.new_campaign(l, dates, bid, sr)
            r = promote.get_renderable_campaigns(l, campaign)
            jquery.new_campaign(r.campaign_id36, r.start_date, r.end_date,
                                r.duration, r.bid, r.sr, r.status)
Example #24
0
    def POST_edit_campaign(self, form, jquery, link, campaign_id36,
                          dates, bid, sr, targeting, priority):
        if not link:
            return

        start, end = dates or (None, None)

        author = Account._byID(link.author_id, data=True)
        cpm = author.cpm_selfserve_pennies

        if (start and end and not promote.is_accepted(link) and
            not c.user_is_sponsor):
            # if the ad is not approved already, ensure the start date
            # is at least 2 days in the future
            start = start.date()
            end = end.date()
            now = promote.promo_datetime_now()
            future = make_offset_date(now, g.min_promote_future,
                                      business_days=True)
            if start < future.date():
                day = promote.promo_datetime_now(offset=g.min_promote_future)
                day = day.strftime("%m/%d/%Y")
                c.errors.add(errors.DATE_TOO_EARLY, msg_params=dict(day=day),
                             field="startdate")

        if (form.has_errors('startdate', errors.BAD_DATE,
                            errors.DATE_TOO_EARLY, errors.DATE_TOO_LATE) or
            form.has_errors('enddate', errors.BAD_DATE, errors.DATE_TOO_EARLY,
                            errors.DATE_TOO_LATE, errors.BAD_DATE_RANGE)):
            return

        # Limit the number of PromoCampaigns a Link can have
        # Note that the front end should prevent the user from getting
        # this far
        existing_campaigns = list(PromoCampaign._by_link(link._id))
        if len(existing_campaigns) > g.MAX_CAMPAIGNS_PER_LINK:
            c.errors.add(errors.TOO_MANY_CAMPAIGNS,
                         msg_params={'count': g.MAX_CAMPAIGNS_PER_LINK},
                         field='title')
            form.has_errors('title', errors.TOO_MANY_CAMPAIGNS)
            return

        campaign = None
        if campaign_id36:
            try:
                campaign = PromoCampaign._byID36(campaign_id36)
            except NotFound:
                pass

        if priority.cpm:
            if form.has_errors('bid', errors.BAD_BID):
                return

            # you cannot edit the bid of a live ad unless it's a freebie
            if (campaign and bid != campaign.bid and
                campaign.start_date < datetime.now(g.tz) and
                not campaign.is_freebie()):
                c.errors.add(errors.BID_LIVE, field='bid')
                form.has_errors('bid', errors.BID_LIVE)
                return

            min_bid = 0 if c.user_is_sponsor else g.min_promote_bid
            if bid is None or bid < min_bid:
                c.errors.add(errors.BAD_BID, field='bid',
                             msg_params={'min': min_bid,
                                         'max': g.max_promote_bid})
                form.has_errors('bid', errors.BAD_BID)
                return
        else:
            bid = 0.   # Set bid to 0 as dummy value

        if targeting == 'one':
            if form.has_errors('sr', errors.SUBREDDIT_NOEXIST,
                               errors.SUBREDDIT_NOTALLOWED,
                               errors.SUBREDDIT_REQUIRED):
                # checking to get the error set in the form, but we can't
                # check for rate-limiting if there's no subreddit
                return

            roadblock = PromotedLinkRoadblock.is_roadblocked(sr, start, end)
            if roadblock and not c.user_is_sponsor:
                msg_params = {"start": roadblock[0].strftime('%m/%d/%Y'),
                              "end": roadblock[1].strftime('%m/%d/%Y')}
                c.errors.add(errors.OVERSOLD, field='sr',
                             msg_params=msg_params)
                form.has_errors('sr', errors.OVERSOLD)
                return

        elif targeting == 'none':
            sr = None

        # Check inventory
        campaign = campaign if campaign_id36 else None
        if (not priority.inventory_override and
            has_oversold_error(form, campaign, start, end, bid, cpm, sr)):
            return

        if campaign:
            promote.edit_campaign(link, campaign, dates, bid, cpm, sr, priority)
            r = promote.get_renderable_campaigns(link, campaign)
            jquery.update_campaign(r.campaign_id36, r.start_date, r.end_date,
                                   r.duration, r.bid, r.spent, r.cpm, r.sr,
                                   r.priority_name, r.inventory_override,
                                   r.status)
        else:
            campaign = promote.new_campaign(link, dates, bid, cpm, sr, priority)
            r = promote.get_renderable_campaigns(link, campaign)
            jquery.new_campaign(r.campaign_id36, r.start_date, r.end_date,
                                r.duration, r.bid, r.spent, r.cpm, r.sr,
                                r.priority_name, r.inventory_override, r.status)
Example #25
0
    def POST_edit_campaign(self, form, jquery, link, campaign_id36, dates, bid,
                           sr, targeting):
        if not link:
            return

        start, end = dates or (None, None)

        author = Account._byID(link.author_id, data=True)
        cpm = author.cpm_selfserve_pennies

        if (start and end and not promote.is_accepted(link)
                and not c.user_is_sponsor):
            # if the ad is not approved already, ensure the start date
            # is at least 2 days in the future
            start = start.date()
            end = end.date()
            now = promote.promo_datetime_now()
            future = make_offset_date(now,
                                      g.min_promote_future,
                                      business_days=True)
            if start < future.date():
                c.errors.add(errors.BAD_FUTURE_DATE,
                             msg_params=dict(day=g.min_promote_future),
                             field="startdate")

        if (form.has_errors('startdate', errors.BAD_DATE,
                            errors.BAD_FUTURE_DATE)
                or form.has_errors('enddate', errors.BAD_DATE,
                                   errors.BAD_FUTURE_DATE,
                                   errors.BAD_DATE_RANGE)):
            return

        # Limit the number of PromoCampaigns a Link can have
        # Note that the front end should prevent the user from getting
        # this far
        existing_campaigns = list(PromoCampaign._by_link(link._id))
        if len(existing_campaigns) > g.MAX_CAMPAIGNS_PER_LINK:
            c.errors.add(errors.TOO_MANY_CAMPAIGNS,
                         msg_params={'count': g.MAX_CAMPAIGNS_PER_LINK},
                         field='title')
            form.has_errors('title', errors.TOO_MANY_CAMPAIGNS)
            return

        if form.has_errors('bid', errors.BAD_BID):
            return

        if campaign_id36:
            # you cannot edit the bid of a live ad unless it's a freebie
            try:
                campaign = PromoCampaign._byID36(campaign_id36)
                if (bid != campaign.bid
                        and campaign.start_date < datetime.now(g.tz)
                        and not campaign.is_freebie()):
                    c.errors.add(errors.BID_LIVE, field='bid')
                    form.has_errors('bid', errors.BID_LIVE)
                    return
            except NotFound:
                pass

        min_bid = 0 if c.user_is_sponsor else g.min_promote_bid
        if bid is None or bid < min_bid:
            c.errors.add(errors.BAD_BID,
                         field='bid',
                         msg_params={
                             'min': min_bid,
                             'max': g.max_promote_bid
                         })
            form.has_errors('bid', errors.BAD_BID)
            return

        if targeting == 'one':
            if form.has_errors('sr', errors.SUBREDDIT_NOEXIST,
                               errors.SUBREDDIT_NOTALLOWED,
                               errors.SUBREDDIT_REQUIRED):
                # checking to get the error set in the form, but we can't
                # check for rate-limiting if there's no subreddit
                return

            roadblock = PromotedLinkRoadblock.is_roadblocked(sr, start, end)
            if roadblock and not c.user_is_sponsor:
                msg_params = {
                    "start": roadblock[0].strftime('%m/%d/%Y'),
                    "end": roadblock[1].strftime('%m/%d/%Y')
                }
                c.errors.add(errors.OVERSOLD,
                             field='sr',
                             msg_params=msg_params)
                form.has_errors('sr', errors.OVERSOLD)
                return

        elif targeting == 'none':
            sr = None

        # Check inventory
        campaign_id = campaign._id if campaign_id36 else None
        if has_oversold_error(form, campaign_id, start, end, bid, cpm, sr):
            return

        if campaign_id36 is not None:
            campaign = PromoCampaign._byID36(campaign_id36)
            promote.edit_campaign(link, campaign, dates, bid, cpm, sr)
            r = promote.get_renderable_campaigns(link, campaign)
            jquery.update_campaign(r.campaign_id36, r.start_date, r.end_date,
                                   r.duration, r.bid, r.spent, r.cpm, r.sr,
                                   r.status)
        else:
            campaign = promote.new_campaign(link, dates, bid, cpm, sr)
            r = promote.get_renderable_campaigns(link, campaign)
            jquery.new_campaign(r.campaign_id36, r.start_date, r.end_date,
                                r.duration, r.bid, r.spent, r.cpm, r.sr,
                                r.status)