import json import random import time import jwt from fastapi import Request, HTTPException, Security from fastapi.responses import Response from fastapi.security import HTTPAuthorizationCredentials import utils.globals as globals from app import app, security_scheme from chatgpt.authorization import verify_token from chatgpt.fp import get_fp from gateway.reverseProxy import get_real_req_token from utils.Client import Client from utils.Logger import logger from utils.configs import proxy_url_list, chatgpt_base_url_list, authorization_list base_headers = { 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br, zstd', 'accept-language': 'en-US,en;q=0.9', 'content-type': 'application/json', 'oai-language': 'en-US', 'priority': 'u=1, i', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', } def verify_authorization(bearer_token): if not bearer_token: raise HTTPException(status_code=401, detail="Authorization header is missing") if bearer_token not in authorization_list: raise HTTPException(status_code=401, detail="Invalid authorization") @app.get("/seedtoken") async def get_seedtoken(request: Request, credentials: HTTPAuthorizationCredentials = Security(security_scheme)): verify_authorization(credentials.credentials) try: params = request.query_params seed = params.get("seed") if seed: if seed not in globals.seed_map: raise HTTPException(status_code=404, detail=f"Seed '{seed}' not found") return { "status": "success", "data": { "seed": seed, "token": globals.seed_map[seed]["token"] } } token_map = { seed: data["token"] for seed, data in globals.seed_map.items() } return {"status": "success", "data": token_map} except Exception as e: raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}") @app.post("/seedtoken") async def set_seedtoken(request: Request, credentials: HTTPAuthorizationCredentials = Security(security_scheme)): verify_authorization(credentials.credentials) data = await request.json() seed = data.get("seed") token = data.get("token") if seed not in globals.seed_map: globals.seed_map[seed] = { "token": token, "conversations": [] } else: globals.seed_map[seed]["token"] = token with open(globals.SEED_MAP_FILE, "w", encoding="utf-8") as f: json.dump(globals.seed_map, f, indent=4) return {"status": "success", "message": "Token updated successfully"} @app.delete("/seedtoken") async def delete_seedtoken(request: Request, credentials: HTTPAuthorizationCredentials = Security(security_scheme)): verify_authorization(credentials.credentials) try: data = await request.json() seed = data.get("seed") if seed == "clear": globals.seed_map.clear() with open(globals.SEED_MAP_FILE, "w", encoding="utf-8") as f: json.dump(globals.seed_map, f, indent=4) return {"status": "success", "message": "All seeds deleted successfully"} if not seed: raise HTTPException(status_code=400, detail="Missing required field: seed") if seed not in globals.seed_map: raise HTTPException(status_code=404, detail=f"Seed '{seed}' not found") del globals.seed_map[seed] with open(globals.SEED_MAP_FILE, "w", encoding="utf-8") as f: json.dump(globals.seed_map, f, indent=4) return { "status": "success", "message": f"Seed '{seed}' deleted successfully" } except json.JSONDecodeError: raise HTTPException(status_code=400, detail="Invalid JSON data") except Exception as e: raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}") async def chatgpt_account_check(access_token): auth_info = {} client = Client(proxy=random.choice(proxy_url_list) if proxy_url_list else None) try: host_url = random.choice(chatgpt_base_url_list) if chatgpt_base_url_list else "https://chatgpt.com" req_token = await get_real_req_token(access_token) access_token = await verify_token(req_token) fp = get_fp(req_token).copy() proxy_url = fp.pop("proxy_url", None) impersonate = fp.pop("impersonate", "safari15_3") headers = base_headers.copy() headers.update(fp) headers.update({"authorization": f"Bearer {access_token}"}) client = Client(proxy=proxy_url, impersonate=impersonate) r = await client.get(f"{host_url}/backend-api/models?history_and_training_disabled=false", headers=headers, timeout=10) if r.status_code != 200: raise HTTPException(status_code=r.status_code, detail=r.text) models = r.json() r = await client.get(f"{host_url}/backend-api/accounts/check/v4-2023-04-27", headers=headers, timeout=10) if r.status_code != 200: raise HTTPException(status_code=r.status_code, detail=r.text) accounts_info = r.json() auth_info.update({"models": models["models"]}) auth_info.update({"accounts_info": accounts_info}) account_ordering = accounts_info.get("account_ordering", []) is_deactivated = True plan_type = None team_ids = [] for account in account_ordering: this_is_deactivated = accounts_info['accounts'].get(account, {}).get("account", {}).get("is_deactivated", False) this_plan_type = accounts_info['accounts'].get(account, {}).get("account", {}).get("plan_type", "free") if not this_is_deactivated: is_deactivated = False if "team" in this_plan_type and not this_is_deactivated: plan_type = this_plan_type team_ids.append(account) elif plan_type is None: plan_type = this_plan_type auth_info.update({"accountCheckInfo": { "is_deactivated": is_deactivated, "plan_type": plan_type, "team_ids": team_ids }}) return auth_info except Exception as e: logger.error(f"chatgpt_account_check: {e}") return {} finally: await client.close() async def chatgpt_refresh(refresh_token): client = Client(proxy=random.choice(proxy_url_list) if proxy_url_list else None) try: data = { "client_id": "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh", "grant_type": "refresh_token", "redirect_uri": "com.openai.chat://auth0.openai.com/ios/com.openai.chat/callback", "refresh_token": refresh_token } r = await client.post("https://auth0.openai.com/oauth/token", json=data, timeout=10) if r.status_code != 200: raise HTTPException(status_code=r.status_code, detail=r.text) res = r.json() auth_info = {} auth_info.update(res) auth_info.update({"refresh_token": refresh_token}) auth_info.update({"accessToken": res.get("access_token", "")}) return auth_info except Exception as e: logger.error(f"chatgpt_refresh: {e}") return {} finally: await client.close() @app.post("/auth/refresh") async def refresh(request: Request): auth_info = {} form_data = await request.form() auth_info.update(form_data) access_token = auth_info.get("access_token", auth_info.get("accessToken", "")) refresh_token = auth_info.get("refresh_token", "") if not refresh_token and not access_token: raise HTTPException(status_code=401, detail="refresh_token or access_token is required") need_refresh = True if access_token: try: access_token_info = jwt.decode(access_token, options={"verify_signature": False}) exp = access_token_info.get("exp", 0) if exp > int(time.time()) + 60 * 60 * 24 * 5: need_refresh = False except Exception as e: logger.error(f"access_token: {e}") if refresh_token and need_refresh: chatgpt_refresh_info = await chatgpt_refresh(refresh_token) if chatgpt_refresh_info: auth_info.update(chatgpt_refresh_info) access_token = auth_info.get("accessToken", "") account_check_info = await chatgpt_account_check(access_token) if account_check_info: auth_info.update(account_check_info) auth_info.update({"accessToken": access_token}) return Response(content=json.dumps(auth_info), media_type="application/json") elif access_token: account_check_info = await chatgpt_account_check(access_token) if account_check_info: auth_info.update(account_check_info) auth_info.update({"accessToken": access_token}) return Response(content=json.dumps(auth_info), media_type="application/json") raise HTTPException(status_code=401, detail="Unauthorized")