Files
goalfylearning-admin/scripts/invite_code_api.py

125 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
邀请码申请 API - 简洁版本
使用方法:
1. 直接运行: ./scripts/run_invite_api.sh
2. 或者: uv run scripts/invite_code_api.py
3. 访问: POST http://localhost:8000/api/invite-code/apply
默认使用 AWS RDS 数据库(与 Go 项目共享)
如需使用本地数据库,请设置环境变量或创建 scripts/.env 文件
"""
import os
from datetime import datetime, timezone
from typing import Optional
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Text
from sqlalchemy.orm import declarative_base, Session
from sqlalchemy.exc import IntegrityError
# 数据库配置 - 从环境变量读取(默认使用 AWS RDS 配置)
DB_USER = os.getenv("DB_USER", "goalfymax_prod")
DB_PASSWORD = os.getenv("DB_PASSWORD", "X6cQDaOLOifFBOMq")
DB_HOST = os.getenv("DB_HOST", "goalfyagent-aurora-mysql-staging.cb2sq6y2mg93.us-west-2.rds.amazonaws.com")
DB_PORT = os.getenv("DB_PORT", "3306")
DB_NAME = os.getenv("DB_NAME", "goalfymax_prod")
DATABASE_URL = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8mb4"
Base = declarative_base()
engine = create_engine(DATABASE_URL, echo=False, pool_pre_ping=True)
# 数据模型 - 与 Go 项目的 admin_invite_code_applications 表结构保持一致
class InviteCodeApplication(Base):
__tablename__ = "admin_invite_code_applications"
id = Column(Integer, primary_key=True, autoincrement=True)
email = Column(String(255), nullable=False, index=True)
reason = Column(Text, nullable=True)
language = Column(String(10), nullable=False, default="zh")
status = Column(String(20), nullable=False, default="pending", index=True)
created_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
updated_at = Column(DateTime, nullable=False, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
# 不自动创建表(使用 Go 项目已有的表结构)
# Base.metadata.create_all(engine)
# FastAPI 应用
app = FastAPI(title="邀请码申请 API")
# 请求/响应模型
class ApplicationRequest(BaseModel):
email: EmailStr
reason: Optional[str] = None
language: Optional[str] = "zh" # zh 或 en默认 zh
class ApplicationResponse(BaseModel):
id: int
email: str
reason: Optional[str]
language: str
status: str
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class SuccessResponse(BaseModel):
code: int = 0
message: str
data: ApplicationResponse
# API 端点
@app.post("/api/invite-code/apply", response_model=SuccessResponse)
async def submit_application(req: ApplicationRequest):
"""提交邀请码申请"""
with Session(engine) as session:
# 检查是否已有待处理或已通过的申请
existing = session.query(InviteCodeApplication).filter(
InviteCodeApplication.email == req.email,
InviteCodeApplication.status.in_(["pending", "approved"])
).first()
if existing:
if existing.status == "pending":
raise HTTPException(status_code=400, detail="您已经提交过申请,请等待审核")
if existing.status == "approved":
raise HTTPException(status_code=400, detail="您的申请已通过,请检查邮箱")
# 创建新申请
language = req.language if req.language in ["zh", "en"] else "zh"
application = InviteCodeApplication(
email=req.email,
reason=req.reason,
language=language,
status="pending"
)
try:
session.add(application)
session.commit()
session.refresh(application)
return SuccessResponse(
message="申请已提交我们将在1-2个工作日内处理您的申请",
data=ApplicationResponse.model_validate(application)
)
except IntegrityError:
session.rollback()
raise HTTPException(status_code=500, detail="创建申请失败")
# 健康检查
@app.get("/health")
async def health_check():
return {"status": "ok"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)