import logging import sys import json from pathlib import Path from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from typing import List, Optional from datetime import datetime, timezone from ..database import get_db from ..models import SearchProvider from .auth import get_current_user logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/search-providers", tags=["search_providers"]) @router.get("") def list_providers(db: Session = Depends(get_db), current_user=Depends(get_current_user)): providers = db.query(SearchProvider).order_by(SearchProvider.priority).all() return [p.to_dict() for p in providers] @router.post("") def create_provider(data: dict, db: Session = Depends(get_db), current_user=Depends(get_current_user)): p = SearchProvider( name=data.get("name", ""), provider_type=data.get("provider_type", ""), api_key=data.get("api_key", ""), api_url=data.get("api_url", ""), console_url=data.get("console_url", ""), priority=data.get("priority", 99), enabled=data.get("enabled", True), daily_limit=data.get("daily_limit", 1500), extra_config=data.get("extra_config", {}), ) db.add(p) db.commit() db.refresh(p) return p.to_dict() @router.put("/{provider_id}") def update_provider(provider_id: int, data: dict, db: Session = Depends(get_db), current_user=Depends(get_current_user)): p = db.query(SearchProvider).filter(SearchProvider.id == provider_id).first() if not p: raise HTTPException(status_code=404, detail="Provider not found") for key in ("name", "provider_type", "api_key", "api_url", "console_url", "priority", "enabled", "daily_limit"): if key in data: setattr(p, key, data[key]) if "extra_config" in data: p.extra_config = data["extra_config"] p.updated_at = datetime.now(timezone.utc) db.commit() db.refresh(p) return p.to_dict() @router.delete("/{provider_id}") def delete_provider(provider_id: int, db: Session = Depends(get_db), current_user=Depends(get_current_user)): p = db.query(SearchProvider).filter(SearchProvider.id == provider_id).first() if not p: raise HTTPException(status_code=404, detail="Provider not found") db.delete(p) db.commit() return {"ok": True} @router.post("/{provider_id}/test") def test_provider(provider_id: int, data: dict = {}, db: Session = Depends(get_db), current_user=Depends(get_current_user)): p = db.query(SearchProvider).filter(SearchProvider.id == provider_id).first() if not p: raise HTTPException(status_code=404, detail="Provider not found") query = data.get("query", "测试搜索") try: test_key = data.get("api_key") or p.api_key test_url = data.get("api_url") or p.api_url if p.provider_type == "baidu": import requests resp = requests.post( test_url, headers={"Authorization": f"Bearer {test_key}", "Content-Type": "application/json"}, json={"messages": [{"role": "user", "content": query}], "search_source": "baidu_search_v2", "resource_type_filter": [{"type": "web", "top_k": 3}]}, timeout=15 ) if resp.status_code != 200: return {"ok": False, "error": f"HTTP {resp.status_code}: {resp.text[:200]}"} return {"ok": True, "results": resp.json().get("results", [])[:3]} elif p.provider_type == "qiniu": import requests resp = requests.post( test_url, headers={"Authorization": f"Bearer {test_key}", "Content-Type": "application/json"}, json={"query": query, "max_results": 3, "search_type": "web"}, timeout=15 ) if resp.status_code != 200: return {"ok": False, "error": f"HTTP {resp.status_code}: {resp.text[:200]}"} return {"ok": True, "results": resp.json().get("results", resp.json().get("data", []))[:3]} elif p.provider_type == "tinyfish": import requests resp = requests.get( test_url, params={"query": query, "max_results": 3}, headers={"X-API-Key": test_key}, timeout=15 ) if resp.status_code != 200: return {"ok": False, "error": f"HTTP {resp.status_code}: {resp.text[:200]}"} return {"ok": True, "results": resp.json().get("results", resp.json().get("data", []))[:3]} elif p.provider_type == "bing": import requests resp = requests.get( test_url, params={"q": query, "count": 3, "mkt": "zh-CN"}, headers={"Ocp-Apim-Subscription-Key": test_key}, timeout=15 ) if resp.status_code != 200: return {"ok": False, "error": f"HTTP {resp.status_code}: {resp.text[:200]}"} return {"ok": True, "results": resp.json().get("webPages", {}).get("value", [])[:3]} elif p.provider_type == "mcp": import subprocess, json as _json mcp_script = Path(__file__).resolve().parent.parent.parent.parent.parent / "scripts" / "mcp_search_server.py" r = subprocess.run( [sys.executable, str(mcp_script), "--query", query], capture_output=True, text=True, timeout=90, ) if r.returncode != 0: return {"ok": False, "error": f"子进程失败: {r.stderr[:200]}"} return {"ok": True, "results": _json.loads(r.stdout)[:3]} return {"ok": False, "error": f"Unknown provider_type: {p.provider_type}"} except Exception as e: return {"ok": False, "error": str(e)} @router.post("/reset-usage") def reset_usage(db: Session = Depends(get_db), current_user=Depends(get_current_user)): db.query(SearchProvider).update({SearchProvider.usage_today: 0}) db.commit() return {"ok": True}