matcher = $matcher; } /** * Builds the snippet. * * @return string The snippet, or an empty string when nothing is blocked. */ public function build(): string { $tokens = $this->matcher->get_enforceable_tokens(); if ( empty( $tokens ) ) { return ''; } $lines = array( '# BEGIN AI Blackout', '# Add this inside the server { } block for your site, then reload nginx', '# with: sudo nginx -t && sudo systemctl reload nginx', '#', '# This blocks AI crawlers that identify themselves. It cannot stop a', '# crawler that disguises its user agent.', '', 'if ($http_user_agent ~* "(' . implode( '|', array_map( array( $this, 'escape' ), $tokens ) ) . ')") {', ' return 403;', '}', '', '# END AI Blackout', ); return implode( "\n", $lines ) . "\n"; } /** * Escapes a token for use inside an nginx regular expression. * * @param string $token User-agent token. * @return string Escaped token. */ private function escape( string $token ): string { return preg_quote( $token, '"' ); } }