*/ public static function builtins() { $entries = array( 'googlebot' => array( 'label' => 'Googlebot', 'ua' => 'googlebot', 'domains' => array( '.googlebot.com', '.google.com' ), 'url' => 'https://developers.google.com/search/apis/ipranges/googlebot.json', ), 'bingbot' => array( 'label' => 'Bingbot', 'ua' => 'bingbot', 'domains' => array( '.search.msn.com' ), 'url' => 'https://www.bing.com/toolbox/bingbot.json', ), 'duckduckbot' => array( 'label' => 'DuckDuckBot', 'ua' => 'duckduckbot', 'domains' => array( '.duckduckgo.com' ), 'url' => 'https://duckduckgo.com/duckduckbot.json', ), 'applebot' => array( 'label' => 'Applebot', 'ua' => 'applebot', 'domains' => array( '.applebot.apple.com', '.apple.com' ), 'url' => 'https://search.developer.apple.com/applebot.json', ), 'yandex' => array( 'label' => 'Yandex', 'ua' => 'yandex', 'domains' => array( '.yandex.com', '.yandex.net', '.yandex.ru' ), 'url' => '', ), 'gptbot' => array( 'label' => 'GPTBot (OpenAI)', 'ua' => 'gptbot', 'domains' => array(), 'url' => 'https://openai.com/gptbot.json', ), 'oai-searchbot' => array( 'label' => 'OAI-SearchBot (OpenAI)', 'ua' => 'oai-searchbot', 'domains' => array(), 'url' => 'https://openai.com/searchbot.json', ), 'perplexitybot' => array( 'label' => 'PerplexityBot', 'ua' => 'perplexitybot', 'domains' => array(), 'url' => 'https://www.perplexity.ai/perplexitybot.json', ), ); $out = array(); foreach ( $entries as $token => $e ) { $e['token'] = $token; $e['builtin'] = true; $out[ $token ] = $e; } return $out; } /** * The effective registry: built-ins the owner hasn't disabled, plus their custom * entries (already sanitised at save — {@see Settings::sanitize}). * * @return array Token => entry. */ public static function entries() { $all = get_option( Settings::OPTION, array() ); $disabled = isset( $all['verifier_disabled'] ) ? (array) $all['verifier_disabled'] : array(); $custom = isset( $all['verifier_custom'] ) ? (array) $all['verifier_custom'] : array(); $entries = self::builtins(); foreach ( $disabled as $token ) { unset( $entries[ (string) $token ] ); } foreach ( $custom as $e ) { if ( ! is_array( $e ) || empty( $e['token'] ) || empty( $e['ua'] ) ) { continue; } $entries[ (string) $e['token'] ] = array( 'token' => (string) $e['token'], 'label' => isset( $e['label'] ) ? (string) $e['label'] : (string) $e['token'], 'ua' => strtolower( (string) $e['ua'] ), 'domains' => isset( $e['domains'] ) ? array_values( (array) $e['domains'] ) : array(), 'url' => isset( $e['url'] ) ? (string) $e['url'] : '', 'builtin' => false, ); } /** * Filter the effective verified-bot registry (token => entry). * * @param array $entries Registry entries. */ return (array) apply_filters( 'agentimus_verifier_registry', $entries ); } /** * One entry, or null. * * @param string $token Entry token. * @return array|null */ public static function entry( $token ) { $entries = self::entries(); return isset( $entries[ $token ] ) ? $entries[ $token ] : null; } /** * The registry entry a lowercased UA claims, or '' when it claims none. Longest * UA-needle wins, so a specific claim ("oai-searchbot") is never shadowed by a * shorter one it happens to contain. * * @param string $ua_lc Lowercased User-Agent. * @return string Token, or ''. */ public static function claimed( $ua_lc ) { $ua_lc = (string) $ua_lc; if ( '' === $ua_lc ) { return ''; } $best = ''; $best_len = 0; foreach ( self::entries() as $token => $e ) { $needle = (string) $e['ua']; if ( '' === $needle || strlen( $needle ) <= $best_len ) { continue; } if ( false !== strpos( $ua_lc, $needle ) ) { $best = (string) $token; $best_len = strlen( $needle ); } } return $best; } /** * The rDNS half of the registry: token => domain suffixes, for entries that have * them. This is {@see BotVerifier::engine_domains()}'s source, so disabling or * adding an entry changes every rDNS consumer at once. * * @return array */ public static function rdns_map() { $map = array(); foreach ( self::entries() as $token => $e ) { if ( ! empty( $e['domains'] ) ) { $map[ $token ] = (array) $e['domains']; } } return $map; } /** * Human label for a token ('' when unknown). * * @param string $token Entry token. * @return string */ public static function label( $token ) { $e = self::entry( $token ); return $e ? (string) $e['label'] : ''; } }