from typing import List from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from pypinyin import pinyin, Style from sqlalchemy import or_, and_ from app.core.deps import get_db from app.core.deps import get_current_user from app.models.hotword import Hotword from app.models.user import User from app.schemas.hotword import Hotword as HotwordSchema, HotwordCreate, HotwordUpdate router = APIRouter() def is_admin(user: User): role_codes = [ur.role.role_code for ur in user.roles] if hasattr(user, "roles") else [] return "admin" in role_codes or "superuser" in role_codes @router.get("", response_model=List[HotwordSchema]) def list_hotwords( db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): query = db.query(Hotword, User).outerjoin(User, Hotword.user_id == User.user_id) if not is_admin(current_user): query = query.filter( or_( Hotword.scope.in_(["public", "global"]), and_(Hotword.scope == "personal", Hotword.user_id == current_user.user_id), ) ) results = query.all() out: List[HotwordSchema] = [] for hotword, creator in results: item = HotwordSchema.model_validate(hotword) item.creator_id = hotword.user_id item.creator_name = creator.display_name if creator else None item.creator_username = creator.username if creator else None out.append(item) return out @router.post("", response_model=HotwordSchema) def create_hotword( hotword_in: HotwordCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): # Auto generate pinyin py_list = pinyin(hotword_in.word, style=Style.NORMAL) # py_list is like [['zhong'], ['guo']] generated_pinyin = " ".join([item[0] for item in py_list]) scope = hotword_in.scope or "personal" if scope not in ["personal", "public"]: raise HTTPException(status_code=400, detail="Invalid scope") db_obj = Hotword( word=hotword_in.word, pinyin=generated_pinyin, weight=hotword_in.weight, scope=scope, user_id=current_user.user_id ) db.add(db_obj) db.commit() db.refresh(db_obj) return db_obj @router.put("/{hotword_id}", response_model=HotwordSchema) def update_hotword( hotword_id: int, hotword_in: HotwordUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): hotword = db.query(Hotword).filter(Hotword.id == hotword_id).first() if not hotword: raise HTTPException(status_code=404, detail="Hotword not found") if not is_admin(current_user): if hotword.scope == "personal" and hotword.user_id != current_user.user_id: raise HTTPException(status_code=403, detail="无权修改该热词") if hotword.scope in ["public", "global"] and hotword.user_id != current_user.user_id: raise HTTPException(status_code=403, detail="无权修改该热词") update_data = hotword_in.dict(exclude_unset=True) # If word is updated, regenerate pinyin if "word" in update_data and update_data["word"]: py_list = pinyin(update_data["word"], style=Style.NORMAL) update_data["pinyin"] = " ".join([item[0] for item in py_list]) if "scope" in update_data and update_data["scope"] not in ["personal", "public"]: raise HTTPException(status_code=400, detail="Invalid scope") for field, value in update_data.items(): setattr(hotword, field, value) db.add(hotword) db.commit() db.refresh(hotword) return hotword @router.delete("/{hotword_id}") def delete_hotword( hotword_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): hotword = db.query(Hotword).filter(Hotword.id == hotword_id).first() if not hotword: raise HTTPException(status_code=404, detail="Hotword not found") if not is_admin(current_user): if hotword.scope == "personal" and hotword.user_id != current_user.user_id: raise HTTPException(status_code=403, detail="无权删除该热词") if hotword.scope in ["public", "global"] and hotword.user_id != current_user.user_id: raise HTTPException(status_code=403, detail="无权删除该热词") db.delete(hotword) db.commit() return {"status": "success"}