- 虚拟用户管理(昵称/头像/性别/简介/邮箱同步到目标平台) - AI互动调度(点赞/收藏/评论/转发) - 日志时间改为北京时间 - 评论达上限后继续执行点赞收藏转发 - 一键登出全部功能 - 浅色主题UI
116 lines
3.9 KiB
Python
116 lines
3.9 KiB
Python
"""系统设置接口"""
|
||
from fastapi import APIRouter, Depends
|
||
from sqlalchemy import select, update as sql_update
|
||
from app.core.database import get_db
|
||
from app.schemas import ApiResponse
|
||
from app.models import SystemConfig
|
||
|
||
router = APIRouter()
|
||
|
||
|
||
@router.get("/configs")
|
||
async def get_configs(db=Depends(get_db)):
|
||
result = await db.execute(select(SystemConfig).order_by(SystemConfig.config_key))
|
||
configs = result.scalars().all()
|
||
data = {c.config_key: {"value": c.config_value, "type": c.config_type, "desc": c.description}
|
||
for c in configs}
|
||
return ApiResponse(data=data)
|
||
|
||
|
||
@router.put("/configs")
|
||
async def update_configs(body: dict, db=Depends(get_db)):
|
||
"""批量更新配置"""
|
||
for key, value in body.items():
|
||
result = await db.execute(select(SystemConfig).where(SystemConfig.config_key == key))
|
||
cfg = result.scalar_one_or_none()
|
||
if cfg:
|
||
cfg.config_value = str(value)
|
||
else:
|
||
db.add(SystemConfig(config_key=key, config_value=str(value)))
|
||
await db.commit()
|
||
return ApiResponse(message="配置已保存")
|
||
|
||
|
||
@router.post("/scheduler/toggle")
|
||
async def toggle_scheduler(body: dict, db=Depends(get_db)):
|
||
enabled = body.get("enabled", True)
|
||
result = await db.execute(select(SystemConfig).where(SystemConfig.config_key == "scheduler_enabled"))
|
||
cfg = result.scalar_one_or_none()
|
||
if cfg:
|
||
cfg.config_value = "true" if enabled else "false"
|
||
await db.commit()
|
||
return ApiResponse(message=f"调度器已{'启用' if enabled else '暂停'}")
|
||
|
||
|
||
@router.post("/sessions/reset-all")
|
||
async def reset_all_sessions(db=Depends(get_db)):
|
||
"""重置所有用户会话"""
|
||
from app.models import VirtualUser
|
||
await db.execute(
|
||
sql_update(VirtualUser).values(status=0, session_token=None, session_expires_at=None)
|
||
)
|
||
await db.commit()
|
||
return ApiResponse(message="所有会话已重置")
|
||
|
||
|
||
@router.post("/login/diagnose")
|
||
async def diagnose_login(body: dict, db=Depends(get_db)):
|
||
"""
|
||
诊断登录接口原始响应 - 临时调试用
|
||
传入: {"username": "xxx", "password": "xxx"}
|
||
"""
|
||
import httpx, hashlib, uuid
|
||
from datetime import datetime
|
||
from app.services.news_service import news_service
|
||
|
||
cfg = await news_service._client(db)
|
||
auth = await news_service._auth_url(db)
|
||
|
||
username = body.get("username", "")
|
||
password = body.get("password", "")
|
||
|
||
# 构建 formData(与真实登录完全一致)
|
||
extra = {
|
||
"username": username,
|
||
"password": password,
|
||
"loginType": "password",
|
||
"grantType": "password",
|
||
"isRegister": "false",
|
||
}
|
||
if cfg.get("clientCode"):
|
||
extra["clientCode"] = cfg["clientCode"]
|
||
|
||
form = news_service._build_form(extra, cfg)
|
||
|
||
try:
|
||
async with httpx.AsyncClient(timeout=15) as c:
|
||
resp = await c.post(f"{auth}/open/login/token", data=form)
|
||
|
||
# 返回完整诊断信息
|
||
try:
|
||
resp_json = resp.json()
|
||
except Exception:
|
||
resp_json = None
|
||
|
||
return ApiResponse(data={
|
||
"status_code": resp.status_code,
|
||
"response_text": resp.text[:2000],
|
||
"response_json": resp_json,
|
||
"request_url": f"{auth}/open/login/token",
|
||
"request_form": {k: v if k not in ("password","accessSecret") else "***" for k, v in form.items()},
|
||
"content_type": resp.headers.get("content-type", ""),
|
||
})
|
||
except Exception as e:
|
||
return ApiResponse(code=500, message=str(e), data={"error": str(e)})
|
||
|
||
|
||
@router.post("/interaction/run-now")
|
||
async def run_interaction_now(db=Depends(get_db)):
|
||
"""立即触发一次互动任务(不受时间段限制)"""
|
||
from app.services.scheduler import scheduler_service
|
||
try:
|
||
result = await scheduler_service.run_once_now(db)
|
||
return ApiResponse(data=result, message="互动任务已触发")
|
||
except Exception as e:
|
||
return ApiResponse(code=500, message=f"触发失败: {e}")
|