feat: add NSFW script generation feature and Grok API configuration

This commit is contained in:
2026-03-13 12:58:28 +08:00
parent 424c3edf0b
commit 0d63d0e6d1
28 changed files with 850 additions and 36 deletions

View File

@@ -26,6 +26,8 @@ from schemas.audiobook import (
ScriptGenerationRequest,
SynopsisGenerationRequest,
ContinueScriptRequest,
NsfwSynopsisGenerationRequest,
NsfwScriptGenerationRequest,
)
from core.config import settings
@@ -33,6 +35,13 @@ logger = logging.getLogger(__name__)
router = APIRouter(prefix="/audiobook", tags=["audiobook"])
async def require_nsfw(current_user: User = Depends(get_current_user), db: Session = Depends(get_db)):
from db.crud import can_user_use_nsfw
if not can_user_use_nsfw(current_user):
raise HTTPException(status_code=403, detail="NSFW access not granted")
return current_user
def _project_to_response(project) -> AudiobookProjectResponse:
return AudiobookProjectResponse(
id=project.id,
@@ -268,6 +277,86 @@ async def continue_script(
return {"message": f"Continuing script generation ({additional_chapters} chapters)", "project_id": project_id}
@router.post("/projects/generate-synopsis-nsfw")
async def generate_synopsis_nsfw(
data: NsfwSynopsisGenerationRequest,
current_user: User = Depends(require_nsfw),
db: Session = Depends(get_db),
):
from db.crud import get_system_setting
if not get_system_setting(db, "grok_api_key") or not get_system_setting(db, "grok_base_url"):
raise HTTPException(status_code=400, detail="Grok config not set. Please configure Grok API key first.")
from core.audiobook_service import _get_grok_service
llm = _get_grok_service(db)
system_prompt = (
"你是一位专业的成人小说策划师,擅长根据创作参数生成引人入胜的故事简介。"
"请根据用户提供的类型、风格、主角、冲突等参数生成一段200-400字的中文故事简介。"
"简介需涵盖:世界观背景、主角基本情况、核心矛盾冲突、故事基调。"
"直接输出简介正文,不要加任何前缀标题或说明文字。"
)
parts = [f"类型:{data.genre}"]
if data.subgenre:
parts.append(f"子类型:{data.subgenre}")
if data.protagonist_type:
parts.append(f"主角类型:{data.protagonist_type}")
if data.tone:
parts.append(f"故事基调:{data.tone}")
if data.conflict_scale:
parts.append(f"冲突规模:{data.conflict_scale}")
parts.append(f"角色数量:约{data.num_characters}个主要角色")
parts.append(f"故事体量:约{data.num_chapters}")
user_message = "\n".join(parts) + "\n\n请生成故事简介:"
try:
synopsis = await llm.chat(system_prompt, user_message)
except Exception as e:
logger.error(f"NSFW synopsis generation failed: {e}")
raise HTTPException(status_code=500, detail=f"Grok generation failed: {str(e)}")
return {"synopsis": synopsis}
@router.post("/projects/generate-script-nsfw", response_model=AudiobookProjectResponse, status_code=status.HTTP_201_CREATED)
async def create_nsfw_script_project(
data: NsfwScriptGenerationRequest,
current_user: User = Depends(require_nsfw),
db: Session = Depends(get_db),
):
from db.crud import get_system_setting
if not get_system_setting(db, "grok_api_key") or not get_system_setting(db, "grok_base_url"):
raise HTTPException(status_code=400, detail="Grok config not set. Please configure Grok API key first.")
script_config = data.model_dump()
script_config["nsfw_mode"] = True
project = crud.create_audiobook_project(
db=db,
user_id=current_user.id,
title=data.title,
source_type="ai_generated",
script_config=script_config,
)
from core.audiobook_service import generate_ai_script_nsfw
from core.database import SessionLocal
project_id = project.id
user_id = current_user.id
async def run():
async_db = SessionLocal()
try:
db_user = crud.get_user_by_id(async_db, user_id)
await generate_ai_script_nsfw(project_id, db_user, async_db)
finally:
async_db.close()
asyncio.create_task(run())
return _project_to_response(project)
@router.get("/projects/{project_id}", response_model=AudiobookProjectDetail)
async def get_project(
project_id: int,