Spaces:
Sleeping
Sleeping
db
Browse files- .gitignore +2 -1
- api_keys.db +0 -0
- app.py +47 -12
- captcha.png +0 -0
- db.py +64 -0
- requirements.txt +5 -1
- routers/openai_v1.py +86 -0
- routers/users_v1.py +48 -0
- routers/webtools_v1.py +29 -0
- sql.md +88 -0
- test_db.py +22 -0
- users.sql +41 -0
.gitignore
CHANGED
|
@@ -1 +1,2 @@
|
|
| 1 |
-
__pycache__/
|
|
|
|
|
|
| 1 |
+
__pycache__/
|
| 2 |
+
.env
|
api_keys.db
ADDED
|
Binary file (12.3 kB). View file
|
|
|
app.py
CHANGED
|
@@ -1,19 +1,54 @@
|
|
| 1 |
# uvicorn app:app --host 0.0.0.0 --port 7860 --reload
|
| 2 |
|
| 3 |
-
from fastapi import FastAPI, HTTPException
|
| 4 |
from starlette.requests import Request
|
| 5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
app = FastAPI()
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
@app.get("/")
|
| 9 |
-
def greet_json():
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
@app.
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
# uvicorn app:app --host 0.0.0.0 --port 7860 --reload
|
| 2 |
|
| 3 |
+
from fastapi import FastAPI, HTTPException, Response, Depends
|
| 4 |
from starlette.requests import Request
|
| 5 |
|
| 6 |
+
from routers.webtools_v1 import router as webtools_router
|
| 7 |
+
from routers.users_v1 import router as users_router
|
| 8 |
+
from routers.openai_v1 import router as openai_router
|
| 9 |
+
|
| 10 |
+
from db import Db
|
| 11 |
+
|
| 12 |
+
from dotenv import load_dotenv
|
| 13 |
+
import os
|
| 14 |
+
|
| 15 |
+
# 加载.env文件
|
| 16 |
+
load_dotenv()
|
| 17 |
+
|
| 18 |
+
DB_PATH = os.getenv("DB_PATH")
|
| 19 |
+
|
| 20 |
+
# 依赖注入,获取 DB_PATH
|
| 21 |
+
def get_db_path():
|
| 22 |
+
return DB_PATH
|
| 23 |
+
|
| 24 |
app = FastAPI()
|
| 25 |
|
| 26 |
+
app.include_router(webtools_router, prefix="/airs/v1", tags=["webtools"])
|
| 27 |
+
app.include_router(users_router, prefix="/airs/v1", tags=["users"])
|
| 28 |
+
app.include_router(openai_router, prefix="/airs/v1", tags=["openai"])
|
| 29 |
+
|
| 30 |
@app.get("/")
|
| 31 |
+
def greet_json(db_path: str = Depends(get_db_path)):
|
| 32 |
+
print(DB_PATH)
|
| 33 |
+
return {"Hello": "World!"}
|
| 34 |
+
@app.get("/init_db")
|
| 35 |
+
def init_db():
|
| 36 |
+
sql = """
|
| 37 |
+
CREATE TABLE api_keys (
|
| 38 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 39 |
+
api_key TEXT NOT NULL,
|
| 40 |
+
type TEXT NOT NULL,
|
| 41 |
+
status INTEGER NOT NULL,
|
| 42 |
+
idx INTEGER NOT NULL,
|
| 43 |
+
dest_api_key TEXT NOT NULL
|
| 44 |
+
);
|
| 45 |
+
"""
|
| 46 |
+
Db('api_keys.db').execute_query(sql)
|
| 47 |
+
|
| 48 |
+
# def create_user_api_key(user_id, api_key, type, status, idx, dest_api_key):
|
| 49 |
+
# sql = f"""
|
| 50 |
+
# INSERT INTO api_keys (api_key, type, status, idx, dest_api_key)
|
| 51 |
+
# """
|
| 52 |
+
# Db('api_keys.db').execute_query(sql)
|
| 53 |
+
|
| 54 |
+
# create_user_api_key('i_am_tanbushi', 'llm', '1', '0', 'dest_api_key')
|
captcha.png
ADDED
|
db.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sqlite3
|
| 2 |
+
import json
|
| 3 |
+
|
| 4 |
+
class Db():
|
| 5 |
+
def __init__(self, db_path):
|
| 6 |
+
self.db_path = db_path
|
| 7 |
+
# print(self.db_path)
|
| 8 |
+
|
| 9 |
+
def list_query(self, query):
|
| 10 |
+
conn = sqlite3.connect(self.db_path)
|
| 11 |
+
cursor = conn.cursor()
|
| 12 |
+
cursor.execute(query)
|
| 13 |
+
conn.commit()
|
| 14 |
+
|
| 15 |
+
rows = cursor.fetchall()
|
| 16 |
+
# print('results')
|
| 17 |
+
# print(results)
|
| 18 |
+
cursor.close()
|
| 19 |
+
conn.close()
|
| 20 |
+
|
| 21 |
+
json_rows = []
|
| 22 |
+
# 为每一行结果创建一个字典,并添加到列表中
|
| 23 |
+
for row in rows:
|
| 24 |
+
# 使用cursor.description获取列名和相关信息
|
| 25 |
+
columns = dict(zip([col[0] for col in cursor.description], row))
|
| 26 |
+
json_rows.append(columns)
|
| 27 |
+
|
| 28 |
+
return json_rows
|
| 29 |
+
|
| 30 |
+
def insert_query(self, query):
|
| 31 |
+
conn = sqlite3.connect(self.db_path)
|
| 32 |
+
cursor = conn.cursor()
|
| 33 |
+
cursor.execute(query)
|
| 34 |
+
conn.commit()
|
| 35 |
+
rowcount = cursor.rowcount
|
| 36 |
+
|
| 37 |
+
return f"插入的行数: {rowcount}"
|
| 38 |
+
|
| 39 |
+
def update_query(self, query):
|
| 40 |
+
conn = sqlite3.connect(self.db_path)
|
| 41 |
+
cursor = conn.cursor()
|
| 42 |
+
cursor.execute(query)
|
| 43 |
+
conn.commit()
|
| 44 |
+
rowcount = cursor.rowcount
|
| 45 |
+
|
| 46 |
+
return f"影响的行数: {rowcount}"
|
| 47 |
+
# from fastapi import FastAPI
|
| 48 |
+
|
| 49 |
+
# # 依赖注入,获取 FastAPI 应用实例
|
| 50 |
+
# def get_app() -> FastAPI:
|
| 51 |
+
# return FastAPI()
|
| 52 |
+
|
| 53 |
+
# def execute_query(query):
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
# CREATE TABLE api_keys (
|
| 59 |
+
# api_key TEXT NOT NULL,
|
| 60 |
+
# type TEXT NOT NULL,
|
| 61 |
+
# status INTEGER NOT NULL,
|
| 62 |
+
# idx INTEGER NOT NULL,
|
| 63 |
+
# PRIMARY KEY (api_key, type, status, idx)
|
| 64 |
+
# );
|
requirements.txt
CHANGED
|
@@ -1,2 +1,6 @@
|
|
| 1 |
fastapi
|
| 2 |
-
uvicorn[standard]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
fastapi
|
| 2 |
+
uvicorn[standard]
|
| 3 |
+
captcha
|
| 4 |
+
python-dotenv
|
| 5 |
+
langchain_google_genai==1.0.10
|
| 6 |
+
langchain-openai==0.1.25 # 使用 openai 或兼容 openai
|
routers/openai_v1.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Request, HTTPException
|
| 2 |
+
from db import Db
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
import os, json
|
| 5 |
+
from langchain_core.output_parsers import StrOutputParser
|
| 6 |
+
from langchain_core.prompts import ChatPromptTemplate
|
| 7 |
+
|
| 8 |
+
# 加载.env文件
|
| 9 |
+
load_dotenv()
|
| 10 |
+
|
| 11 |
+
router = APIRouter()
|
| 12 |
+
|
| 13 |
+
@router.post("/chat/completions")
|
| 14 |
+
async def chat_completions(request:Request):
|
| 15 |
+
print('chat_completions')
|
| 16 |
+
auth_header = request.headers['authorization']
|
| 17 |
+
user_api_key = auth_header.split()[1] # 分割字符串并取第二个元素
|
| 18 |
+
data = await request.json()
|
| 19 |
+
try:
|
| 20 |
+
model = data['model']
|
| 21 |
+
except:
|
| 22 |
+
model = ''
|
| 23 |
+
if model=='':
|
| 24 |
+
model = await get_default_model()
|
| 25 |
+
api_key_info = await get_api_key(model)
|
| 26 |
+
api_key = api_key_info['api_key']
|
| 27 |
+
group_name = api_key_info['group_name']
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
# 下面是google api
|
| 31 |
+
if group_name=='gemini':
|
| 32 |
+
from langchain_google_genai import ChatGoogleGenerativeAI
|
| 33 |
+
# 初始化模型
|
| 34 |
+
llm = ChatGoogleGenerativeAI(
|
| 35 |
+
api_key = api_key,
|
| 36 |
+
model = model,
|
| 37 |
+
)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
# 下面就是 chatgpt 兼容 api
|
| 41 |
+
if group_name=='glm':
|
| 42 |
+
from langchain_openai import ChatOpenAI
|
| 43 |
+
# 初始化 ChatOpenAI 模型
|
| 44 |
+
llm = ChatOpenAI(
|
| 45 |
+
model = model,
|
| 46 |
+
api_key = api_key,
|
| 47 |
+
base_url = 'https://open.bigmodel.cn/api/paas/v4', # 下一步将base_url 写到数据库里
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
messages = data['messages']
|
| 51 |
+
rslt = [(item["role"], item["content"]) for item in messages] # 转换为所需的元组列表格式
|
| 52 |
+
parser = StrOutputParser()
|
| 53 |
+
prompt_template = ChatPromptTemplate.from_messages(rslt)
|
| 54 |
+
|
| 55 |
+
chain = prompt_template | llm | parser
|
| 56 |
+
result = chain.invoke({})
|
| 57 |
+
return result
|
| 58 |
+
|
| 59 |
+
async def get_default_model():
|
| 60 |
+
results = Db(os.getenv("DB_PATH")).list_query("SELECT * FROM api_names order by default_order limit 1")
|
| 61 |
+
try:
|
| 62 |
+
result = results[0]['api_name']
|
| 63 |
+
except:
|
| 64 |
+
result = ''
|
| 65 |
+
return result
|
| 66 |
+
|
| 67 |
+
async def get_api_key(model):
|
| 68 |
+
sql = f"""
|
| 69 |
+
SELECT an.api_name, ak.api_key, ag.group_name
|
| 70 |
+
FROM api_keys ak
|
| 71 |
+
JOIN api_groups ag ON ak.api_group_id = ag.id
|
| 72 |
+
JOIN api_names an ON an.api_group_id = ag.id
|
| 73 |
+
WHERE ak.category='LLM' and an.api_name='{model}' and disabled=0
|
| 74 |
+
ORDER BY ak.last_call_at
|
| 75 |
+
limit 1
|
| 76 |
+
"""
|
| 77 |
+
results = Db(os.getenv("DB_PATH")).list_query(sql)
|
| 78 |
+
try:
|
| 79 |
+
result = results[0]
|
| 80 |
+
api_key = result['api_key']
|
| 81 |
+
except:
|
| 82 |
+
api_key = ''
|
| 83 |
+
|
| 84 |
+
sql = f"update api_keys set last_call_at=datetime('now') where api_key='{api_key}'"
|
| 85 |
+
Db(os.getenv("DB_PATH")).update_query(sql)
|
| 86 |
+
return result
|
routers/users_v1.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Request, FastAPI, Depends
|
| 2 |
+
from dotenv import load_dotenv
|
| 3 |
+
import os
|
| 4 |
+
import uuid
|
| 5 |
+
from db import Db
|
| 6 |
+
|
| 7 |
+
router = APIRouter()
|
| 8 |
+
|
| 9 |
+
# 加载.env文件
|
| 10 |
+
load_dotenv()
|
| 11 |
+
|
| 12 |
+
DB_PATH = os.getenv("DB_PATH")
|
| 13 |
+
|
| 14 |
+
# 依赖注入,获取 DB_PATH
|
| 15 |
+
def get_db_path():
|
| 16 |
+
return DB_PATH
|
| 17 |
+
|
| 18 |
+
@router.get("/users")
|
| 19 |
+
async def read_users(db_path: str = Depends(get_db_path)):
|
| 20 |
+
# print('\n\n\n\n\n')
|
| 21 |
+
# print(db_path)
|
| 22 |
+
result = Db(db_path).list_query("SELECT * FROM users")
|
| 23 |
+
return result
|
| 24 |
+
|
| 25 |
+
@router.post("/users")
|
| 26 |
+
async def create_user(request: Request, b_path: str = Depends(get_db_path)):
|
| 27 |
+
request_json = await request.json()
|
| 28 |
+
username = request_json.get('username')
|
| 29 |
+
password = request_json.get('password')
|
| 30 |
+
email = request_json.get('email')
|
| 31 |
+
nikename = request_json.get('nikename')
|
| 32 |
+
if nikename==None:
|
| 33 |
+
nikename = ''
|
| 34 |
+
# print(nikename)
|
| 35 |
+
api_key = f'airs-{uuid.uuid4()}'
|
| 36 |
+
# result = api_key
|
| 37 |
+
# print(api_key)
|
| 38 |
+
result = Db(b_path).insert_query(f"INSERT INTO users (username, password, email, nikename, api_key) VALUES ('{username}', '{password}', '{email}', '{nikename}', '{api_key}')")
|
| 39 |
+
return result
|
| 40 |
+
|
| 41 |
+
@router.get("/users/{id}")
|
| 42 |
+
async def read_user(request: Request, id:int, db_path: str = Depends(get_db_path)):
|
| 43 |
+
result = Db(db_path).list_query(f"SELECT * FROM users where id={id}")
|
| 44 |
+
if len(result)>0:
|
| 45 |
+
return result[0]
|
| 46 |
+
else:
|
| 47 |
+
return None
|
| 48 |
+
|
routers/webtools_v1.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, APIRouter, Response, Depends
|
| 2 |
+
from captcha.image import ImageCaptcha
|
| 3 |
+
from io import BytesIO
|
| 4 |
+
|
| 5 |
+
router = APIRouter()
|
| 6 |
+
|
| 7 |
+
# 依赖注入,获取 FastAPI 应用实例
|
| 8 |
+
def get_app() -> FastAPI:
|
| 9 |
+
return FastAPI()
|
| 10 |
+
|
| 11 |
+
@router.get("/webtools/captcha")
|
| 12 |
+
async def get_captcha(app: FastAPI = Depends(get_app)):
|
| 13 |
+
# 生成随机验证码字符串
|
| 14 |
+
captcha_text = "123456" # 这里只是一个示例,实际应用中应该生成一个随机字符串
|
| 15 |
+
# 创建验证码图片
|
| 16 |
+
image = ImageCaptcha(width=280, height=90)
|
| 17 |
+
image.write(captcha_text, "captcha.png")
|
| 18 |
+
|
| 19 |
+
# 将验证码字符串存储在内存中,以便后续验证
|
| 20 |
+
# 注意:实际应用中应该使用更安全的方式存储验证码,例如使用会话或数据库
|
| 21 |
+
app.captcha_text = captcha_text
|
| 22 |
+
|
| 23 |
+
# 读取图片内容并返回
|
| 24 |
+
image_buffer = BytesIO()
|
| 25 |
+
image.write(captcha_text, image_buffer)
|
| 26 |
+
image_buffer.seek(0)
|
| 27 |
+
|
| 28 |
+
# 返回图片数据
|
| 29 |
+
return Response(content=image_buffer.getvalue(), media_type="image/png")
|
sql.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
当然,以下是完整的SQL语句,用于创建`api_names`、`api_keys`表,以及可选的`api_usage`表。这些表将支持存储API名称、API-KEY信息,并可选地记录API的使用情况。
|
| 2 |
+
|
| 3 |
+
### SQL 创建表的语句
|
| 4 |
+
|
| 5 |
+
```sql
|
| 6 |
+
-- 创建 users 表
|
| 7 |
+
DROP TABLE IF EXISTS "users";
|
| 8 |
+
CREATE TABLE "users" (
|
| 9 |
+
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 10 |
+
"username" TEXT NOT NULL,
|
| 11 |
+
"password" TEXT NOT NULL,
|
| 12 |
+
"email" TEXT NOT NULL,
|
| 13 |
+
"nikename" TEXT,
|
| 14 |
+
"created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 15 |
+
"updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 16 |
+
UNIQUE ("username" ASC),
|
| 17 |
+
UNIQUE ("email" ASC)
|
| 18 |
+
);
|
| 19 |
+
|
| 20 |
+
-- 创建api_groups表
|
| 21 |
+
CREATE TABLE api_groups (
|
| 22 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 23 |
+
group_name TEXT NOT NULL UNIQUE,
|
| 24 |
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 25 |
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
| 26 |
+
);
|
| 27 |
+
|
| 28 |
+
-- 创建api_names表
|
| 29 |
+
CREATE TABLE api_names (
|
| 30 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 31 |
+
api_name TEXT NOT NULL UNIQUE,
|
| 32 |
+
api_group_id INTEGER,
|
| 33 |
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 34 |
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 35 |
+
FOREIGN KEY (api_group_id) REFERENCES api_groups(id) ON DELETE SET NULL
|
| 36 |
+
);
|
| 37 |
+
|
| 38 |
+
-- 创建api_keys表
|
| 39 |
+
CREATE TABLE api_keys (
|
| 40 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 41 |
+
api_group_id INTEGER NOT NULL,
|
| 42 |
+
api_key TEXT NOT NULL,
|
| 43 |
+
category TEXT NOT NULL,
|
| 44 |
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 45 |
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 46 |
+
FOREIGN KEY (api_group_id) REFERENCES api_groups(id) ON DELETE CASCADE
|
| 47 |
+
);
|
| 48 |
+
|
| 49 |
+
-- 创建user_api_keys表
|
| 50 |
+
CREATE TABLE user_api_keys (
|
| 51 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 52 |
+
user_api_key TEXT NOT NULL,
|
| 53 |
+
user_id INTEGER,
|
| 54 |
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 55 |
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
| 56 |
+
);
|
| 57 |
+
|
| 58 |
+
-- 创建api_usage表(如果需要)
|
| 59 |
+
CREATE TABLE api_usage (
|
| 60 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 61 |
+
user_api_key_id INTEGER,
|
| 62 |
+
api_key_id INTEGER,
|
| 63 |
+
request_count INTEGER DEFAULT 0,
|
| 64 |
+
last_used DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 65 |
+
FOREIGN KEY (user_api_key_id) REFERENCES user_api_keys(id),
|
| 66 |
+
FOREIGN KEY (api_key_id) REFERENCES api_keys(id)
|
| 67 |
+
);
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
### 说明
|
| 71 |
+
|
| 72 |
+
- **`api_names` 表**:存储唯一的API名称。
|
| 73 |
+
- **`api_keys` 表**:存储每个API名称对应的多个API-KEY,包括分类信息。`api_names_id`作为外键,关联到`api_names`表。
|
| 74 |
+
- **`user_api_keys` 表**:存储用户的API-KEY。
|
| 75 |
+
- **`api_usage` 表**(可选):记录API的使用情况,包括请求次数和最后使用时间。这个表可以用来监控API的使用情况,帮助管理API-KEY的使用限额。
|
| 76 |
+
|
| 77 |
+
这些SQL语句假设你使用的是MySQL数据库。如果你使用的是其他类型的数据库(如PostgreSQL、SQLite等),可能需要对SQL语句进行适当的调整。如果有任何问题或需要进一步的帮助,请随时告诉我。
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
### 通过 api_name 查询 api_key 的 SQL 语句
|
| 82 |
+
```sql
|
| 83 |
+
SELECT ak.api_key
|
| 84 |
+
FROM api_keys ak
|
| 85 |
+
JOIN api_groups ag ON ak.api_group_id = ag.id
|
| 86 |
+
JOIN api_names an ON an.api_group_id = ag.id
|
| 87 |
+
WHERE an.api_name = 'your_api_name';
|
| 88 |
+
```
|
test_db.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# PC上数据库的位置为:/mnt/f/微云同步目录/1913864316/dev/projects/api-mapper
|
| 2 |
+
|
| 3 |
+
from db import Db
|
| 4 |
+
from dotenv import load_dotenv
|
| 5 |
+
import os
|
| 6 |
+
|
| 7 |
+
# 加载.env文件
|
| 8 |
+
load_dotenv()
|
| 9 |
+
|
| 10 |
+
db = Db(os.getenv("DB_PATH"))
|
| 11 |
+
|
| 12 |
+
results = db.execute_query("""
|
| 13 |
+
SELECT an.api_name, ak.api_key
|
| 14 |
+
FROM api_keys ak
|
| 15 |
+
JOIN api_groups ag ON ak.api_group_id = ag.id
|
| 16 |
+
JOIN api_names an ON an.api_group_id = ag.id
|
| 17 |
+
WHERE an.api_name = 'glm-4-flash';
|
| 18 |
+
""")
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
for row in results:
|
| 22 |
+
print(row)
|
users.sql
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
Navicat Premium Dump SQL
|
| 3 |
+
|
| 4 |
+
Source Server : api_keys
|
| 5 |
+
Source Server Type : SQLite
|
| 6 |
+
Source Server Version : 3045000 (3.45.0)
|
| 7 |
+
Source Schema : main
|
| 8 |
+
|
| 9 |
+
Target Server Type : SQLite
|
| 10 |
+
Target Server Version : 3045000 (3.45.0)
|
| 11 |
+
File Encoding : 65001
|
| 12 |
+
|
| 13 |
+
Date: 03/11/2024 20:45:36
|
| 14 |
+
*/
|
| 15 |
+
|
| 16 |
+
PRAGMA foreign_keys = false;
|
| 17 |
+
|
| 18 |
+
-- ----------------------------
|
| 19 |
+
-- Table structure for users
|
| 20 |
+
-- ----------------------------
|
| 21 |
+
DROP TABLE IF EXISTS "users";
|
| 22 |
+
CREATE TABLE "users" (
|
| 23 |
+
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 24 |
+
"username" TEXT NOT NULL,
|
| 25 |
+
"password" TEXT NOT NULL,
|
| 26 |
+
"email" TEXT NOT NULL,
|
| 27 |
+
"nikename" TEXT,
|
| 28 |
+
"api_key" TEXT,
|
| 29 |
+
"config" TEXT,
|
| 30 |
+
"created_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 31 |
+
"updated_at" DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 32 |
+
UNIQUE ("username" ASC),
|
| 33 |
+
UNIQUE ("email" ASC)
|
| 34 |
+
);
|
| 35 |
+
|
| 36 |
+
-- ----------------------------
|
| 37 |
+
-- Auto increment value for users
|
| 38 |
+
-- ----------------------------
|
| 39 |
+
UPDATE "sqlite_sequence" SET seq = 5 WHERE name = 'users';
|
| 40 |
+
|
| 41 |
+
PRAGMA foreign_keys = true;
|