Spaces:
Sleeping
Sleeping
| import logging | |
| from datetime import datetime, timezone | |
| from typing import List, Optional | |
| from fastapi import APIRouter, Depends, HTTPException, Query | |
| from sqlmodel import select, desc | |
| from sqlmodel.ext.asyncio.session import AsyncSession | |
| from db import get_session | |
| from models import ( | |
| ContentSubmission, | |
| ResolutionRequest, | |
| FeedbackRequest, | |
| ModerationLog, | |
| QueueResponse | |
| ) | |
| from moderation.detector import ModerationDetector | |
| logger = logging.getLogger(__name__) | |
| router = APIRouter(prefix="/api/moderation", tags=["moderation"]) | |
| async def check_submission( | |
| submission: ContentSubmission, | |
| db: AsyncSession = Depends(get_session) | |
| ): | |
| """Checks a post or comment submission, runs AI moderation, and stores logs.""" | |
| try: | |
| # Check if already processed | |
| existing = await db.get(ModerationLog, submission.id) | |
| if existing: | |
| # If already processed, return existing log (or re-evaluate) | |
| return existing | |
| # Run detection pipeline | |
| log = await ModerationDetector.analyze_submission(db, submission) | |
| # Add to database | |
| db.add(log) | |
| await db.commit() | |
| await db.refresh(log) | |
| return log | |
| except Exception as e: | |
| logger.error(f"Error checking submission {submission.id}: {e}") | |
| raise HTTPException(status_code=500, detail=f"Moderation check failed: {str(e)}") | |
| async def get_moderation_queue( | |
| subreddit: str, | |
| db: AsyncSession = Depends(get_session) | |
| ): | |
| """Fetches the prioritized moderation queue for a specific subreddit.""" | |
| try: | |
| # Select flagged items that have not been resolved | |
| stmt = ( | |
| select(ModerationLog) | |
| .where(ModerationLog.subreddit == subreddit) | |
| .where(ModerationLog.status == "flagged") | |
| ) | |
| result = await db.execute(stmt) | |
| items = result.scalars().all() | |
| # Priority mapping for sorting | |
| priority_map = {"high": 3, "medium": 2, "low": 1} | |
| # Sort by priority level (high -> medium -> low), then by created_at desc | |
| sorted_items = sorted( | |
| items, | |
| key=lambda x: (priority_map.get(x.priority, 0), x.created_at), | |
| reverse=True | |
| ) | |
| return sorted_items | |
| except Exception as e: | |
| logger.error(f"Error fetching queue for subreddit {subreddit}: {e}") | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| async def resolve_item( | |
| request: ResolutionRequest, | |
| db: AsyncSession = Depends(get_session) | |
| ): | |
| """Resolves a flagged queue item (approves, removes, ignores, warns).""" | |
| try: | |
| log = await db.get(ModerationLog, request.id) | |
| if not log: | |
| raise HTTPException(status_code=404, detail="Moderation log item not found") | |
| # Map actions to log statuses | |
| action_map = { | |
| "approve": "approved", | |
| "remove": "removed", | |
| "ignore": "ignored", | |
| "warn": "warned" | |
| } | |
| new_status = action_map.get(request.action.lower()) | |
| if not new_status: | |
| raise HTTPException(status_code=400, detail=f"Invalid resolution action: {request.action}") | |
| log.status = new_status | |
| log.resolved_at = datetime.now(timezone.utc) | |
| log.resolved_by = request.moderator | |
| db.add(log) | |
| await db.commit() | |
| logger.info(f"Subreddit item {request.id} resolved as '{new_status}' by mod {request.moderator}") | |
| return {"status": "success", "resolved_id": request.id, "new_status": new_status} | |
| except HTTPException: | |
| raise | |
| except Exception as e: | |
| logger.error(f"Error resolving item {request.id}: {e}") | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| async def submit_feedback( | |
| request: FeedbackRequest, | |
| db: AsyncSession = Depends(get_session) | |
| ): | |
| """Allows moderators to flag false positives and rate AI accuracy.""" | |
| try: | |
| log = await db.get(ModerationLog, request.id) | |
| if not log: | |
| raise HTTPException(status_code=404, detail="Moderation log item not found") | |
| log.feedback_correct = request.is_correct | |
| log.feedback_reason = request.reason | |
| db.add(log) | |
| await db.commit() | |
| logger.info(f"Feedback logged for item {request.id}. Correctness: {request.is_correct}") | |
| return {"status": "success", "item_id": request.id} | |
| except HTTPException: | |
| raise | |
| except Exception as e: | |
| logger.error(f"Error saving feedback for item {request.id}: {e}") | |
| raise HTTPException(status_code=500, detail=str(e)) | |