
=== Bot Blocker ===
Contributors: botcrawl
Tags: bots, crawler, ai, security, monitoring, bot blocker, bot detection, firewall
Requires at least: 6.0
Tested up to: 6.9
Requires PHP: 7.4
Stable tag: 1.1.3
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Live bot monitor with a world geo-map, per-category rules, allow/block lists, searchable logs, and settings.

== Description ==

Bot Blocker detects a broad range of known bot traffic, applies configurable per-category policies (allow, log, rate-limit, temporary block, or hard block), and streams those events to a live world map monitor in your WordPress admin dashboard.

Key features:

* Live geo-map monitor - A Plotly-powered world map shows bot origins in real time. Markers are color-coded by action (red = blocked, orange = fake bot, yellow = rate-limited, blue = verified, green = allowed/logged). A live feed panel alongside the map shows the most recent events with bot name, location, path, action, and relative timestamp.
* 13 bot categories - Verified bots, claimed trusted bots, fake trusted bots, AI crawlers, AI assistants, search/SEO bots, preview/unfurl bots, monitoring bots, service/integration bots, scanner bots, scraper bots, spam bots, and sensitive-path probes.
* Per-category rules - Assign any action (allow, log, rate-limit, temporary block, block) to each category independently.
* Manual allow/block lists - Override rules by IP address, CIDR range, user-agent substring, or path prefix.
* Asynchronous geolocation - IP geolocation via ipwho.is is performed in a background scheduled job so it never slows down live requests. Results are backfilled into recent events automatically.
* Asynchronous DNS verification - Trusted bot identity checks (reverse-DNS) run asynchronously, keeping the live request path fast.
* Event aggregation - Repeated hits from the same bot within a 30-second window are collapsed into a single database row with a burst counter, preventing log bloat.
* Trusted proxy support - Cloudflare and other reverse-proxy forwarded IP headers are only trusted when the connecting IP matches a configured trusted-proxy list.
* Privacy-safe defaults - Raw IPs, query strings, and referrers are not stored by default. IP hashing and masking are applied to all stored events.
* GDPR tools - Integrates with the WordPress personal data exporter and eraser.
* Automatic log cleanup - A daily scheduled task removes events older than the configured retention period.
* Rate limiting - Configurable per-minute thresholds for AI crawlers, scraper bots, scanner bots, and spam bots before a temporary block is applied.

== Installation ==

1. Upload the plugin zip through Plugins > Add New > Upload Plugin in WordPress.
2. Activate the plugin.
3. Open Bot Blocker in the WordPress admin sidebar.
4. Review the default rules on the Rules page and adjust them to suit your site.
5. Optionally configure allow/block lists, geolocation, and log retention on the Lists and Settings pages.

== Frequently Asked Questions ==

= Why are some events unmapped on the geo-map? =
Geolocation is performed asynchronously in a background job after the event is recorded. If the background job has not yet run, or if geolocation is disabled in Settings, the event will appear in the live feed and counts but will not have map coordinates. These are counted as "Unmapped" in the topbar.

= Does geolocation slow down my site? =
No. Geolocation lookups are dispatched to a WordPress scheduled event and run in the background, completely outside the live request path. Your visitors are never delayed.

= What is the difference between "Claimed trusted bots" and "Fake trusted bots"? =
"Claimed trusted bots" are requests whose user agent string claims to be a well-known trusted crawler (e.g. Googlebot) but whose identity has not yet been verified via reverse-DNS. "Fake trusted bots" are requests that claimed a trusted identity but failed the reverse-DNS verification check, meaning they are almost certainly malicious impersonators.

= How does DNS verification work? =
When a bot claims to be a trusted crawler, Bot Blocker schedules an asynchronous reverse-DNS lookup. If the resolved hostname does not match the expected domain for that crawler, the event is marked as failed verification and re-categorized as a fake trusted bot for future requests from that IP.

