06/15 Phase 4 + 5 codes
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""Ads blueprint: click tracking redirect, sponsor directory.
|
||||
Ad creative upload lives in the admin blueprint (Phase 6).
|
||||
"""
|
||||
from flask import (Blueprint, redirect, abort, render_template,
|
||||
request, current_app)
|
||||
from flask_login import current_user
|
||||
from flask_babel import get_locale
|
||||
|
||||
from app.extensions import db
|
||||
from app.models.ads import Ad
|
||||
from app.services.ads import (get_ad, record_impression, record_click,
|
||||
active_sponsors)
|
||||
|
||||
ads_bp = Blueprint("ads", __name__)
|
||||
|
||||
|
||||
# ── Click tracking redirect ────────────────────────────────────────────────
|
||||
|
||||
@ads_bp.route("/ads/<int:ad_id>/click")
|
||||
def click(ad_id):
|
||||
ad = db.session.get(Ad, ad_id)
|
||||
if ad is None or not ad.is_running:
|
||||
abort(404)
|
||||
try:
|
||||
record_click(ad_id)
|
||||
except Exception as e:
|
||||
current_app.logger.error("Click record error: %s", e)
|
||||
return redirect(ad.target_url)
|
||||
|
||||
|
||||
# ── Sponsor directory ──────────────────────────────────────────────────────
|
||||
|
||||
@ads_bp.route("/sponsors")
|
||||
def sponsor_directory():
|
||||
sponsors = active_sponsors(tier="directory")
|
||||
return render_template("sponsors/directory.html", sponsors=sponsors)
|
||||
|
||||
|
||||
# ── Context processor: inject ads into every template ─────────────────────
|
||||
|
||||
def inject_ads():
|
||||
"""Called by the app factory context processor.
|
||||
Returns ad slots for use in templates.
|
||||
Ads suppressed for subscribers (ad_free plan limit).
|
||||
"""
|
||||
show_ads = True
|
||||
if current_user.is_authenticated:
|
||||
plan = current_user.tier
|
||||
if plan and plan.limit("ad_free"):
|
||||
show_ads = False
|
||||
|
||||
if not show_ads:
|
||||
return {"ads": {}, "show_ads": False}
|
||||
|
||||
lang = str(get_locale()) if get_locale() else None
|
||||
state = request.args.get("state") or None
|
||||
|
||||
ads = {}
|
||||
for slot in Ad.SLOTS:
|
||||
ad = get_ad(slot, lang=lang, state=state)
|
||||
if ad:
|
||||
ads[slot] = ad
|
||||
# record impression (fire-and-forget; errors suppressed)
|
||||
try:
|
||||
record_impression(ad.id)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return {"ads": ads, "show_ads": True}
|
||||
Reference in New Issue
Block a user