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()
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()
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()
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
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
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
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
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]
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()
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)
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)
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)
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()
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})
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})
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."))
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 )
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)
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)
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)