= What happens when a bot is "rate limited"? =
The plugin counts requests from the bot within a rolling one-minute window. When the count exceeds the configured threshold for that category, the bot receives a 429 Too Many Requests response. The temporary block is lifted automatically after the window expires.

= What is a "temporary block"? =
A temporary block stores a lock record in the database for the bot IP hash. Subsequent requests from the same IP within the lock duration receive a 403 Forbidden response. Locks expire automatically and are cleaned up by the daily maintenance task.

= Does Bot Blocker affect real visitors? =
No. Bot Blocker only processes requests that match known bot user agents or sensitive-path probes. Regular visitor traffic is not inspected or affected.

= Can I whitelist my own monitoring tools or crawlers? =
Yes. Add the IP address or user-agent substring of your tool to the Allow IPs or Allow agents list on the Lists page. Allow-list entries are evaluated before any rules.

= Is this plugin compatible with Cloudflare? =
Yes. Enable the "Prefer Cloudflare connecting IP header" option in Settings and add your Cloudflare IP ranges to the Trusted proxy IPs list. Bot Blocker will then use the CF-Connecting-IP header to identify the real client IP.

= Where is bot data stored? =
All event data is stored in a dedicated custom database table (wp_bot_blocker_events) in your WordPress database. No data is sent to external servers except for the optional asynchronous geolocation lookup to ipwho.is.

= How do I completely remove all data when uninstalling? =
Deactivating and then deleting the plugin via the WordPress admin will trigger the uninstall routine, which drops the custom database tables and deletes all plugin options and transients.

== Privacy ==

Bot Blocker stores bot event logs in a custom database table. Stored fields include: a SHA-256 hash of the IP address (salted with the WordPress auth key), a masked IP (last octet zeroed for IPv4, last 64 bits zeroed for IPv6), the raw IP address only if "Store raw IP addresses" is enabled (off by default), the user agent string, the requested path, the action taken, the matched rule, and optional geolocation fields (country, region, city, latitude, longitude) only when geolocation is enabled.

Query strings and referrers are not stored by default because they may contain personal or sensitive data. These can be enabled individually in Settings.

Geolocation uses the ipwho.is third-party API only when geolocation is explicitly enabled in Settings. The IP address is sent to ipwho.is to retrieve geographic coordinates. Results are cached in WordPress transients for 7 days.

The plugin registers with the WordPress personal data exporter and eraser tools to support GDPR data subject requests.

== Changelog ==

= 1.1.3 =
* Fixed duplicate delete_all branch in bulk log action handler (dead code removed).
* Hardened feed rendering: all bot names, paths, and locations are now HTML-escaped before output.
* Added Pause / Resume toggle to the live monitor feed.
* Added last-updated timestamp indicator to the monitor topbar.
* Added graceful error state when the REST poll fails.
* Added empty-state placeholder for the map and feed.
* Added color legend bar below the KPI cards.
* Added hover highlight on feed items.
* Added burst-count badge on feed items for aggregated events.
* Added human-readable action labels in the feed.
* Added relative timestamp per feed item.
* Improved Plotly map hover text formatting.
* Removed unused variables from monitor.js.
* Added contextual description text to Rules, Lists, and Settings pages.
* Improved Settings page labels with clearer descriptions.
* Fixed location string formatting in monitor REST endpoint.

= 1.1.2 =
* Updated plugin metadata for the current WordPress 6.9 stable branch.

= 1.1.1 =
* Rebuilt the request pipeline so enforcement, logging, and enrichment are properly separated.
* Added trusted proxy-aware client IP handling and stronger temporary lock behavior.
* Moved geolocation and trusted bot DNS verification out of the live request path and into scheduled jobs.
* Added privacy-safer defaults, IP hashing, event aggregation, and deactivation cleanup.
* Tightened registry sanitization, admin validation, and log handling.

= 1.0.0 =
* Initial release.
