3f7b5167fa
Co-authored-by: guke <guke@wonderable.ai> Co-authored-by: 左辰勇 <exinglang@gmail.com> Reviewed-on: #167 Co-authored-by: zuochenyong <zuochenyong@wonderable.ai> Co-committed-by: zuochenyong <zuochenyong@wonderable.ai>
65 lines
2.5 KiB
Python
65 lines
2.5 KiB
Python
"""新手引导视频(领券等候浮层前 N 次替代广告)。
|
|
|
|
路由前缀 `/api/v1/guide-video`(均需 Bearer):
|
|
POST /start 这次浮层放引导视频还是放广告?命中则**当场计次**并下发 play_token
|
|
POST /reward 播完 / 中途关闭都调,按 play_token 幂等发固定金币
|
|
|
|
发币额度以**服务端配置**为准(运营后台可改),客户端只报"播完/关闭",报不了金额,
|
|
所以被破解也刷不到超额金币;次数上限由 guide_video_play 行数(按账号)硬卡。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends
|
|
|
|
from app.api.deps import CurrentUser, DbSession
|
|
from app.core.ratelimit import rate_limit
|
|
from app.repositories import guide_video as crud_guide
|
|
from app.schemas.guide_video import (
|
|
GuideVideoRewardIn,
|
|
GuideVideoRewardOut,
|
|
GuideVideoStartIn,
|
|
GuideVideoStartOut,
|
|
)
|
|
|
|
logger = logging.getLogger("shagua.guide_video")
|
|
|
|
router = APIRouter(prefix="/api/v1/guide-video", tags=["guide-video"])
|
|
|
|
|
|
@router.post(
|
|
"/start",
|
|
response_model=GuideVideoStartOut,
|
|
summary="领券浮层是否放新手引导视频(命中即计次)",
|
|
dependencies=[Depends(rate_limit(60, 60, "guide-video-start"))],
|
|
)
|
|
def start(payload: GuideVideoStartIn, user: CurrentUser, db: DbSession) -> GuideVideoStartOut:
|
|
"""开播即计数:返回 should_play=True 时服务端已写下这一次,客户端必须真的播。
|
|
|
|
没配视频 / 开关关 / 次数用完 → should_play=False,客户端照旧走广告链路(行为不变)。
|
|
"""
|
|
result = crud_guide.start_play(db, user.id, scene=payload.scene or "coupon")
|
|
logger.info(
|
|
"guide video start user_id=%d scene=%s should_play=%s seq=%d remaining=%d",
|
|
user.id, payload.scene, result["should_play"], result["seq"], result["remaining"],
|
|
)
|
|
return GuideVideoStartOut(**result)
|
|
|
|
|
|
@router.post(
|
|
"/reward",
|
|
response_model=GuideVideoRewardOut,
|
|
summary="引导视频发金币(播完/中途关闭都发,play_token 幂等)",
|
|
dependencies=[Depends(rate_limit(60, 60, "guide-video-reward"))],
|
|
)
|
|
def reward(payload: GuideVideoRewardIn, user: CurrentUser, db: DbSession) -> GuideVideoRewardOut:
|
|
result = crud_guide.grant_play(
|
|
db, user.id, play_token=payload.play_token, completed=payload.completed
|
|
)
|
|
logger.info(
|
|
"guide video reward user_id=%d token=%s completed=%s granted=%s coin=%d",
|
|
user.id, payload.play_token[:12], payload.completed, result["granted"], result["coin"],
|
|
)
|
|
return GuideVideoRewardOut(**result)
|