module BotBlocker extend ActiveSupport::Concern included do before_action :block_bots end private def block_bots return unless bot_request? render plain: "Bot access is not allowed", status: :forbidden end def bot_request? user_agent = request.user_agent.to_s.downcase # List of known bot user agents bot_patterns = [ "gptbot", # OpenAI GPTBot "chatgpt", # ChatGPT "claude-web", # Anthropic Claude "bingbot", # Microsoft Bing "googlebot", # Google "baiduspider", # Baidu "yandexbot", # Yandex "duckduckbot", # DuckDuckGo "slurp", # Yahoo "facebookexternalhit", # Facebook "twitterbot", # Twitter "linkedinbot", # LinkedIn "whatsapp", # WhatsApp "telegrambot", # Telegram "slackbot", # Slack "discordbot", # Discord "applebot", # Apple "ia_archiver", # Alexa/Internet Archive "petalbot", # Huawei "seznambot", # Seznam "ahrefsbot", # Ahrefs "semrushbot", # SEMrush "mj12bot", # Majestic "dotbot", # OpenSiteExplorer "rogerbot", # Moz "exabot", # Exalead "facebot", # Facebook "spider", # Generic spiders "crawler", # Generic crawlers "scraper", # Generic scrapers "bot" # Generic bots (last resort) ] bot_patterns.any? { |pattern| user_agent.include?(pattern) } end end