|
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") |
|
|
|
|
|
|