比价结果状态
This commit is contained in:
@@ -95,11 +95,14 @@ def invalidate_store_mapping(
|
||||
x_internal_secret: Annotated[str | None, Header()] = None,
|
||||
) -> StoreMappingInvalidateOut:
|
||||
_check_secret(x_internal_secret)
|
||||
if payload.platform != "taobao":
|
||||
# 当前只接淘宝; 其它平台先 no-op(affected=0), 不报错 — 向后兼容 pricebot 将来扩展。
|
||||
if payload.platform == "taobao":
|
||||
affected = repo.mark_taobao_deeplink_invalid(db, payload.shop_id)
|
||||
elif payload.platform == "jd":
|
||||
affected = repo.mark_jd_deeplink_invalid(db, payload.shop_id)
|
||||
else:
|
||||
# 当前只接淘宝/京东; 其它平台先 no-op(affected=0), 不报错 — 向后兼容 pricebot 将来扩展。
|
||||
logger.info("store_mapping invalidate 跳过: platform=%s 暂不支持", payload.platform)
|
||||
return StoreMappingInvalidateOut(ok=True, affected=0)
|
||||
affected = repo.mark_taobao_deeplink_invalid(db, payload.shop_id)
|
||||
logger.info(
|
||||
"store_mapping invalidate platform=%s shop_id=%s → 标记失效 %d 行",
|
||||
payload.platform, payload.shop_id, affected,
|
||||
|
||||
+35
-1
@@ -32,6 +32,8 @@ from app.schemas.ad import (
|
||||
FeedRewardIn,
|
||||
FeedRewardOut,
|
||||
PangleCallbackOut,
|
||||
RewardNoShowIn,
|
||||
RewardNoShowOut,
|
||||
TestGrantIn,
|
||||
TestGrantOut,
|
||||
WatchReportIn,
|
||||
@@ -242,10 +244,12 @@ def ecpm_report(payload: EcpmReportIn, user: CurrentUser, db: DbSession) -> Ecpm
|
||||
ad_type=payload.ad_type, ecpm_raw=payload.ecpm,
|
||||
ad_session_id=payload.ad_session_id,
|
||||
adn=payload.adn, slot_id=payload.slot_id,
|
||||
app_env=payload.app_env, our_code_id=payload.our_code_id,
|
||||
)
|
||||
logger.info(
|
||||
"ad ecpm report user_id=%d type=%s session=%s ecpm=%s adn=%s slot=%s",
|
||||
"ad ecpm report user_id=%d type=%s session=%s ecpm=%s adn=%s slot=%s app=%s code=%s",
|
||||
user.id, payload.ad_type, payload.ad_session_id, payload.ecpm, payload.adn, payload.slot_id,
|
||||
payload.app_env, payload.our_code_id,
|
||||
)
|
||||
return EcpmReportOut(ok=True)
|
||||
|
||||
@@ -359,6 +363,9 @@ def feed_reward(payload: FeedRewardIn, user: CurrentUser, db: DbSession) -> Feed
|
||||
ad_session_id=payload.ad_session_id,
|
||||
adn=payload.adn,
|
||||
slot_id=payload.slot_id,
|
||||
app_env=payload.app_env,
|
||||
our_code_id=payload.our_code_id,
|
||||
aborted=payload.aborted,
|
||||
)
|
||||
logger.info(
|
||||
"feed ad reward user_id=%d event=%s status=%s units=%d coin=%d",
|
||||
@@ -371,3 +378,30 @@ def feed_reward(payload: FeedRewardIn, user: CurrentUser, db: DbSession) -> Feed
|
||||
unit_count=rec.unit_count,
|
||||
daily_limit=rewards.get_ad_daily_limit(db),
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/reward-noshow",
|
||||
response_model=RewardNoShowOut,
|
||||
summary="激励视频提前关闭/未发奖留痕",
|
||||
dependencies=[Depends(rate_limit(120, 60, "ad-reward-noshow"))],
|
||||
)
|
||||
def reward_noshow(payload: RewardNoShowIn, user: CurrentUser, db: DbSession) -> RewardNoShowOut:
|
||||
"""激励视频展示了但用户提前关/跳过、未触发 S2S 发奖时,客户端 best-effort 上报一条留痕,
|
||||
让广告收益报表能呈现「有展示、没发金币」的原因。不发金币;同一 session 已发奖则跳过。
|
||||
"""
|
||||
rec = crud_ad.record_reward_noshow(
|
||||
db,
|
||||
user.id,
|
||||
ad_session_id=payload.ad_session_id,
|
||||
ecpm=payload.ecpm,
|
||||
adn=payload.adn,
|
||||
slot_id=payload.slot_id,
|
||||
app_env=payload.app_env,
|
||||
our_code_id=payload.our_code_id,
|
||||
)
|
||||
logger.info(
|
||||
"ad reward noshow user_id=%d session=%s watched=%ds -> status=%s",
|
||||
user.id, payload.ad_session_id, payload.watched_seconds, rec.status,
|
||||
)
|
||||
return RewardNoShowOut(ok=True, status=rec.status)
|
||||
|
||||
+14
-1
@@ -18,7 +18,7 @@ import httpx
|
||||
from fastapi import APIRouter, HTTPException, Request, status
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
|
||||
from app.api.deps import DbSession
|
||||
from app.api.deps import CurrentUser, DbSession
|
||||
from app.core.config import settings
|
||||
from app.core.pricebot_router import pick_pricebot
|
||||
from app.db.session import SessionLocal
|
||||
@@ -28,6 +28,7 @@ from app.schemas.coupon_state import (
|
||||
CouponPromptDismissIn,
|
||||
CouponPromptShouldShowOut,
|
||||
CouponPromptShownIn,
|
||||
CouponStatsOut,
|
||||
)
|
||||
|
||||
logger = logging.getLogger("shagua.coupon")
|
||||
@@ -268,3 +269,15 @@ def coupon_completed_today_reset(
|
||||
与 /prompt/reset 配套:开发设置「重置今日领券弹窗状态」一键把今日状态全清。MVP 不鉴权。"""
|
||||
coupon_repo.reset_today_completion(db, payload.device_id)
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@router.get(
|
||||
"/stats",
|
||||
response_model=CouponStatsOut,
|
||||
summary="累计领券数(「我的」页战绩卡「领取优惠券 X 张」)",
|
||||
)
|
||||
def coupon_stats(user: CurrentUser, db: DbSession) -> CouponStatsOut:
|
||||
"""该登录用户累计领到的券数(SUM(claimed_count),口径见 coupon_repo.sum_claimed_count)。
|
||||
**鉴权(CurrentUser)**——区别于同文件不鉴权的 /step 透传与 /prompt 频控(那些按 device_id):
|
||||
个人战绩按 user_id 聚合,必须有登录态。"""
|
||||
return CouponStatsOut(coupon_count=coupon_repo.sum_claimed_count(db, user.id))
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
"""CPS 群发短链跳转:用户点 /c/{code} → 记一条点击 → 302 跳美团。
|
||||
|
||||
公网、无鉴权(群里任何人点都要能跳)。记点击失败绝不影响跳转(用户体验优先)。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from fastapi.responses import RedirectResponse
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.db.session import get_db
|
||||
from app.repositories import cps_link as cps_link_repo
|
||||
|
||||
router = APIRouter(tags=["cps-redirect"])
|
||||
|
||||
# code 不存在/失效时的兜底落地(避免用户看到报错)
|
||||
_FALLBACK_URL = "https://www.meituan.com/"
|
||||
|
||||
|
||||
def _client_ip(request: Request) -> str | None:
|
||||
xff = request.headers.get("x-forwarded-for")
|
||||
if xff:
|
||||
return xff.split(",")[0].strip()
|
||||
return request.client.host if request.client else None
|
||||
|
||||
|
||||
@router.get("/c/{code}", summary="群发短链跳转(记点击 + 302)")
|
||||
def cps_redirect(code: str, request: Request, db: Session = Depends(get_db)):
|
||||
link = cps_link_repo.get_by_code(db, code)
|
||||
if link is None:
|
||||
return RedirectResponse(_FALLBACK_URL, status_code=302)
|
||||
try:
|
||||
cps_link_repo.record_click(
|
||||
db, link=link, ip=_client_ip(request),
|
||||
ua=request.headers.get("user-agent"),
|
||||
)
|
||||
except Exception:
|
||||
pass # 记点击失败不阻断跳转
|
||||
return RedirectResponse(link.target_url, status_code=302)
|
||||
@@ -21,7 +21,7 @@ logger = logging.getLogger("shagua.feedback")
|
||||
router = APIRouter(prefix="/api/v1/feedback", tags=["feedback"])
|
||||
|
||||
_MAX_IMAGES = 6
|
||||
_CONTENT_MAX = 2000
|
||||
_CONTENT_MAX = 200
|
||||
_CONTACT_MAX = 128
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user