Spaces:
Paused
Paused
Refactor config, add multi-SSO support and admin panel
Browse files- Move configuration loading to `src/config.py` and utilize environment variables.
- Add support for multiple SSO tokens loaded from the `SSO` environment variable.
- Implement logic to cycle through available SSO tokens for API requests.
- Introduce a basic password-protected admin panel (`/admin`) for managing SSO tokens.
- Update README with detailed configuration instructions using `.env`.
- Change default application port to 7860.
- Add `.env` to `.gitignore`.
- Include support for various environment variables (proxy, CF cookie, image keys, etc.).
- Add basic retry mechanism for API calls.
- .env.example +40 -0
- .gitignore +4 -1
- README.md +31 -9
- app.py +1 -64
- src/config.py +73 -0
.env.example
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# .env 示例文件
|
| 2 |
+
|
| 3 |
+
# 是否使用临时对话模式 (默认为 true)
|
| 4 |
+
# IS_TEMP_CONVERSATION=true
|
| 5 |
+
|
| 6 |
+
# 是否使用自定义 SSO 令牌模式 (默认为 false)
|
| 7 |
+
# IS_CUSTOM_SSO=false
|
| 8 |
+
|
| 9 |
+
# Grok API 的基础 URL (默认为 https://grok.com)
|
| 10 |
+
# API_BASE_URL=https://grok.com
|
| 11 |
+
|
| 12 |
+
# 用于访问本程序 API 的密钥 (默认为 sk-123456)
|
| 13 |
+
# API_KEY=your_api_key_here
|
| 14 |
+
|
| 15 |
+
# PicGo 图床的 API 密钥 (可选)
|
| 16 |
+
# PICGO_KEY=
|
| 17 |
+
|
| 18 |
+
# Tumy 图床的 API 密钥 (可选)
|
| 19 |
+
# TUMY_KEY=
|
| 20 |
+
|
| 21 |
+
# HTTP/HTTPS 代理地址 (可选)
|
| 22 |
+
# PROXY=
|
| 23 |
+
|
| 24 |
+
# 是否开启管理页面 (可选)
|
| 25 |
+
# MANAGER_SWITCH= # 是否开启管理页面 (可选,默认为关闭)
|
| 26 |
+
|
| 27 |
+
# 管理页面的访问密码 (可选,开启管理页面时需要设置)
|
| 28 |
+
# ADMINPASSWORD=
|
| 29 |
+
|
| 30 |
+
# Cloudflare 的 cf_clearance cookie 值 (可选)
|
| 31 |
+
# CF_CLEARANCE=
|
| 32 |
+
|
| 33 |
+
# 应用程序监听的端口 (默认为 7860)
|
| 34 |
+
# PORT=7860
|
| 35 |
+
|
| 36 |
+
# Flask 应用程序的 Secret Key,用于会话管理 (如果未设置,将自动生成)
|
| 37 |
+
# FLASK_SECRET_KEY=
|
| 38 |
+
|
| 39 |
+
# Grok SSO 令牌,多个令牌使用逗号分隔
|
| 40 |
+
# SSO=sso_token_1,sso_token_2
|
.gitignore
CHANGED
|
@@ -16,4 +16,7 @@ venv/
|
|
| 16 |
*.swp
|
| 17 |
|
| 18 |
# Hugging Face Space nested directory (if it exists locally)
|
| 19 |
-
g2api-test/
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
*.swp
|
| 17 |
|
| 18 |
# Hugging Face Space nested directory (if it exists locally)
|
| 19 |
+
g2api-test/
|
| 20 |
+
|
| 21 |
+
# Environment variables
|
| 22 |
+
.env
|
README.md
CHANGED
|
@@ -12,7 +12,7 @@ pinned: false
|
|
| 12 |
|
| 13 |
## 项目简介
|
| 14 |
|
| 15 |
-
本项目旨在将现有的 Grok 网页版逆向封装为 API 的 Python Flask 程序进行全面改造。改造目标是构建一个结构专业、功能完善(包含 Web UI)、文档齐全且易于部署的应用。项目严格遵守内存数据模式,所有运行时数据仅存储在内存中,不进行本地持久化。
|
| 16 |
|
| 17 |
## 功能列表
|
| 18 |
|
|
@@ -44,25 +44,47 @@ pinned: false
|
|
| 44 |
```
|
| 45 |
3. 运行 Docker 容器:
|
| 46 |
```bash
|
| 47 |
-
docker run -p
|
| 48 |
```
|
| 49 |
-
应用程序将在本地的
|
| 50 |
|
| 51 |
### 部署到 Hugging Face Spaces (使用 Docker)
|
| 52 |
|
| 53 |
1. 在 Hugging Face Spaces 上创建一个新的 Space。
|
| 54 |
2. 选择 Docker 作为 Space SDK。
|
| 55 |
3. 将本项目仓库关联到你的 Hugging Face Space。
|
| 56 |
-
4. Hugging Face Spaces 将会自动检测项目根目录下的 `Dockerfile` 并进行构建和部署。确保你的 `Dockerfile` 配置正确,暴露了 Flask 应用运行的端口(默认为
|
| 57 |
|
| 58 |
## 配置说明
|
| 59 |
|
| 60 |
-
本项目
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
| 65 |
-
请根据
|
| 66 |
|
| 67 |
## API 使用指南
|
| 68 |
|
|
|
|
| 12 |
|
| 13 |
## 项目简介
|
| 14 |
|
| 15 |
+
本项目基于 [https://github.com/xLmiler/grok2api_python](https://github.com/xLmiler/grok2api_python) 进行二次开发改造。旨在将现有的 Grok 网页版逆向封装为 API 的 Python Flask 程序进行全面改造。改造目标是构建一个结构专业、功能完善(包含 Web UI)、文档齐全且易于部署的应用。项目严格遵守内存数据模式,所有运行时数据仅存储在内存中,不进行本地持久化。
|
| 16 |
|
| 17 |
## 功能列表
|
| 18 |
|
|
|
|
| 44 |
```
|
| 45 |
3. 运行 Docker 容器:
|
| 46 |
```bash
|
| 47 |
+
docker run -p 7860:7860 grok-api-remodel
|
| 48 |
```
|
| 49 |
+
应用程序将在本地的 7860 端口运行。
|
| 50 |
|
| 51 |
### 部署到 Hugging Face Spaces (使用 Docker)
|
| 52 |
|
| 53 |
1. 在 Hugging Face Spaces 上创建一个新的 Space。
|
| 54 |
2. 选择 Docker 作为 Space SDK。
|
| 55 |
3. 将本项目仓库关联到你的 Hugging Face Space。
|
| 56 |
+
4. Hugging Face Spaces 将会自动检测项目根目录下的 `Dockerfile` 并进行构建和部署。确保你的 `Dockerfile` 配置正确,暴露了 Flask 应用运行的端口(默认为 7860)。
|
| 57 |
|
| 58 |
## 配置说明
|
| 59 |
|
| 60 |
+
本项目通过环境变量管理大部分配置项。您可以在项目根目录下创建 `.env` 文件来设置这些环境变量。
|
| 61 |
+
|
| 62 |
+
主要环境变量列表:
|
| 63 |
+
|
| 64 |
+
- `IS_TEMP_CONVERSATION`: 是否使用临时对话模式(默认为 `true`)。
|
| 65 |
+
- `IS_CUSTOM_SSO`: 是否使用自定义 SSO 令牌模式(默认为 `false`)。
|
| 66 |
+
- `API_BASE_URL`: Grok API 的基础 URL(默认为 `https://grok.com`)。
|
| 67 |
+
- `API_KEY`: 用于访问本程序 API 的密钥(默认为 `sk-123456`)。
|
| 68 |
+
- `PICGO_KEY`: PicGo 图床的 API 密钥(可选)。
|
| 69 |
+
- `TUMY_KEY`: Tumy 图床的 API 密钥(可选)。
|
| 70 |
+
- `PROXY`: HTTP/HTTPS 代理地址(可选)。
|
| 71 |
+
- `MANAGER_SWITCH`: 是否开启管理页面(可选,默认为关闭)。
|
| 72 |
+
- `ADMINPASSWORD`: 管理页面的访问密码(可选,开启管理页面时需要设置)。
|
| 73 |
+
- `CF_CLEARANCE`: Cloudflare 的 cf_clearance cookie 值(可选)。
|
| 74 |
+
- `PORT`: 应用程序监听的端口(默认为 `7860`)。
|
| 75 |
+
- `FLASK_SECRET_KEY`: Flask 应用程序的 Secret Key,用于会话管理(如果未设置,将自动生成)。
|
| 76 |
+
- `SSO`: Grok SSO 令牌,多个令牌使用逗号分隔。
|
| 77 |
+
|
| 78 |
+
示例 `.env` 文件内容:
|
| 79 |
+
|
| 80 |
+
```dotenv
|
| 81 |
+
IS_TEMP_CONVERSATION=true
|
| 82 |
+
API_KEY=your_api_key_here
|
| 83 |
+
PORT=7860
|
| 84 |
+
SSO=sso_token_1,sso_token_2
|
| 85 |
+
```
|
| 86 |
|
| 87 |
+
请根据您的实际需求配置这些环境变量。
|
| 88 |
|
| 89 |
## API 使用指南
|
| 90 |
|
app.py
CHANGED
|
@@ -6,77 +6,14 @@ import base64
|
|
| 6 |
import sys
|
| 7 |
import inspect
|
| 8 |
import secrets
|
| 9 |
-
from dotenv import load_dotenv
|
| 10 |
import requests
|
| 11 |
from flask import Flask, request, Response, jsonify, stream_with_context, render_template, redirect, session
|
| 12 |
from curl_cffi import requests as curl_requests
|
| 13 |
from werkzeug.middleware.proxy_fix import ProxyFix
|
| 14 |
|
|
|
|
| 15 |
from src.core.logger import logger # 从新的位置导入 logger
|
| 16 |
|
| 17 |
-
current_dir = os.path.dirname(os.path.abspath(__file__))
|
| 18 |
-
env_path = os.path.join(current_dir, '.env')
|
| 19 |
-
load_dotenv(env_path)
|
| 20 |
-
|
| 21 |
-
CONFIG = {
|
| 22 |
-
"MODELS": {
|
| 23 |
-
'grok-2': 'grok-latest',
|
| 24 |
-
'grok-2-imageGen': 'grok-latest',
|
| 25 |
-
'grok-2-search': 'grok-latest',
|
| 26 |
-
"grok-3": "grok-3",
|
| 27 |
-
"grok-3-search": "grok-3",
|
| 28 |
-
"grok-3-imageGen": "grok-3",
|
| 29 |
-
"grok-3-deepsearch": "grok-3",
|
| 30 |
-
"grok-3-reasoning": "grok-3"
|
| 31 |
-
},
|
| 32 |
-
"API": {
|
| 33 |
-
"IS_TEMP_CONVERSATION": os.getenv("IS_TEMP_CONVERSATION", "true").lower() == "true",
|
| 34 |
-
"IS_CUSTOM_SSO": os.getenv("IS_CUSTOM_SSO", "false").lower() == "true",
|
| 35 |
-
"BASE_URL": "https://grok.com",
|
| 36 |
-
"API_KEY": os.getenv("API_KEY", "sk-123456"),
|
| 37 |
-
"SIGNATURE_COOKIE": None,
|
| 38 |
-
"PICGO_KEY": os.getenv("PICGO_KEY") or None,
|
| 39 |
-
"TUMY_KEY": os.getenv("TUMY_KEY") or None,
|
| 40 |
-
"RETRY_TIME": 1000,
|
| 41 |
-
"PROXY": os.getenv("PROXY") or None
|
| 42 |
-
},
|
| 43 |
-
"ADMIN": {
|
| 44 |
-
"MANAGER_SWITCH": os.getenv("MANAGER_SWITCH") or None,
|
| 45 |
-
"PASSWORD": os.getenv("ADMINPASSWORD") or None
|
| 46 |
-
},
|
| 47 |
-
"SERVER": {
|
| 48 |
-
"COOKIE": None,
|
| 49 |
-
"CF_CLEARANCE":os.getenv("CF_CLEARANCE") or None,
|
| 50 |
-
"PORT": int(os.getenv("PORT", 5200))
|
| 51 |
-
},
|
| 52 |
-
"RETRY": {
|
| 53 |
-
"RETRYSWITCH": False,
|
| 54 |
-
"MAX_ATTEMPTS": 2
|
| 55 |
-
},
|
| 56 |
-
"SHOW_THINKING": os.getenv("SHOW_THINKING") == "true",
|
| 57 |
-
"IS_THINKING": False,
|
| 58 |
-
"IS_IMG_GEN": False,
|
| 59 |
-
"IS_IMG_GEN2": False,
|
| 60 |
-
"ISSHOW_SEARCH_RESULTS": os.getenv("ISSHOW_SEARCH_RESULTS", "true").lower() == "true"
|
| 61 |
-
}
|
| 62 |
-
|
| 63 |
-
DEFAULT_HEADERS = {
|
| 64 |
-
'Accept': '*/*',
|
| 65 |
-
'Accept-Language': 'zh-CN,zh;q=0.9',
|
| 66 |
-
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
| 67 |
-
'Content-Type': 'text/plain;charset=UTF-8',
|
| 68 |
-
'Connection': 'keep-alive',
|
| 69 |
-
'Origin': 'https://grok.com',
|
| 70 |
-
'Priority': 'u=1, i',
|
| 71 |
-
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
|
| 72 |
-
'Sec-Ch-Ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
|
| 73 |
-
'Sec-Ch-Ua-Mobile': '?0',
|
| 74 |
-
'Sec-Ch-Ua-Platform': '"macOS"',
|
| 75 |
-
'Sec-Fetch-Dest': 'empty',
|
| 76 |
-
'Sec-Fetch-Mode': 'cors',
|
| 77 |
-
'Sec-Fetch-Site': 'same-origin',
|
| 78 |
-
'Baggage': 'sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c'
|
| 79 |
-
}
|
| 80 |
|
| 81 |
from src.core.auth_token_manager import AuthTokenManager # 从新的位置导入 AuthTokenManager
|
| 82 |
|
|
|
|
| 6 |
import sys
|
| 7 |
import inspect
|
| 8 |
import secrets
|
|
|
|
| 9 |
import requests
|
| 10 |
from flask import Flask, request, Response, jsonify, stream_with_context, render_template, redirect, session
|
| 11 |
from curl_cffi import requests as curl_requests
|
| 12 |
from werkzeug.middleware.proxy_fix import ProxyFix
|
| 13 |
|
| 14 |
+
from src.config import CONFIG, DEFAULT_HEADERS # 导入配置项和默认请求头
|
| 15 |
from src.core.logger import logger # 从新的位置导入 logger
|
| 16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
from src.core.auth_token_manager import AuthTokenManager # 从新的位置导入 AuthTokenManager
|
| 19 |
|
src/config.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 应用程序配置项
|
| 2 |
+
import os
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
|
| 5 |
+
# 加载 .env 文件
|
| 6 |
+
current_dir = os.path.dirname(os.path.abspath(__file__))
|
| 7 |
+
# 假设 .env 文件在项目根目录,需要调整路径
|
| 8 |
+
# env_path = os.path.join(current_dir, '.env')
|
| 9 |
+
# load_dotenv(env_path)
|
| 10 |
+
# 如果 .env 文件在项目根目录,则直接加载
|
| 11 |
+
load_dotenv()
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
CONFIG = {
|
| 15 |
+
"MODELS": {
|
| 16 |
+
'grok-2': 'grok-latest',
|
| 17 |
+
'grok-2-imageGen': 'grok-latest',
|
| 18 |
+
'grok-2-search': 'grok-latest',
|
| 19 |
+
"grok-3": "grok-3",
|
| 20 |
+
"grok-3-search": "grok-3",
|
| 21 |
+
"grok-3-imageGen": "grok-3",
|
| 22 |
+
"grok-3-deepsearch": "grok-3",
|
| 23 |
+
"grok-3-reasoning": "grok-3"
|
| 24 |
+
},
|
| 25 |
+
"API": {
|
| 26 |
+
"IS_TEMP_CONVERSATION": os.getenv("IS_TEMP_CONVERSATION", "true").lower() == "true",
|
| 27 |
+
"IS_CUSTOM_SSO": os.getenv("IS_CUSTOM_SSO", "false").lower() == "true",
|
| 28 |
+
"BASE_URL": os.getenv("API_BASE_URL", "https://grok.com"),
|
| 29 |
+
"API_KEY": os.getenv("API_KEY", "sk-123456"),
|
| 30 |
+
"SIGNATURE_COOKIE": None,
|
| 31 |
+
"PICGO_KEY": os.getenv("PICGO_KEY") or None,
|
| 32 |
+
"TUMY_KEY": os.getenv("TUMY_KEY") or None,
|
| 33 |
+
"RETRY_TIME": 1000,
|
| 34 |
+
"PROXY": os.getenv("PROXY") or None
|
| 35 |
+
},
|
| 36 |
+
"ADMIN": {
|
| 37 |
+
"MANAGER_SWITCH": os.getenv("MANAGER_SWITCH") or None,
|
| 38 |
+
"PASSWORD": os.getenv("ADMINPASSWORD") or None
|
| 39 |
+
},
|
| 40 |
+
"SERVER": {
|
| 41 |
+
"COOKIE": None,
|
| 42 |
+
"CF_CLEARANCE":os.getenv("CF_CLEARANCE") or None,
|
| 43 |
+
"PORT": int(os.getenv("PORT", 7860))
|
| 44 |
+
},
|
| 45 |
+
"RETRY": {
|
| 46 |
+
"RETRYSWITCH": False,
|
| 47 |
+
"MAX_ATTEMPTS": 2
|
| 48 |
+
},
|
| 49 |
+
"SHOW_THINKING": os.getenv("SHOW_THINKING") == "true",
|
| 50 |
+
"IS_THINKING": False,
|
| 51 |
+
"IS_IMG_GEN": False,
|
| 52 |
+
"IS_IMG_GEN2": False,
|
| 53 |
+
"ISSHOW_SEARCH_RESULTS": os.getenv("ISSHOW_SEARCH_RESULTS", "true").lower() == "true"
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
# 默认请求头
|
| 57 |
+
DEFAULT_HEADERS = {
|
| 58 |
+
'Accept': '*/*',
|
| 59 |
+
'Accept-Language': 'zh-CN,zh;q=0.9',
|
| 60 |
+
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
| 61 |
+
'Content-Type': 'text/plain;charset=UTF-8',
|
| 62 |
+
'Connection': 'keep-alive',
|
| 63 |
+
'Origin': 'https://grok.com',
|
| 64 |
+
'Priority': 'u=1, i',
|
| 65 |
+
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
|
| 66 |
+
'Sec-Ch-Ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
|
| 67 |
+
'Sec-Ch-Ua-Mobile': '?0',
|
| 68 |
+
'Sec-Ch-Ua-Platform': '"macOS"',
|
| 69 |
+
'Sec-Fetch-Dest': 'empty',
|
| 70 |
+
'Sec-Fetch-Mode': 'cors',
|
| 71 |
+
'Sec-Fetch-Site': 'same-origin',
|
| 72 |
+
'Baggage': 'sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c'
|
| 73 |
+
}
|