{% extends "paxalia/base.html" %}
{% load static i18n %}
{% block page_title %}{% trans "Bot Traffic" %}{% endblock %}
{% block page_subtitle %}{% trans "Investigate crawlers and scanners by client, category, provider, and requested path" %}{% endblock %}
{% block extra_css %}{% endblock %}
{% block filter_bar %}{% include 'paxalia/includes/filter_bar.html' %}{% endblock %}
{% block dashboard_content %}
{% trans "Bot requests" %}{{ total_bot_views }}
{% trans "Today" %}{{ bot_views_today }}
{% trans "Unique IP / hash" %}{{ unique_bot_ips }}
{% trans "Categories" %}{{ category_breakdown|length }}
{% trans "Bot requests over time" %}
{% trans "Top requested paths" %}
{% trans "Bot countries" %}
{% trans "Category mix" %}
{% if category_breakdown %}{% else %}
{% trans "No classified bot traffic in this period." %}
{% endif %}
{% trans "Path intelligence" %}
{% trans "See which paths attract automated traffic and how many different clients requested them. Use the Pages or Broken Links actions to turn a known scanner path into a persistent rule." %}
{{ path_rows|length }}
{% if path_rows %}
{% trans "Path" %}
{% trans "Requests" %}
{% trans "Unique IP / hash" %}
{% trans "Last seen" %}
{% for row in path_rows %}
{{ row.path }}
{{ row.count }}
{{ row.unique_ips }}
{{ row.last_seen|date:"Y-m-d H:i" }}
{% endfor %}
{% else %}
{% trans "No bot paths were recorded in this date range." %}
{% endif %}
{% trans "IP investigation" %}
{% trans "Each client is grouped with the paths it requested. Provider/name comes from its User-Agent claim; scanner path rules are stronger evidence and are shown as rule-based classification." %}
{{ row.requests }} {% trans "requests" %} · {{ row.unique_paths }} {% trans "paths" %}
{% trans "First" %} {{ row.first_seen|date:"Y-m-d H:i" }} · {% trans "Last" %} {{ row.last_seen|date:"Y-m-d H:i" }} · {% trans "Identity evidence" %}: {{ row.identity_confidence }}
{% if row.user_agent %}
{% trans "Observed User-Agent" %}{{ row.user_agent }}
{% endif %}
{% trans "Requested path" %}
{% trans "Category" %}
{% trans "Hits" %}
{% trans "Last seen" %}
{% for path in row.paths %}
{{ path.path }}
{{ path.category_label }}
{{ path.count }}
{{ path.last_seen|date:"Y-m-d H:i" }}
{% endfor %}
{% endfor %}
{% else %}
{% trans "No bot IPs were recorded in this date range." %}
{% endif %}
{% trans "Scanner activity" %}
{% trans "Known malicious/scanner path matches, grouped by client and target endpoint." %}
{% if scanner_rows %}
{% trans "IP / hash" %}
{% trans "Path" %}
{% trans "Hits" %}
{% trans "Different User-Agents" %}
{% trans "Last seen" %}
{% for row in scanner_rows %}
{{ row.ip_hash|default:"Unknown" }}
{{ row.path }}
{{ row.count }}
{{ row.unique_agents }}
{{ row.last_seen|date:"Y-m-d H:i" }}
{% endfor %}
{% else %}
{% trans "No malicious/scanner requests in this period." %}
{% endif %}
{% trans "Crawler identity" %}
{% trans "Search-engine, AI, social-preview, and SEO identities are inferred from User-Agent strings; the IP itself is not independently verified here." %}
{% if crawler_rows %}
{% trans "Category" %}
{% trans "Provider / name" %}
{% trans "User-Agent" %}
{% trans "Hits" %}
{% trans "IPs" %}
{% for row in crawler_rows %}
{{ row.category|default:"Unclassified" }}
{{ row.name }}{% if row.provider %}
{{ row.provider }}
{% endif %}
{{ row.user_agent }}
{{ row.count }}
{{ row.unique_ips }}
{% endfor %}
{% else %}
{% trans "No crawler identity records in this period." %}
{% endif %}
{% trans "Configured Bot / Scanner path prefixes" %}
{% trans "These prefixes are applied at ingestion time. Pages and Broken Links can add a path and clean matching normal page-view records in one bounded action." %}