180 lines
4.7 KiB
Python
180 lines
4.7 KiB
Python
"""
|
|
新闻 API - 提供新闻查询接口
|
|
"""
|
|
from fastapi import APIRouter, HTTPException, Query
|
|
from typing import Dict, List, Optional, Any
|
|
|
|
from app.news_agent.news_agent import get_news_agent
|
|
from app.news_agent.news_db_service import get_news_db_service
|
|
from app.utils.logger import logger
|
|
|
|
|
|
router = APIRouter(prefix="/api/news", tags=["新闻管理"])
|
|
|
|
|
|
@router.get("/articles")
|
|
async def get_articles(
|
|
category: Optional[str] = Query(None, description="分类过滤 (crypto/stock)"),
|
|
limit: int = Query(50, ge=1, le=200, description="返回数量限制"),
|
|
hours: int = Query(24, ge=1, le=168, description="查询最近多少小时")
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
获取新闻文章列表
|
|
|
|
Args:
|
|
category: 分类过滤
|
|
limit: 返回数量限制
|
|
hours: 查询最近多少小时
|
|
|
|
Returns:
|
|
文章列表
|
|
"""
|
|
try:
|
|
db_service = get_news_db_service()
|
|
articles = db_service.get_latest_articles(
|
|
category=category,
|
|
limit=limit,
|
|
hours=hours
|
|
)
|
|
|
|
return {
|
|
'success': True,
|
|
'articles': articles,
|
|
'count': len(articles)
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"获取新闻文章失败: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.get("/stats")
|
|
async def get_news_stats(
|
|
hours: int = Query(24, ge=1, le=168, description="统计最近多少小时")
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
获取新闻统计信息
|
|
|
|
Args:
|
|
hours: 统计最近多少小时
|
|
|
|
Returns:
|
|
统计数据
|
|
"""
|
|
try:
|
|
news_agent = get_news_agent()
|
|
agent_stats = news_agent.get_stats()
|
|
|
|
db_service = get_news_db_service()
|
|
db_stats = db_service.get_stats(hours=hours)
|
|
|
|
return {
|
|
'success': True,
|
|
'agent': agent_stats,
|
|
'database': db_stats
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"获取新闻统计失败: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.post("/fetch")
|
|
async def manual_fetch(
|
|
category: Optional[str] = Query(None, description="分类过滤 (crypto/stock)")
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
手动触发新闻抓取
|
|
|
|
Args:
|
|
category: 分类过滤
|
|
|
|
Returns:
|
|
抓取结果
|
|
"""
|
|
try:
|
|
news_agent = get_news_agent()
|
|
result = await news_agent.manual_fetch(category)
|
|
|
|
return {
|
|
'success': True,
|
|
**result
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"手动抓取新闻失败: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.get("/high-priority")
|
|
async def get_high_priority_articles(
|
|
limit: int = Query(20, ge=1, le=100, description="返回数量限制"),
|
|
min_priority: float = Query(40.0, description="最低优先级分数"),
|
|
hours: int = Query(24, ge=1, le=168, description="查询最近多少小时")
|
|
) -> Dict[str, Any]:
|
|
"""
|
|
获取高优先级文章
|
|
|
|
Args:
|
|
limit: 返回数量限制
|
|
min_priority: 最低优先级分数
|
|
hours: 查询最近多少小时
|
|
|
|
Returns:
|
|
高优先级文章列表
|
|
"""
|
|
try:
|
|
db_service = get_news_db_service()
|
|
articles = db_service.get_high_priority_articles(
|
|
limit=limit,
|
|
min_priority=min_priority,
|
|
hours=hours
|
|
)
|
|
|
|
return {
|
|
'success': True,
|
|
'articles': [article.to_dict() for article in articles],
|
|
'count': len(articles)
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"获取高优先级文章失败: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
@router.get("/sources")
|
|
async def get_news_sources() -> Dict[str, Any]:
|
|
"""
|
|
获取新闻源配置
|
|
|
|
Returns:
|
|
新闻源列表
|
|
"""
|
|
try:
|
|
from app.news_agent.sources import CRYPTO_NEWS_SOURCES, STOCK_NEWS_SOURCES
|
|
|
|
# 只返回基本信息,隐藏敏感配置
|
|
crypto_sources = [
|
|
{
|
|
'name': s['name'],
|
|
'category': s['category'],
|
|
'enabled': s['enabled']
|
|
}
|
|
for s in CRYPTO_NEWS_SOURCES
|
|
]
|
|
|
|
stock_sources = [
|
|
{
|
|
'name': s['name'],
|
|
'category': s['category'],
|
|
'enabled': s['enabled']
|
|
}
|
|
for s in STOCK_NEWS_SOURCES
|
|
]
|
|
|
|
return {
|
|
'success': True,
|
|
'crypto': crypto_sources,
|
|
'stock': stock_sources,
|
|
'total': len(crypto_sources) + len(stock_sources)
|
|
}
|
|
except Exception as e:
|
|
logger.error(f"获取新闻源失败: {e}")
|
|
raise HTTPException(status_code=500, detail=str(e))
|