fix: content quality, image format, task monitor, calendar data source, search UI & sort

This commit is contained in:
Yuzhiran Dev
2026-05-26 11:26:10 +08:00
parent b2d043b231
commit ac8644d752
36 changed files with 2294 additions and 873 deletions
@@ -0,0 +1,141 @@
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}