292 lines
9.7 KiB
Python
292 lines
9.7 KiB
Python
"""
|
||
会会接口对接服务
|
||
基于 http://192.168.1.200:63120/doc.html 接口文档
|
||
"""
|
||
import httpx
|
||
import logging
|
||
from typing import Optional, Dict, Any, List
|
||
from datetime import datetime
|
||
|
||
from app.core.config import settings
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class HuihuiAPIService:
|
||
"""会会 API 服务类"""
|
||
|
||
def __init__(self):
|
||
self.base_url = settings.HUIHUI_API_BASE
|
||
self.timeout = 30 # 秒
|
||
self._session_cache: Dict[str, httpx.AsyncClient] = {}
|
||
|
||
def _get_client(self, session_token: Optional[str] = None) -> httpx.AsyncClient:
|
||
"""获取 HTTP 客户端"""
|
||
headers = {
|
||
"Content-Type": "application/json",
|
||
"Accept": "application/json",
|
||
}
|
||
|
||
if session_token:
|
||
headers["Authorization"] = f"Bearer {session_token}"
|
||
|
||
return httpx.AsyncClient(
|
||
base_url=self.base_url,
|
||
headers=headers,
|
||
timeout=self.timeout,
|
||
)
|
||
|
||
async def login(self, username: str, password: str) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
用户登录
|
||
:param username: 用户名
|
||
:param password: 密码
|
||
:return: 登录响应(包含 session token)
|
||
"""
|
||
try:
|
||
async with self._get_client() as client:
|
||
response = await client.post(
|
||
"/api/login", # 实际接口路径需根据 doc.html 调整
|
||
json={"username": username, "password": password}
|
||
)
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
logger.info(f"Login success for user: {username}")
|
||
return data
|
||
else:
|
||
logger.error(f"Login failed: {response.status_code} - {response.text}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Login error: {e}")
|
||
return None
|
||
|
||
async def get_news_list(
|
||
self,
|
||
page: int = 1,
|
||
page_size: int = 20,
|
||
category: Optional[str] = None
|
||
) -> Optional[List[Dict[str, Any]]]:
|
||
"""
|
||
获取新闻列表
|
||
:param page: 页码
|
||
:param page_size: 每页数量
|
||
:param category: 分类(可选)
|
||
:return: 新闻列表
|
||
"""
|
||
try:
|
||
async with self._get_client() as client:
|
||
params = {"page": page, "pageSize": page_size}
|
||
if category:
|
||
params["category"] = category
|
||
|
||
response = await client.get(
|
||
"/api/news/list", # 实际接口路径需根据 doc.html 调整
|
||
params=params
|
||
)
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
return data.get("data", [])
|
||
else:
|
||
logger.error(f"Get news list failed: {response.status_code}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Get news list error: {e}")
|
||
return None
|
||
|
||
async def get_news_detail(self, news_id: str) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
获取新闻详情
|
||
:param news_id: 新闻 ID
|
||
:return: 新闻详情
|
||
"""
|
||
try:
|
||
async with self._get_client() as client:
|
||
response = await client.get(f"/api/news/{news_id}")
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
return data.get("data")
|
||
else:
|
||
logger.error(f"Get news detail failed: {response.status_code}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Get news detail error: {e}")
|
||
return None
|
||
|
||
async def create_comment(
|
||
self,
|
||
news_id: str,
|
||
content: str,
|
||
session_token: str
|
||
) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
创建评论
|
||
:param news_id: 新闻 ID
|
||
:param content: 评论内容
|
||
:param session_token: 会话 Token
|
||
:return: 评论结果
|
||
"""
|
||
try:
|
||
async with self._get_client(session_token) as client:
|
||
response = await client.post(
|
||
"/api/comment/create", # 实际接口路径需根据 doc.html 调整
|
||
json={"newsId": news_id, "content": content}
|
||
)
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
logger.info(f"Comment created for news: {news_id}")
|
||
return data
|
||
else:
|
||
logger.error(f"Create comment failed: {response.status_code} - {response.text}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Create comment error: {e}")
|
||
return None
|
||
|
||
async def create_reply(
|
||
self,
|
||
comment_id: str,
|
||
content: str,
|
||
session_token: str
|
||
) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
创建回复
|
||
:param comment_id: 评论 ID
|
||
:param content: 回复内容
|
||
:param session_token: 会话 Token
|
||
:return: 回复结果
|
||
"""
|
||
try:
|
||
async with self._get_client(session_token) as client:
|
||
response = await client.post(
|
||
"/api/reply/create", # 实际接口路径需根据 doc.html 调整
|
||
json={"commentId": comment_id, "content": content}
|
||
)
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
logger.info(f"Reply created for comment: {comment_id}")
|
||
return data
|
||
else:
|
||
logger.error(f"Create reply failed: {response.status_code}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Create reply error: {e}")
|
||
return None
|
||
|
||
async def like_comment(
|
||
self,
|
||
comment_id: str,
|
||
session_token: str
|
||
) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
点赞评论
|
||
:param comment_id: 评论 ID
|
||
:param session_token: 会话 Token
|
||
:return: 点赞结果
|
||
"""
|
||
try:
|
||
async with self._get_client(session_token) as client:
|
||
response = await client.post(f"/api/comment/{comment_id}/like")
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
logger.info(f"Comment liked: {comment_id}")
|
||
return data
|
||
else:
|
||
logger.error(f"Like comment failed: {response.status_code}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Like comment error: {e}")
|
||
return None
|
||
|
||
async def favorite_news(
|
||
self,
|
||
news_id: str,
|
||
session_token: str
|
||
) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
收藏新闻
|
||
:param news_id: 新闻 ID
|
||
:param session_token: 会话 Token
|
||
:return: 收藏结果
|
||
"""
|
||
try:
|
||
async with self._get_client(session_token) as client:
|
||
response = await client.post(f"/api/news/{news_id}/favorite")
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
logger.info(f"News favorited: {news_id}")
|
||
return data
|
||
else:
|
||
logger.error(f"Favorite news failed: {response.status_code}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Favorite news error: {e}")
|
||
return None
|
||
|
||
async def share_news(
|
||
self,
|
||
news_id: str,
|
||
session_token: str
|
||
) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
转发新闻
|
||
:param news_id: 新闻 ID
|
||
:param session_token: 会话 Token
|
||
:return: 转发结果
|
||
"""
|
||
try:
|
||
async with self._get_client(session_token) as client:
|
||
response = await client.post(f"/api/news/{news_id}/share")
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
logger.info(f"News shared: {news_id}")
|
||
return data
|
||
else:
|
||
logger.error(f"Share news failed: {response.status_code}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Share news error: {e}")
|
||
return None
|
||
|
||
async def get_comments(
|
||
self,
|
||
news_id: str,
|
||
page: int = 1,
|
||
page_size: int = 20
|
||
) -> Optional[List[Dict[str, Any]]]:
|
||
"""
|
||
获取新闻评论列表
|
||
:param news_id: 新闻 ID
|
||
:param page: 页码
|
||
:param page_size: 每页数量
|
||
:return: 评论列表
|
||
"""
|
||
try:
|
||
async with self._get_client() as client:
|
||
params = {"page": page, "pageSize": page_size}
|
||
response = await client.get(
|
||
f"/api/news/{news_id}/comments",
|
||
params=params
|
||
)
|
||
|
||
if response.status_code == 200:
|
||
data = response.json()
|
||
return data.get("data", [])
|
||
else:
|
||
logger.error(f"Get comments failed: {response.status_code}")
|
||
return None
|
||
except Exception as e:
|
||
logger.error(f"Get comments error: {e}")
|
||
return None
|
||
|
||
|
||
# 创建全局服务实例
|
||
huihui_api_service = HuihuiAPIService()
|