diff --git a/src/codebuddy_proxy/__main__.py b/src/codebuddy_proxy/__main__.py index 897356b..ee742b5 100755 --- a/src/codebuddy_proxy/__main__.py +++ b/src/codebuddy_proxy/__main__.py @@ -815,6 +815,61 @@ async def health(): } +# ============================================================================ +# 端点:/v1/checkin-status 与 /v1/checkin(每日签到透传) +# ============================================================================ + +async def _billing_post(path: str) -> dict[str, Any]: + """用本地已登录会话调用官方 billing 端点并返回原始 JSON。 + + 自动处理 401:先走 ensure_authenticated 刷新 token 再重试一次。 + """ + state = get_state() + url = state.client.endpoint.rstrip("/") + path + async with httpx.AsyncClient(timeout=httpx.Timeout(10.0)) as client: + resp = await client.post(url, json={}, headers=state.client.auth_headers()) + if resp.status_code == 401: + # token 过期:触发一次刷新后重试 + try: + await asyncio.to_thread(state.client.ensure_authenticated, False) + except Exception: + pass + resp = await client.post(url, json={}, headers=state.client.auth_headers()) + try: + return resp.json() + except Exception: + return {"code": resp.status_code, "msg": f"non-JSON response (HTTP {resp.status_code})"} + + +@app.get("/v1/checkin-status") +async def checkin_status(): + """查询每日签到活动状态(透传官方 /v2/billing/meter/checkin-status)。""" + state = get_state() + try: + state.ensure_auth() + except Exception as e: + raise HTTPException(status_code=503, detail={"error": {"message": f"not authenticated: {e}", "type": "auth_error"}}) + result = await _billing_post("/v2/billing/meter/checkin-status") + return {"status": "ok", "upstream": result} + + +@app.post("/v1/checkin") +async def checkin(): + """执行每日签到(透传官方 /v2/billing/meter/daily-checkin)。 + + 业务结果原样返回:code=0 且 data 非空为领取成功;已签到/活动结束等 + 业务拒绝通过上游 data.status / msg 区分,这里不做二次解释。 + """ + state = get_state() + try: + state.ensure_auth() + except Exception as e: + raise HTTPException(status_code=503, detail={"error": {"message": f"not authenticated: {e}", "type": "auth_error"}}) + result = await _billing_post("/v2/billing/meter/daily-checkin") + diagnostic("checkin_claim_result", code=result.get("code"), msg=result.get("msg")) + return {"status": "ok", "upstream": result} + + # ============================================================================ # 端点:/v1/models # ============================================================================