88 lines
3.2 KiB
Python
88 lines
3.2 KiB
Python
"""
|
|
Chat REST API: conversations, messages, recall.
|
|
"""
|
|
from flask import Blueprint, request, jsonify
|
|
from flask_jwt_extended import jwt_required, get_jwt_identity
|
|
from app.services.chat_engine import ChatEngineService
|
|
from app.socket_events import broadcast_new_message
|
|
|
|
chat_bp = Blueprint("chat", __name__)
|
|
|
|
|
|
@chat_bp.route("/conversations", methods=["GET"])
|
|
@jwt_required()
|
|
def list_conversations():
|
|
skip = request.args.get("skip", 0, type=int)
|
|
limit = min(request.args.get("limit", 20, type=int), 100)
|
|
user_id = get_jwt_identity()
|
|
convs = ChatEngineService.list_conversations(user_id, skip=skip, limit=limit)
|
|
return jsonify({
|
|
"items": [
|
|
{
|
|
"id": c.id,
|
|
"title": c.title,
|
|
"last_message_at": c.last_message_at.isoformat() if c.last_message_at else None,
|
|
"created_at": c.created_at.isoformat() if c.created_at else None,
|
|
}
|
|
for c in convs
|
|
]
|
|
})
|
|
|
|
|
|
@chat_bp.route("/conversations", methods=["POST"])
|
|
@jwt_required()
|
|
def create_conversation():
|
|
data = request.get_json() or {}
|
|
title = (data.get("title") or "新对话").strip() or "新对话"
|
|
user_id = get_jwt_identity()
|
|
conv = ChatEngineService.get_or_create_conversation(user_id, title=title)
|
|
return jsonify({
|
|
"id": conv.id,
|
|
"title": conv.title,
|
|
"last_message_at": conv.last_message_at.isoformat() if conv.last_message_at else None,
|
|
"created_at": conv.created_at.isoformat() if conv.created_at else None,
|
|
}), 201
|
|
|
|
|
|
@chat_bp.route("/conversations/<conversation_id>/messages", methods=["GET"])
|
|
@jwt_required()
|
|
def get_messages(conversation_id):
|
|
before_id = request.args.get("before_id")
|
|
limit = min(request.args.get("limit", 50, type=int), 100)
|
|
user_id = get_jwt_identity()
|
|
messages = ChatEngineService.get_messages(conversation_id, user_id, before_id=before_id, limit=limit)
|
|
return jsonify({"items": [m.to_dict() for m in reversed(messages)]})
|
|
|
|
|
|
@chat_bp.route("/conversations/<conversation_id>/messages", methods=["POST"])
|
|
@jwt_required()
|
|
def send_message(conversation_id):
|
|
data = request.get_json() or {}
|
|
content = (data.get("content") or "").strip()
|
|
content_type = data.get("content_type") or "text"
|
|
attachment_url = data.get("attachment_url")
|
|
attachment_name = data.get("attachment_name")
|
|
if not content and not attachment_url:
|
|
return jsonify({"error": "content or attachment required"}), 400
|
|
user_id = get_jwt_identity()
|
|
msg = ChatEngineService.send_message(
|
|
conversation_id, user_id, content or "(附件)",
|
|
content_type=content_type,
|
|
attachment_url=attachment_url,
|
|
attachment_name=attachment_name,
|
|
)
|
|
if not msg:
|
|
return jsonify({"error": "Conversation not found or access denied"}), 404
|
|
broadcast_new_message(msg)
|
|
return jsonify(msg.to_dict()), 201
|
|
|
|
|
|
@chat_bp.route("/messages/<message_id>/recall", methods=["POST"])
|
|
@jwt_required()
|
|
def recall_message(message_id):
|
|
user_id = get_jwt_identity()
|
|
ok = ChatEngineService.recall_message(message_id, user_id)
|
|
if not ok:
|
|
return jsonify({"error": "Message not found or recall not allowed"}), 400
|
|
return jsonify({"status": "recalled"})
|