2026-01-31 02:59:49 +08:00
|
|
|
|
"""
|
2026-04-06 16:47:36 +07:00
|
|
|
|
Community APIs - indicator community interface
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
2026-04-06 16:47:36 +07:00
|
|
|
|
REST API that provides indicator markets, buying, commenting, and more.
|
2026-01-31 02:59:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
2026-04-09 14:30:51 +07:00
|
|
|
|
from flask import Blueprint, g, jsonify, request
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
2026-04-09 14:30:51 +07:00
|
|
|
|
from app.services.community_service import get_community_service
|
2026-01-31 02:59:49 +08:00
|
|
|
|
from app.utils.auth import login_required
|
|
|
|
|
|
from app.utils.logger import get_logger
|
|
|
|
|
|
|
|
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
community_bp = Blueprint("community", __name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==========================================
|
2026-04-06 16:47:36 +07:00
|
|
|
|
# indicator market
|
2026-01-31 02:59:49 +08:00
|
|
|
|
# ==========================================
|
|
|
|
|
|
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
@community_bp.route("/indicators", methods=["GET"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def get_market_indicators():
|
|
|
|
|
|
"""
|
2026-04-06 16:47:36 +07:00
|
|
|
|
Get a list of market indicators
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
Query params:
|
2026-04-06 16:47:36 +07:00
|
|
|
|
page: page number (default 1)
|
|
|
|
|
|
page_size: Number of pages per page (default 12)
|
|
|
|
|
|
keyword: search keyword
|
|
|
|
|
|
pricing_type: 'free' / 'paid' / empty (all)
|
2026-01-31 02:59:49 +08:00
|
|
|
|
sort_by: 'newest' / 'hot' / 'price_asc' / 'price_desc' / 'rating'
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
page = int(request.args.get("page", 1))
|
|
|
|
|
|
page_size = int(request.args.get("page_size", 12))
|
|
|
|
|
|
keyword = request.args.get("keyword", "").strip()
|
|
|
|
|
|
pricing_type = request.args.get("pricing_type", "").strip() or None
|
|
|
|
|
|
sort_by = request.args.get("sort_by", "newest").strip()
|
|
|
|
|
|
|
2026-04-06 16:47:36 +07:00
|
|
|
|
# Limit the number of pages per page
|
2026-01-31 02:59:49 +08:00
|
|
|
|
page_size = min(max(page_size, 1), 50)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
|
|
|
|
|
result = service.get_market_indicators(
|
|
|
|
|
|
page=page,
|
|
|
|
|
|
page_size=page_size,
|
|
|
|
|
|
keyword=keyword if keyword else None,
|
|
|
|
|
|
pricing_type=pricing_type,
|
|
|
|
|
|
sort_by=sort_by,
|
2026-04-09 14:30:51 +07:00
|
|
|
|
user_id=g.user_id,
|
2026-01-31 02:59:49 +08:00
|
|
|
|
)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
|
|
|
|
|
return jsonify({"code": 1, "msg": "success", "data": result})
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"get_market_indicators failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/indicators/<int:indicator_id>", methods=["GET"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def get_indicator_detail(indicator_id: int):
|
2026-04-06 16:47:36 +07:00
|
|
|
|
"""Get indicator details"""
|
2026-01-31 02:59:49 +08:00
|
|
|
|
try:
|
|
|
|
|
|
service = get_community_service()
|
|
|
|
|
|
result = service.get_indicator_detail(indicator_id, user_id=g.user_id)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
if not result:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": "indicator_not_found", "data": None}), 404
|
|
|
|
|
|
|
|
|
|
|
|
return jsonify({"code": 1, "msg": "success", "data": result})
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"get_indicator_detail failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==========================================
|
2026-04-06 16:47:36 +07:00
|
|
|
|
# Purchase function
|
2026-01-31 02:59:49 +08:00
|
|
|
|
# ==========================================
|
|
|
|
|
|
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
@community_bp.route("/indicators/<int:indicator_id>/purchase", methods=["POST"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def purchase_indicator(indicator_id: int):
|
|
|
|
|
|
"""
|
2026-04-06 16:47:36 +07:00
|
|
|
|
buy indicator
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-04-06 16:47:36 +07:00
|
|
|
|
will automatically:
|
|
|
|
|
|
1. Check whether the points are sufficient
|
|
|
|
|
|
2. Deduct buyer points and increase seller points
|
|
|
|
|
|
3. Create purchase records
|
|
|
|
|
|
4. Copy the indicator to the buyer’s account
|
2026-01-31 02:59:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
service = get_community_service()
|
2026-04-09 14:30:51 +07:00
|
|
|
|
success, message, data = service.purchase_indicator(buyer_id=g.user_id, indicator_id=indicator_id)
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
if success:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 1, "msg": message, "data": data})
|
2026-01-31 02:59:49 +08:00
|
|
|
|
else:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": message, "data": data}), 400
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"purchase_indicator failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/my-purchases", methods=["GET"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def get_my_purchases():
|
2026-04-06 16:47:36 +07:00
|
|
|
|
"""Get a list of indicators I purchased"""
|
2026-01-31 02:59:49 +08:00
|
|
|
|
try:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
page = int(request.args.get("page", 1))
|
|
|
|
|
|
page_size = int(request.args.get("page_size", 20))
|
2026-01-31 02:59:49 +08:00
|
|
|
|
page_size = min(max(page_size, 1), 50)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
2026-04-09 14:30:51 +07:00
|
|
|
|
result = service.get_my_purchases(user_id=g.user_id, page=page, page_size=page_size)
|
|
|
|
|
|
|
|
|
|
|
|
return jsonify({"code": 1, "msg": "success", "data": result})
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"get_my_purchases failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==========================================
|
2026-04-06 16:47:36 +07:00
|
|
|
|
# Comment function
|
2026-01-31 02:59:49 +08:00
|
|
|
|
# ==========================================
|
|
|
|
|
|
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
@community_bp.route("/indicators/<int:indicator_id>/comments", methods=["GET"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def get_comments(indicator_id: int):
|
2026-04-06 16:47:36 +07:00
|
|
|
|
"""Get a list of indicator comments"""
|
2026-01-31 02:59:49 +08:00
|
|
|
|
try:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
page = int(request.args.get("page", 1))
|
|
|
|
|
|
page_size = int(request.args.get("page_size", 20))
|
2026-01-31 02:59:49 +08:00
|
|
|
|
page_size = min(max(page_size, 1), 50)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
2026-04-09 14:30:51 +07:00
|
|
|
|
result = service.get_comments(indicator_id=indicator_id, page=page, page_size=page_size)
|
|
|
|
|
|
|
|
|
|
|
|
return jsonify({"code": 1, "msg": "success", "data": result})
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"get_comments failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/indicators/<int:indicator_id>/comments", methods=["POST"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def add_comment(indicator_id: int):
|
|
|
|
|
|
"""
|
2026-04-06 16:47:36 +07:00
|
|
|
|
Add comment
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
Request body:
|
2026-04-06 16:47:36 +07:00
|
|
|
|
rating: 1-5 star rating
|
|
|
|
|
|
content: Comment content (optional, up to 500 words)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-04-06 16:47:36 +07:00
|
|
|
|
Note: Only users who have purchased can comment, and they can only comment once
|
2026-01-31 02:59:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
data = request.get_json() or {}
|
2026-04-09 14:30:51 +07:00
|
|
|
|
rating = int(data.get("rating", 5))
|
|
|
|
|
|
content = (data.get("content") or "").strip()
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
|
|
|
|
|
success, message, result = service.add_comment(
|
2026-04-09 14:30:51 +07:00
|
|
|
|
user_id=g.user_id, indicator_id=indicator_id, rating=rating, content=content
|
2026-01-31 02:59:49 +08:00
|
|
|
|
)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
if success:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 1, "msg": message, "data": result})
|
2026-01-31 02:59:49 +08:00
|
|
|
|
else:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": message, "data": result}), 400
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"add_comment failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/indicators/<int:indicator_id>/comments/<int:comment_id>", methods=["PUT"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def update_comment(indicator_id: int, comment_id: int):
|
|
|
|
|
|
"""
|
2026-04-06 16:47:36 +07:00
|
|
|
|
Update comments (you can only modify your own comments)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
Request body:
|
2026-04-06 16:47:36 +07:00
|
|
|
|
rating: 1-5 star rating
|
|
|
|
|
|
content: Comment content (up to 500 words)
|
2026-01-31 02:59:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
data = request.get_json() or {}
|
2026-04-09 14:30:51 +07:00
|
|
|
|
rating = int(data.get("rating", 5))
|
|
|
|
|
|
content = (data.get("content") or "").strip()
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
|
|
|
|
|
success, message, result = service.update_comment(
|
2026-04-09 14:30:51 +07:00
|
|
|
|
user_id=g.user_id, comment_id=comment_id, indicator_id=indicator_id, rating=rating, content=content
|
2026-01-31 02:59:49 +08:00
|
|
|
|
)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
if success:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 1, "msg": message, "data": result})
|
2026-01-31 02:59:49 +08:00
|
|
|
|
else:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": message, "data": result}), 400
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"update_comment failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/indicators/<int:indicator_id>/my-comment", methods=["GET"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def get_my_comment(indicator_id: int):
|
2026-04-06 16:47:36 +07:00
|
|
|
|
"""Get the current user's comments on the specified indicator (for editing)"""
|
2026-01-31 02:59:49 +08:00
|
|
|
|
try:
|
|
|
|
|
|
service = get_community_service()
|
2026-04-09 14:30:51 +07:00
|
|
|
|
result = service.get_user_comment(user_id=g.user_id, indicator_id=indicator_id)
|
|
|
|
|
|
|
|
|
|
|
|
return jsonify({"code": 1, "msg": "success", "data": result})
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"get_my_comment failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==========================================
|
2026-04-06 16:47:36 +07:00
|
|
|
|
# Real offer performance
|
2026-01-31 02:59:49 +08:00
|
|
|
|
# ==========================================
|
|
|
|
|
|
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
@community_bp.route("/indicators/<int:indicator_id>/performance", methods=["GET"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def get_indicator_performance(indicator_id: int):
|
2026-04-06 16:47:36 +07:00
|
|
|
|
"""Get real performance statistics of indicators"""
|
2026-01-31 02:59:49 +08:00
|
|
|
|
try:
|
|
|
|
|
|
service = get_community_service()
|
|
|
|
|
|
result = service.get_indicator_performance(indicator_id)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
|
|
|
|
|
return jsonify({"code": 1, "msg": "success", "data": result})
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"get_indicator_performance failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==========================================
|
2026-04-06 16:47:36 +07:00
|
|
|
|
# Administrator review function
|
2026-01-31 02:59:49 +08:00
|
|
|
|
# ==========================================
|
|
|
|
|
|
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
def _is_admin():
|
2026-04-06 16:47:36 +07:00
|
|
|
|
"""Check if the current user is an administrator"""
|
2026-04-09 14:30:51 +07:00
|
|
|
|
role = getattr(g, "user_role", None)
|
|
|
|
|
|
return role == "admin"
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/admin/pending-indicators", methods=["GET"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def get_pending_indicators():
|
|
|
|
|
|
"""
|
2026-04-06 16:47:36 +07:00
|
|
|
|
Get the list of indicators to be reviewed (for administrators only)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
Query params:
|
2026-04-06 16:47:36 +07:00
|
|
|
|
page: page number (default 1)
|
|
|
|
|
|
page_size: Number of pages per page (default 20)
|
2026-01-31 02:59:49 +08:00
|
|
|
|
review_status: 'pending' / 'approved' / 'rejected' / 'all'
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
if not _is_admin():
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": "admin_required", "data": None}), 403
|
|
|
|
|
|
|
|
|
|
|
|
page = int(request.args.get("page", 1))
|
|
|
|
|
|
page_size = int(request.args.get("page_size", 20))
|
|
|
|
|
|
review_status = request.args.get("review_status", "pending").strip() or "pending"
|
2026-01-31 02:59:49 +08:00
|
|
|
|
page_size = min(max(page_size, 1), 100)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
2026-04-09 14:30:51 +07:00
|
|
|
|
result = service.get_pending_indicators(page=page, page_size=page_size, review_status=review_status)
|
|
|
|
|
|
|
|
|
|
|
|
return jsonify({"code": 1, "msg": "success", "data": result})
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"get_pending_indicators failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/admin/review-stats", methods=["GET"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def get_review_stats():
|
2026-04-06 16:47:36 +07:00
|
|
|
|
"""Get audit statistics (for administrators only)"""
|
2026-01-31 02:59:49 +08:00
|
|
|
|
try:
|
|
|
|
|
|
if not _is_admin():
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": "admin_required", "data": None}), 403
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
|
|
|
|
|
result = service.get_review_stats()
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
|
|
|
|
|
return jsonify({"code": 1, "msg": "success", "data": result})
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"get_review_stats failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/admin/indicators/<int:indicator_id>/review", methods=["POST"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def review_indicator(indicator_id: int):
|
|
|
|
|
|
"""
|
2026-04-06 16:47:36 +07:00
|
|
|
|
Audit indicators (for administrators only)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
Request body:
|
|
|
|
|
|
action: 'approve' / 'reject'
|
2026-04-06 16:47:36 +07:00
|
|
|
|
note: review notes (optional)
|
2026-01-31 02:59:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
if not _is_admin():
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": "admin_required", "data": None}), 403
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
data = request.get_json() or {}
|
2026-04-09 14:30:51 +07:00
|
|
|
|
action = data.get("action", "").strip()
|
|
|
|
|
|
note = data.get("note", "").strip()
|
|
|
|
|
|
|
|
|
|
|
|
if action not in ("approve", "reject"):
|
|
|
|
|
|
return jsonify({"code": 0, "msg": "invalid_action", "data": None}), 400
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
|
|
|
|
|
success, message = service.review_indicator(
|
2026-04-09 14:30:51 +07:00
|
|
|
|
admin_id=g.user_id, indicator_id=indicator_id, action=action, note=note
|
2026-01-31 02:59:49 +08:00
|
|
|
|
)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
if success:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 1, "msg": message, "data": None})
|
2026-01-31 02:59:49 +08:00
|
|
|
|
else:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": message, "data": None}), 400
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"review_indicator failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/admin/indicators/<int:indicator_id>/unpublish", methods=["POST"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def unpublish_indicator(indicator_id: int):
|
|
|
|
|
|
"""
|
2026-04-06 16:47:36 +07:00
|
|
|
|
Delisting indicator (for administrators only)
|
2026-04-09 14:30:51 +07:00
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
Request body:
|
2026-04-06 16:47:36 +07:00
|
|
|
|
note: Reason for delisting (optional)
|
2026-01-31 02:59:49 +08:00
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
if not _is_admin():
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": "admin_required", "data": None}), 403
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
data = request.get_json() or {}
|
2026-04-09 14:30:51 +07:00
|
|
|
|
note = data.get("note", "").strip()
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
2026-04-09 14:30:51 +07:00
|
|
|
|
success, message = service.unpublish_indicator(admin_id=g.user_id, indicator_id=indicator_id, note=note)
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
if success:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 1, "msg": message, "data": None})
|
2026-01-31 02:59:49 +08:00
|
|
|
|
else:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": message, "data": None}), 400
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"unpublish_indicator failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|
2026-01-31 02:59:49 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@community_bp.route("/admin/indicators/<int:indicator_id>", methods=["DELETE"])
|
|
|
|
|
|
@login_required
|
|
|
|
|
|
def admin_delete_indicator(indicator_id: int):
|
2026-04-06 16:47:36 +07:00
|
|
|
|
"""Delete indicator (only for administrators)"""
|
2026-01-31 02:59:49 +08:00
|
|
|
|
try:
|
|
|
|
|
|
if not _is_admin():
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": "admin_required", "data": None}), 403
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
service = get_community_service()
|
2026-04-09 14:30:51 +07:00
|
|
|
|
success, message = service.admin_delete_indicator(admin_id=g.user_id, indicator_id=indicator_id)
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
if success:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 1, "msg": message, "data": None})
|
2026-01-31 02:59:49 +08:00
|
|
|
|
else:
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": message, "data": None}), 400
|
|
|
|
|
|
|
2026-01-31 02:59:49 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"admin_delete_indicator failed: {e}")
|
2026-04-09 14:30:51 +07:00
|
|
|
|
return jsonify({"code": 0, "msg": str(e), "data": None}), 500
|