core_rules = $this->load_core_rules(); } public function get_all_rules(): array { if ( null !== $this->rules_cache ) { return $this->rules_cache; } $settings = aicrg_get_settings(); $rules = []; if ( ! empty( $settings['custom_rules_enabled'] ) ) { $rules = array_merge( $rules, aicrg_sanitize_custom_rules( $settings['custom_rules'] ?? [] ) ); } if ( ! empty( $settings['core_rules_enabled'] ) ) { $rules = array_merge( $rules, $this->core_rules ); } $this->rules_cache = array_values( array_filter( $rules, static function ( $rule ) { return ! empty( $rule['slug'] ) && ! empty( $rule['pattern'] ); } ) ); return $this->rules_cache; } public function get_rule( string $slug ): ?array { foreach ( $this->get_all_rules() as $rule ) { if ( $rule['slug'] === $slug ) { return $rule; } } return null; } public function get_category_info( string $slug ): array { $rule = $this->get_rule( $slug ); if ( $rule ) { return [ 'category' => $rule['category'] ?? 'custom', 'default_status' => $rule['default_status'] ?? 'unknown', 'name' => $rule['name'] ?? $slug, ]; } return [ 'category' => 'custom', 'default_status' => 'unknown', 'name' => $slug, ]; } public function get_category_label( string $category ): string { $labels = [ 'ai' => __( 'AI / LLM', 'ai-crawler-guard' ), 'search' => __( 'AI Search', 'ai-crawler-guard' ), 'social' => __( 'Social / Preview', 'ai-crawler-guard' ), 'utility' => __( 'AI Utility', 'ai-crawler-guard' ), 'custom' => __( 'Custom', 'ai-crawler-guard' ), ]; return $labels[ $category ] ?? $labels['custom']; } private function load_core_rules(): array { return [ // OpenAI family [ 'slug' => 'gptbot', 'name' => 'OpenAI GPTBot', 'pattern' => 'gptbot', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'chatgpt-user', 'name' => 'ChatGPT User', 'pattern' => 'ChatGPT-User', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'chatgpt-agent', 'name' => 'ChatGPT Agent', 'pattern' => 'ChatGPT Agent', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'oai-searchbot', 'name' => 'OpenAI SearchBot', 'pattern' => 'OAI-SearchBot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'openai', 'name' => 'OpenAI Bot', 'pattern' => 'OpenAI', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'operator', 'name' => 'OpenAI Operator', 'pattern' => 'Operator', 'category' => 'ai', 'source' => 'core' ], // Anthropic [ 'slug' => 'anthropic-ai', 'name' => 'Anthropic AI', 'pattern' => 'anthropic-ai', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'claudebot', 'name' => 'ClaudeBot', 'pattern' => 'ClaudeBot', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'claude-user', 'name' => 'Claude User', 'pattern' => 'Claude-User', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'claude-searchbot', 'name' => 'Claude SearchBot', 'pattern' => 'Claude-SearchBot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'claude-web', 'name' => 'Claude Web', 'pattern' => 'Claude-Web', 'category' => 'ai', 'source' => 'core' ], // Major AI search / assistants [ 'slug' => 'applebot', 'name' => 'Applebot', 'pattern' => 'Applebot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'applebot-extended', 'name' => 'Applebot-Extended', 'pattern' => 'Applebot-Extended', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'amazonbot', 'name' => 'Amazonbot', 'pattern' => 'Amazonbot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'bedrockbot', 'name' => 'BedrockBot', 'pattern' => 'bedrockbot', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'amazon-kendra', 'name' => 'Amazon Kendra', 'pattern' => 'amazon-kendra-', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'perplexitybot', 'name' => 'PerplexityBot', 'pattern' => 'PerplexityBot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'perplexity-user', 'name' => 'Perplexity User', 'pattern' => 'Perplexity-User', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'duckduckgo-ai', 'name' => 'DuckDuckGo AI', 'pattern' => 'duckduckgo-ai', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'duckassistbot', 'name' => 'DuckAssist Bot', 'pattern' => 'DuckAssistBot', 'category' => 'search', 'source' => 'core' ], // Additional AI crawlers [ 'slug' => 'ccbot', 'name' => 'Common Crawl CCBot', 'pattern' => 'CCBot', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'bytespider', 'name' => 'ByteDance ByteSpider', 'pattern' => 'Bytespider', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'deepseekbot', 'name' => 'DeepSeekBot', 'pattern' => 'DeepSeekBot', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'mistralai-user', 'name' => 'MistralAI User', 'pattern' => 'MistralAI-User', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'phindbot', 'name' => 'PhindBot', 'pattern' => 'PhindBot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'youbot', 'name' => 'You.com Bot', 'pattern' => 'YouBot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'bravebot', 'name' => 'BraveBot', 'pattern' => 'Bravebot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'petalbot', 'name' => 'PetalBot', 'pattern' => 'PetalBot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'yandexadditional', 'name' => 'Yandex Additional', 'pattern' => 'YandexAdditional', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'yandexadditionalbot','name' => 'Yandex Additional Bot', 'pattern' => 'YandexAdditionalBot','category' => 'ai', 'source' => 'core' ], // Utility / tooling bots [ 'slug' => 'firecrawlagent', 'name' => 'Firecrawl Agent', 'pattern' => 'FirecrawlAgent', 'category' => 'utility','source' => 'core' ], [ 'slug' => 'diffbot', 'name' => 'Diffbot', 'pattern' => 'Diffbot', 'category' => 'utility','source' => 'core' ], [ 'slug' => 'cloudflare-autorag','name' => 'Cloudflare AutoRAG', 'pattern' => 'Cloudflare-AutoRAG','category' => 'utility','source' => 'core' ], [ 'slug' => 'klaviyoaibot', 'name' => 'Klaviyo AI Bot', 'pattern' => 'KlaviyoAIBot', 'category' => 'utility','source' => 'core' ], [ 'slug' => 'linerbot', 'name' => 'LinerBot', 'pattern' => 'LinerBot', 'category' => 'utility','source' => 'core' ], [ 'slug' => 'andibot', 'name' => 'AndiBot', 'pattern' => 'Andibot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'anomura', 'name' => 'Anomura', 'pattern' => 'Anomura', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'iboubot', 'name' => 'IbouBot', 'pattern' => 'IbouBot', 'category' => 'search', 'source' => 'core' ], [ 'slug' => 'panscient', 'name' => 'Panscient', 'pattern' => 'Panscient', 'category' => 'utility','source' => 'core' ], [ 'slug' => 'quillbot', 'name' => 'QuillBot', 'pattern' => 'QuillBot', 'category' => 'utility','source' => 'core' ], [ 'slug' => 'terracotta', 'name' => 'TerraCotta', 'pattern' => 'TerraCotta', 'category' => 'ai', 'source' => 'core' ], [ 'slug' => 'velenpublicwebcrawler', 'name' => 'Velen Public Crawler','pattern' => 'VelenPublicWebCrawler','category' => 'utility','source' => 'core' ], // Social / preview bots (trusted by default) [ 'slug' => 'facebookbot', 'name' => 'FacebookBot', 'pattern' => 'FacebookBot', 'category' => 'social', 'source' => 'core', 'default_status' => 'trusted' ], [ 'slug' => 'meta-externalagent','name' => 'Meta External Agent', 'pattern' => 'Meta-ExternalAgent','category' => 'social', 'source' => 'core', 'default_status' => 'trusted' ], [ 'slug' => 'meta-externalfetcher','name' => 'Meta External Fetcher','pattern' => 'Meta-ExternalFetcher','category' => 'social','source' => 'core', 'default_status' => 'trusted' ], [ 'slug' => 'twitterbot', 'name' => 'Twitterbot', 'pattern' => 'Twitterbot', 'category' => 'social', 'source' => 'core', 'default_status' => 'trusted' ], [ 'slug' => 'linkedinbot', 'name' => 'LinkedIn Bot', 'pattern' => 'LinkedInBot', 'category' => 'social', 'source' => 'core', 'default_status' => 'trusted' ], ]; } }