reddit_hack / api /analytics.py
GitHub Actions Bot
Deploy backend from GitHub Actions
7f99b5c
Raw
History Blame Contribute Delete
4.49 kB
import logging
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import select, func
from sqlmodel.ext.asyncio.session import AsyncSession
from db import get_session
from models import ModerationLog, SubredditAnalytics
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/analytics", tags=["analytics"])
@router.get("/subreddit", response_model=SubredditAnalytics)
async def get_subreddit_analytics(
subreddit: str,
db: AsyncSession = Depends(get_session)
):
"""Retrieves lightweight moderation analytics for a subreddit."""
try:
# Helper queries
# 1. Total items processed (flagged)
stmt_total = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
)
total_items = (await db.execute(stmt_total)).scalar() or 0
# 2. Pending queue count (currently flagged)
stmt_pending = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
.where(ModerationLog.status == "flagged")
)
pending_count = (await db.execute(stmt_pending)).scalar() or 0
# 3. Resolved count
stmt_resolved = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
.where(ModerationLog.status.in_(["approved", "removed", "ignored", "warned"]))
.where(ModerationLog.resolved_at.isnot(None))
)
resolved_count = (await db.execute(stmt_resolved)).scalar() or 0
# 4. Toxicity count
stmt_toxic = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
.where(ModerationLog.is_toxic == True)
)
toxic_count = (await db.execute(stmt_toxic)).scalar() or 0
# 5. Spam count
stmt_spam = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
.where(ModerationLog.is_spam == True)
)
spam_count = (await db.execute(stmt_spam)).scalar() or 0
# 6. Escalation count
stmt_escalation = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
.where(ModerationLog.is_escalation == True)
)
escalation_count = (await db.execute(stmt_escalation)).scalar() or 0
# 7. Duplicate count
stmt_dup = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
.where(ModerationLog.is_duplicate == True)
)
dup_count = (await db.execute(stmt_dup)).scalar() or 0
# 8. False positive count (feedback_correct == False)
stmt_fp = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
.where(ModerationLog.feedback_correct == False)
)
fp_count = (await db.execute(stmt_fp)).scalar() or 0
# 9. Count of items with feedback given
stmt_feedback_total = (
select(func.count(ModerationLog.id))
.where(ModerationLog.subreddit == subreddit)
.where(ModerationLog.feedback_correct.isnot(None))
)
feedback_total = (await db.execute(stmt_feedback_total)).scalar() or 0
# Rates calculations
denom = total_items if total_items > 0 else 1
toxicity_rate = toxic_count / denom
spam_rate = spam_count / denom
escalation_rate = escalation_count / denom
duplicate_rate = dup_count / denom
fp_denom = feedback_total if feedback_total > 0 else 1
false_positive_rate = fp_count / fp_denom
return SubredditAnalytics(
subreddit=subreddit,
total_flagged=total_items,
pending_count=pending_count,
resolved_count=resolved_count,
toxicity_rate=round(toxicity_rate, 4),
spam_rate=round(spam_rate, 4),
escalation_rate=round(escalation_rate, 4),
duplicate_rate=round(duplicate_rate, 4),
false_positive_rate=round(false_positive_rate, 4)
)
except Exception as e:
logger.error(f"Error fetching analytics for subreddit {subreddit}: {e}")
raise HTTPException(status_code=500, detail=str(e))