feat: complete huihui square avatar workflows
This commit is contained in:
@@ -52,20 +52,45 @@ async def retry_interaction(record_id: int, db=Depends(get_db)):
|
||||
if not user or user.status != 2:
|
||||
raise HTTPException(status_code=400, detail="用户未登录,无法重试")
|
||||
|
||||
success, err = False, "未知类型"
|
||||
success, err, platform_record_id = False, "未知类型", ""
|
||||
if record.interact_type == "comment" and record.content:
|
||||
success, err = await news_service.post_comment(db, user, record.article_id, record.article_title or "", record.content)
|
||||
success, err, platform_record_id = await news_service.post_comment_with_record_id(
|
||||
db, user, record.article_id, record.article_title or "", record.content
|
||||
)
|
||||
elif record.interact_type == "like":
|
||||
success, err = await news_service.like_news(db, user, record.article_id, org_id="", title=record.article_title or "")
|
||||
elif record.interact_type == "collect":
|
||||
success, err = await news_service.collect_news(db, user, record.article_id, title=record.article_title or "")
|
||||
elif record.interact_type == "forward":
|
||||
success, err = await news_service.forward_news(db, user, record.article_id)
|
||||
elif record.interact_type == "reply" and record.content:
|
||||
parent_comment = None
|
||||
if record.parent_comment_id:
|
||||
comments = await news_service.get_comments(db, user, record.article_id or "")
|
||||
parent_comment = next(
|
||||
(
|
||||
c for c in comments
|
||||
if str(c.get("id") or c.get("commentId") or "") == str(record.parent_comment_id)
|
||||
),
|
||||
None,
|
||||
)
|
||||
if not parent_comment:
|
||||
success, err, platform_record_id = False, "未找到被回复的原评论,无法重试回复", ""
|
||||
else:
|
||||
success, err, platform_record_id = await news_service.post_reply_with_record_id(
|
||||
db, user,
|
||||
record.article_id or "",
|
||||
record.parent_comment_id or "",
|
||||
record.content,
|
||||
parent_comment=parent_comment,
|
||||
article_title=record.article_title or "",
|
||||
)
|
||||
|
||||
await db.execute(
|
||||
update(InteractionRecord).where(InteractionRecord.id == record_id).values(
|
||||
status=1 if success else 2,
|
||||
error_msg=None if success else err,
|
||||
platform_record_id=platform_record_id or record.platform_record_id,
|
||||
retry_count=record.retry_count + 1,
|
||||
)
|
||||
)
|
||||
@@ -147,15 +172,69 @@ async def cancel_interaction(record_id: int, db=Depends(get_db)):
|
||||
news_id=record.article_id or "",
|
||||
title=record.article_title or "",
|
||||
)
|
||||
elif record.interact_type in ("comment", "reply"):
|
||||
elif record.interact_type == "comment":
|
||||
comment_id = record.platform_record_id or ""
|
||||
if not comment_id:
|
||||
return ApiResponse(code=400, message="缺少评论ID,无法删除")
|
||||
comment_id, comment_count = await news_service.find_comment_id(
|
||||
db, user,
|
||||
news_id=record.article_id or "",
|
||||
content=record.content or "",
|
||||
)
|
||||
if comment_id:
|
||||
await db.execute(
|
||||
update(InteractionRecord).where(InteractionRecord.id == record_id).values(
|
||||
platform_record_id=comment_id
|
||||
)
|
||||
)
|
||||
await db.commit()
|
||||
elif comment_count == 0:
|
||||
await db.execute(
|
||||
update(InteractionRecord).where(InteractionRecord.id == record_id).values(
|
||||
status=3,
|
||||
error_msg="平台未查询到评论,已标记取消",
|
||||
)
|
||||
)
|
||||
await db.commit()
|
||||
return ApiResponse(message="平台未查询到评论,已标记取消")
|
||||
else:
|
||||
return ApiResponse(code=400, message="缺少评论ID,且未能从平台评论列表反查到该评论")
|
||||
ok, err = await news_service.cancel_comment(
|
||||
db, user,
|
||||
news_id=record.article_id or "",
|
||||
comment_id=comment_id,
|
||||
)
|
||||
elif record.interact_type == "reply":
|
||||
reply_id = record.platform_record_id or ""
|
||||
if not reply_id:
|
||||
reply_id, reply_count = await news_service.find_reply_id(
|
||||
db, user,
|
||||
news_id=record.article_id or "",
|
||||
content=record.content or "",
|
||||
parent_comment_id=record.parent_comment_id or "",
|
||||
)
|
||||
if reply_id:
|
||||
await db.execute(
|
||||
update(InteractionRecord).where(InteractionRecord.id == record_id).values(
|
||||
platform_record_id=reply_id
|
||||
)
|
||||
)
|
||||
await db.commit()
|
||||
elif reply_count == 0:
|
||||
await db.execute(
|
||||
update(InteractionRecord).where(InteractionRecord.id == record_id).values(
|
||||
status=3,
|
||||
error_msg="平台未查询到回复,已标记取消",
|
||||
)
|
||||
)
|
||||
await db.commit()
|
||||
return ApiResponse(message="平台未查询到回复,已标记取消")
|
||||
else:
|
||||
return ApiResponse(code=400, message="缺少回复ID,且未能从平台回复列表反查到该回复")
|
||||
ok, err = await news_service.cancel_reply(
|
||||
db, user,
|
||||
news_id=record.article_id or "",
|
||||
reply_id=reply_id,
|
||||
)
|
||||
|
||||
if ok:
|
||||
# 更新状态为手动取消(status=3)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
"""虚拟用户管理接口"""
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
import uuid
|
||||
import mimetypes
|
||||
from fastapi import APIRouter, Depends, Query, UploadFile, File, HTTPException
|
||||
from fastapi.responses import StreamingResponse
|
||||
import io
|
||||
@@ -9,6 +12,21 @@ from app.schemas import ApiResponse, UserCreateRequest, UserUpdateRequest, UserB
|
||||
from app.services.user_service import user_service
|
||||
|
||||
router = APIRouter()
|
||||
_UPLOADS_DIR = Path(__file__).resolve().parents[2] / "uploads" / "avatars"
|
||||
_UPLOADS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
async def _save_local_avatar(file_bytes: bytes, filename: str, content_type: str | None) -> str:
|
||||
ext = Path(filename or "").suffix.lower()
|
||||
if ext not in {".jpg", ".jpeg", ".png", ".gif", ".webp"}:
|
||||
guessed_ext = mimetypes.guess_extension(content_type or "") or ".jpg"
|
||||
ext = ".jpg" if guessed_ext == ".jpe" else guessed_ext
|
||||
if ext not in {".jpg", ".jpeg", ".png", ".gif", ".webp"}:
|
||||
ext = ".jpg"
|
||||
|
||||
target = _UPLOADS_DIR / f"{uuid.uuid4().hex}{ext}"
|
||||
target.write_bytes(file_bytes)
|
||||
return f"/api/uploads/avatars/{target.name}"
|
||||
|
||||
|
||||
@router.get("")
|
||||
@@ -268,13 +286,20 @@ async def sync_all_profiles(db=Depends(get_db)):
|
||||
sess = await get_session(uid)
|
||||
if not sess:
|
||||
return False
|
||||
ur = await s.execute(select(_VU).where(_VU.id == uid))
|
||||
user = ur.scalar_one_or_none()
|
||||
if not user:
|
||||
return False
|
||||
platform_uid = sess.get("platform_uid", "")
|
||||
# 登录成功时 session 里已存有用户信息
|
||||
vals = {}
|
||||
if platform_uid: vals["platform_uid"] = platform_uid
|
||||
# session 里的字段(登录时写入)
|
||||
if sess.get("nickname"): vals["nickname"] = sess["nickname"]
|
||||
if sess.get("real_name"): vals["real_name"] = sess["real_name"]
|
||||
sync_nickname = sess.get("nickname", "")
|
||||
sync_real_name = sess.get("real_name", "")
|
||||
resolved_nickname = news_service._resolve_synced_nickname(user, sync_nickname, sync_real_name)
|
||||
if resolved_nickname: vals["nickname"] = resolved_nickname
|
||||
if sync_real_name: vals["real_name"] = sync_real_name
|
||||
if sess.get("sex"): vals["sex"] = int(sess["sex"])
|
||||
if sess.get("avatar"): vals["avatar_url"] = sess["avatar"]
|
||||
if vals:
|
||||
@@ -327,9 +352,8 @@ async def upload_avatar(
|
||||
else:
|
||||
return ApiResponse(code=500, message=f"头像上传到平台失败: {result}")
|
||||
else:
|
||||
# 仅本地存储(转 base64 或存储到本地)
|
||||
import base64
|
||||
avatar_url = f"data:{file.content_type};base64,{base64.b64encode(file_bytes).decode()}"
|
||||
# 未登录用户本地落盘,避免 base64 超过 avatar_url 字段长度
|
||||
avatar_url = await _save_local_avatar(file_bytes, file.filename or "", file.content_type)
|
||||
|
||||
# 更新数据库
|
||||
await db.execute(update(_VU).where(_VU.id == user_id).values(avatar_url=avatar_url))
|
||||
|
||||
Reference in New Issue
Block a user