def make_adzerk_promotions(offset=0): # make sure is_charged_transaction and is_accepted are the only criteria # for a campaign going live! for link, campaign, weight in promote.accepted_campaigns(offset=offset): if (authorize.is_charged_transaction(campaign.trans_id, campaign._id) and promote.is_accepted(link)): update_adzerk(link, campaign)
def make_adzerk_promotions(offset=0): # campaign goes live if is_charged_transaction and is_accepted for link, campaign, weight in promote.accepted_campaigns(offset=offset): if (authorize.is_charged_transaction(campaign.trans_id, campaign._id) and promote.is_accepted(link)): if is_overdelivered(campaign): deactivate_campaign(link, campaign) else: update_adzerk(link, campaign)
def upsert_campaign(link, campaign): queue.push("upsert_campaign", { "link": link._fullname, "campaign": campaign._fullname, }) action = ("activate" if promote.is_accepted(link) and not link._deleted else "deactivate") queue.push(action, { "campaigns": campaign._fullname })
def upsert_promotion(link): queue.push("upsert_promotion", { "link": link._fullname, }) action = ("activate" if promote.is_accepted(link) and not link._deleted else "deactivate") campaigns = list(PromoCampaign._by_link(link._id)) if not campaigns: return queue.push(action, { "campaigns": ",".join([campaign._fullname for campaign in campaigns]) })
def get_scheduled(date, sr_name=""): campaign_ids = PromotionWeights.get_campaign_ids(date, sr_names=[sr_name]) campaigns = PromoCampaign._byID(campaign_ids, return_dict=False, data=True) links = Link._by_fullname({camp.link_id for camp in campaigns}, return_dict=False, data=True) links = {l._id: l for l in links} kept = [] for camp in campaigns: if camp.trans_id == 0: continue link = links[camp.link_id] if link._spam or not promote.is_accepted(link): continue kept.append(camp._id) return [(camp._fullname, camp.link_id, camp.bid) for camp in kept]
def get_scheduled(date, sr_name=''): campaign_ids = PromotionWeights.get_campaign_ids(date, sr_names=[sr_name]) campaigns = PromoCampaign._byID(campaign_ids, return_dict=False, data=True) links = Link._by_fullname({camp.link_id for camp in campaigns}, return_dict=False, data=True) links = {l._id: l for l in links} kept = [] for camp in campaigns: if camp.trans_id == 0: continue link = links[camp.link_id] if link._spam or not promote.is_accepted(link): continue kept.append(camp._id) return [(camp._fullname, camp.link_id, camp.bid) for camp in kept]
def get_scheduled(date, sr_name=""): all_promotions = PromotionWeights.get_campaigns(date) fp_promotions = [p for p in all_promotions if p.sr_name == sr_name] campaigns = PromoCampaign._byID([i.promo_idx for i in fp_promotions], return_dict=False, data=True) links = Link._by_fullname([i.thing_name for i in fp_promotions], return_dict=False, data=True) links = {l._id: l for l in links} kept = [] for camp in campaigns: if camp.trans_id == 0: continue link = links[camp.link_id] if link._spam or not promote.is_accepted(link): continue kept.append(camp._id) return [ ("%s_%s" % (PC_PREFIX, to36(p.promo_idx)), p.thing_name, p.bid) for p in fp_promotions if p.promo_idx in kept ]
def update_campaign(link, az_advertiser=None): """Add/update a reddit link as an Adzerk Campaign""" if getattr(link, 'external_campaign_id', None) is not None: az_campaign = adzerk_api.Campaign.get(link.external_campaign_id) else: az_campaign = None d = { 'SalespersonId': g.az_selfserve_salesperson_id, 'IsDeleted': False, # deleting an adzerk object will make it # unretrievable, so just set it inactive 'IsActive': promote.is_accepted(link) and not link._deleted, 'Price': 0, } if az_advertiser: d["AdvertiserId"] = az_advertiser.Id if az_campaign: changed = update_changed(az_campaign, **d) change_strs = make_change_strings(changed) if change_strs: log_text = 'updated %s: ' % az_campaign + ', '.join(change_strs) else: log_text = None else: d.update({ 'Name': link._fullname, 'Flights': [], 'StartDate': date_to_adzerk(datetime.datetime.now(g.tz)), }) az_campaign = adzerk_api.Campaign.create(**d) link.external_campaign_id = az_campaign.Id link._commit() log_text = 'created %s' % az_campaign if log_text: PromotionLog.add(link, log_text) g.log.info(log_text) return az_campaign
def get_scheduled(date, sr_name=''): all_promotions = PromotionWeights.get_campaigns(date) fp_promotions = [p for p in all_promotions if p.sr_name == sr_name] campaigns = PromoCampaign._byID([i.promo_idx for i in fp_promotions], return_dict=False, data=True) links = Link._by_fullname([i.thing_name for i in fp_promotions], return_dict=False, data=True) links = {l._id: l for l in links} kept = [] for camp in campaigns: if camp.trans_id == 0: continue link = links[camp.link_id] if link._spam or not promote.is_accepted(link): continue kept.append(camp._id) return [('%s_%s' % (PC_PREFIX, to36(p.promo_idx)), p.thing_name, p.bid) for p in fp_promotions if p.promo_idx in kept]
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 make_adzerk_promotions(offset=0): # campaign goes live if is_charged_transaction and is_accepted for link, campaign, weight in promote.accepted_campaigns(offset=offset): if (authorize.is_charged_transaction(campaign.trans_id, campaign._id) and promote.is_accepted(link)): update_adzerk(link, campaign)
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 update_campaign(link, az_advertiser=None, triggered_by=None): """Add/update a reddit link as an Adzerk Campaign""" if getattr(link, 'external_campaign_id', None) is not None: az_campaign = adzerk_api.Campaign.get( link.external_campaign_id, exclude_flights=True, ) else: az_campaign = None d = { 'SalespersonId': g.az_selfserve_salesperson_id, 'IsDeleted': False, # deleting an adzerk object will make it # unretrievable, so just set it inactive 'IsActive': ((promote.is_accepted(link) or promote.is_external(link)) and not link._deleted), 'Price': 0, } if az_advertiser: d["AdvertiserId"] = az_advertiser.Id request_error = None if az_campaign: try: changed = update_changed(az_campaign, **d) except adzerk_api.AdzerkError as e: request_error = e finally: g.ad_events.adzerk_api_request( request_type="update_campaign", thing=link, request_body=d, triggered_by=triggered_by, request_error=request_error, ) if request_error: raise request_error change_strs = make_change_strings(changed) if change_strs: log_text = 'updated %s: ' % az_campaign + ', '.join(change_strs) else: log_text = None else: d.update({ 'Name': link._fullname, 'Flights': [], 'StartDate': date_to_adzerk(datetime.datetime.now(g.tz)), }) try: az_campaign = adzerk_api.Campaign.create(**d) except adzerk_api.AdzerkError as e: request_error = e finally: g.ad_events.adzerk_api_request( request_type="create_campaign", thing=link, request_body=d, triggered_by=triggered_by, request_error=request_error, ) if request_error: raise request_error link.external_campaign_id = az_campaign.Id link._commit() log_text = 'created %s' % az_campaign if log_text: PromotionLog.add(link, log_text) g.log.info(log_text) return az_campaign
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): 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 )