diff --git a/app/analyzer/db.py b/app/analyzer/db.py index 0112949..eaf6c2b 100644 --- a/app/analyzer/db.py +++ b/app/analyzer/db.py @@ -57,11 +57,11 @@ class AnalyzerDB: Skips boosts (reblogs) and statuses with empty content. """ query = """ - SELECT s.id, s.content, s.account_id + SELECT s.id, s.content, s.account_db_id FROM statuses s LEFT JOIN toxicity_scores ts ON ts.status_id = s.id WHERE ts.status_id IS NULL - AND s.reblog_of_id IS NULL + AND s.status_type != 'reblog' AND s.content IS NOT NULL AND s.content != '' ORDER BY s.created_at DESC diff --git a/app/templates/analysis.html b/app/templates/analysis.html new file mode 100644 index 0000000..1f8da90 --- /dev/null +++ b/app/templates/analysis.html @@ -0,0 +1,734 @@ +{% extends "base.html" %} + +{% block title %}Toxicity Analysis Dashboard{% endblock %} + +{% block extra_css %} + +{% endblock %} + +{% block content %} +
+ {{ stats.total_scored_posts | format_number }} / {{ stats.total_posts | format_number }} posts scored + • + {{ stats.total_scored_mentions | format_number }} / {{ stats.total_mentions | format_number }} mentions scored +
+| Started | +Duration | +Posts Scored | +Mentions Scored | +Errors | +Cost | +Status | +
|---|---|---|---|---|---|---|
| {{ run.started_at | time_ago }} | +{% if run.duration_secs is not none %}{{ "%.0f" | format(run.duration_secs | float) }}s{% else %}—{% endif %} | +{{ run.posts_scored | format_number }} | +{{ run.mentions_scored | format_number }} | +{{ run.errors }} | +${{ "%.4f" | format(run.cost_usd | default(0) | float) }} | ++ + {{ run.status }} + + | +
No analysis runs yet. Start a new analysis to see results here.
+| Type | +{{ sort_header('author_handle', 'Author') }} | +Content | +{{ sort_header('overall', 'Score') }} | +Category | +{{ sort_header('created_at', 'Created') }} | +Review | +
|---|---|---|---|---|---|---|
| + + {% if item.item_type == 'post' %} + Post + {% elif item.item_type == 'reply' %} + Reply + {% elif item.item_type == 'mention' %} + Mention + {% endif %} + + | + + ++ {% if item.author_handle %} + + @{{ item.author_handle }} + + {% else %} + + {% endif %} + {% if item.item_type == 'mention' and item.mentioned_handle %} + → + + @{{ item.mentioned_handle }} + + {% endif %} + | + + ++ {% if item.source_type == 'post' %} + + {{ item.text | truncate_text(200) }} + + {% else %} + {# Convert at://did:plc:xxx/app.bsky.feed.post/yyy to https://bsky.app/profile/handle/post/yyy #} + {% set uri_parts = item.item_id.replace('at://', '').split('/') %} + {% if uri_parts|length >= 3 and item.author_handle %} + + {{ item.text | truncate_text(200) }} + + {% else %} + {{ item.text | truncate_text(200) }} + {% endif %} + {% endif %} + | + + ++ + | + + ++ {% if item.top_category %} + {{ item.top_category }} + {% else %} + — + {% endif %} + | + + ++ + {{ item.created_at | time_ago }} + + | + + ++ + | +
No flagged content found
+Try adjusting your filters or threshold
+