Spaces:
Running
Running
| import os | |
| import sqlite3 | |
| import uuid | |
| import datetime | |
| # 1. 定位原项目在 Docker 容器内生成的 SQLite 数据库路径 | |
| # 原项目默认存放在 server/prisma/dev.db 或类似路径下,根据容器内实际路径做安全兼容 | |
| DB_PATHS = [ | |
| "/app/server/prisma/dev.db", | |
| "server/prisma/dev.db", | |
| "prisma/dev.db" | |
| ] | |
| def get_active_db(): | |
| for path in DB_PATHS: | |
| if os.path.exists(path): | |
| return path | |
| # 如果还没生成,尝试初始化一个路径 | |
| return "/app/server/prisma/dev.db" | |
| def inject_secrets_to_sqlite(): | |
| db_path = get_active_db() | |
| print(f"📦 正在连接 FreeLLMAPI 核心数据库: {db_path}") | |
| # 对齐你配置的 HF Secrets 名字与项目数据库里的 Provider 标识 | |
| secrets_map = { | |
| "GOOGLE_API_KEY": "google", | |
| "GROQ_API_KEY": "groq", | |
| "GITHUB_TOKEN": "github", | |
| "OPENROUTER_API_KEY": "openrouter", | |
| "MISTRAL_API_KEY": "mistral", | |
| "TOGETHER_API_KEY": "together", | |
| "NVIDIA_API_KEY": "nvidia", | |
| "COHERE_API_KEY": "cohere", | |
| "HF_TOKEN": "huggingface", | |
| "CEREBRAS_API_KEY": "cerebras", | |
| "SAMBANOVA_API_KEY": "sambanova", | |
| "CLOUDFLARE_API_TOKEN": "cloudflare", | |
| "ZHIPU_API_KEY": "zhipu" | |
| } | |
| try: | |
| conn = sqlite3.connect(db_path) | |
| cursor = conn.cursor() | |
| # 2. 检查原项目内 Provider 或者是 Keys 表的结构 | |
| # 原项目的表名通常叫 Provider 或者 Credentials | |
| cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") | |
| tables = [t[0] for t in cursor.fetchall()] | |
| print(f"📊 探测到系统当前表结构: {tables}") | |
| # 寻找存储渠道的表(通常包含 'Provider' 或 'Credential' 关键字) | |
| target_table = "Provider" if "Provider" in tables else None | |
| if not target_table: | |
| for t in tables: | |
| if "key" in t.lower() or "provider" in t.lower(): | |
| target_table = t | |
| break | |
| if not target_table: | |
| print("❌ 未能识别到原项目的密钥存储表,请先在前端随便手动添加任意一个Key以初始化数据库。") | |
| return | |
| # 3. 遍历并强行注入 Secrets | |
| success_count = 0 | |
| now = datetime.datetime.utcnow().isoformat() | |
| for secret_name, provider_id in secrets_map.items(): | |
| actual_key = os.getenv(secret_name) | |
| if not actual_key: | |
| continue | |
| # 检查数据库中是否已存在该渠道,防止重复插入 | |
| cursor.execute(f"SELECT id FROM {target_table} WHERE name = ? OR provider = ?", (provider_id, provider_id)) | |
| exists = cursor.fetchone() | |
| if not exists: | |
| # 动态生成符合 Prisma 规范的记录 | |
| # 💡 注意:原版采用了不加密或自加密,这里直接存入(如果原版带加密,脚本运行后前端会显示加密格式) | |
| record_id = str(uuid.uuid4()) | |
| try: | |
| # 根据标准的 Prisma 字段结构进行弹性插入 | |
| cursor.execute(f""" | |
| INSERT INTO {target_table} (id, name, provider, apiKey, status, createdAt, updatedAt) | |
| VALUES (?, ?, ?, ?, ?, ?, ?) | |
| """, (record_id, provider_id, provider_id, actual_key, "active", now, now)) | |
| success_count += 1 | |
| except sqlite3.OperationalError: | |
| # 如果字段不完全对齐,尝试最简化插入 | |
| cursor.execute(f""" | |
| INSERT INTO {target_table} (id, name, apiKey) | |
| VALUES (?, ?, ?) | |
| """, (record_id, provider_id, actual_key)) | |
| success_count += 1 | |
| conn.commit() | |
| conn.close() | |
| print(f"🏁 注入成功!已将 {success_count} 个云端 Secrets 强制同步到本地 SQLite。") | |
| except Exception as e: | |
| print(f"⚠️ 自动注入过程中发生意外,正在等待系统原生初始化: {str(e)}") | |
| if __name__ == "__main__": | |
| inject_secrets_to_sqlite() |