同步任务账号订阅状态,并回写到账号管理
(task_id: int, request: SyncBindCardTaskRequest)
| 3000 | |
| 3001 | @router.post("/bind-card/tasks/{task_id}/sync-subscription") |
| 3002 | def sync_bind_card_task_subscription(task_id: int, request: SyncBindCardTaskRequest): |
| 3003 | """同步任务账号订阅状态,并回写到账号管理""" |
| 3004 | with get_db() as db: |
| 3005 | task = db.query(BindCardTask).options(joinedload(BindCardTask.account)).filter(BindCardTask.id == task_id).first() |
| 3006 | if not task: |
| 3007 | raise HTTPException(status_code=404, detail="绑卡任务不存在") |
| 3008 | account = task.account |
| 3009 | if not account: |
| 3010 | raise HTTPException(status_code=404, detail="任务关联账号不存在") |
| 3011 | |
| 3012 | proxy = _resolve_runtime_proxy(request.proxy, account) |
| 3013 | now = utcnow_naive() |
| 3014 | try: |
| 3015 | detail, refreshed = _check_subscription_detail_with_retry( |
| 3016 | db=db, |
| 3017 | account=account, |
| 3018 | proxy=proxy, |
| 3019 | allow_token_refresh=True, |
| 3020 | ) |
| 3021 | status = str(detail.get("status") or "free").lower() |
| 3022 | source = str(detail.get("source") or "unknown") |
| 3023 | confidence = str(detail.get("confidence") or "low") |
| 3024 | logger.info( |
| 3025 | "绑卡任务同步订阅: task_id=%s account_id=%s status=%s source=%s confidence=%s token_refreshed=%s", |
| 3026 | task.id, account.id, status, source, confidence, refreshed |
| 3027 | ) |
| 3028 | except Exception as exc: |
| 3029 | task.status = "failed" |
| 3030 | task.last_error = str(exc) |
| 3031 | task.last_checked_at = now |
| 3032 | db.commit() |
| 3033 | logger.warning("绑卡任务同步订阅失败: task_id=%s error=%s", task.id, exc) |
| 3034 | raise HTTPException(status_code=500, detail=f"订阅检测失败: {exc}") |
| 3035 | |
| 3036 | # 仅在高置信度 free 时清空;低置信度 free 不覆盖已有订阅 |
| 3037 | if status in ("plus", "team"): |
| 3038 | account.subscription_type = status |
| 3039 | account.subscription_at = now |
| 3040 | elif status == "free": |
| 3041 | if str(detail.get("confidence") or "").lower() == "high": |
| 3042 | account.subscription_type = None |
| 3043 | account.subscription_at = None |
| 3044 | |
| 3045 | task.last_checked_at = now |
| 3046 | if status in ("plus", "team"): |
| 3047 | task.status = "completed" |
| 3048 | task.completed_at = now |
| 3049 | task.last_error = None |
| 3050 | else: |
| 3051 | task.completed_at = None |
| 3052 | note = str(detail.get("note") or "").strip() |
| 3053 | confidence_text = str(detail.get("confidence") or "unknown") |
| 3054 | confidence_lower = confidence_text.lower() |
| 3055 | source_text = str(detail.get("source") or "unknown") |
| 3056 | task_status_now = str(task.status or "") |
| 3057 | has_checkout_context = bool(task.checkout_session_id or task.checkout_url) |
| 3058 | should_keep_paid_pending = ( |
| 3059 | task_status_now == "paid_pending_sync" |
nothing calls this directly
no test coverage detected