Add request logging, bot blocking, and admin log viewer
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
class RequestLogger
|
||||
{
|
||||
private string $logFile;
|
||||
|
||||
public function __construct(string $logFile)
|
||||
{
|
||||
$this->logFile = $logFile;
|
||||
}
|
||||
|
||||
public function log(string $page, string $ip, string $userAgent, string $referrer, string $host, string $acceptLanguage): void
|
||||
{
|
||||
$dir = dirname($this->logFile);
|
||||
if (!is_dir($dir)) {
|
||||
@mkdir($dir, 0755, true);
|
||||
}
|
||||
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
$ua = substr(preg_replace('/[[:cntrl:]]/', '', $userAgent), 0, 500);
|
||||
$ref = substr(preg_replace('/[[:cntrl:]]/', '', $referrer), 0, 500);
|
||||
$line = "[{$timestamp}] [{$ip}] [{$host}] [{$acceptLanguage}] [{$page}] [{$ua}] [{$ref}]\n";
|
||||
@file_put_contents($this->logFile, $line, FILE_APPEND | LOCK_EX);
|
||||
}
|
||||
|
||||
public static function detectBot(): ?string
|
||||
{
|
||||
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
|
||||
if (empty($ua)) return null;
|
||||
|
||||
$bots = [
|
||||
'AI' => [
|
||||
'GPTBot', 'ChatGPT-User', 'Claude-Web', 'ClaudeBot',
|
||||
'anthropic-ai', 'Google-Extended', 'CCBot',
|
||||
'PerplexityBot', 'Amazonbot', 'cohere-ai',
|
||||
'OAI-SearchBot', 'Bytespider', 'FacebookBot',
|
||||
'Applebot-Extended',
|
||||
],
|
||||
'Search' => [
|
||||
'Googlebot', 'Bingbot', 'BingPreview', 'Slurp',
|
||||
'DuckDuckBot', 'Baiduspider', 'YandexBot',
|
||||
'Sogou', 'Exabot', 'facebot',
|
||||
],
|
||||
'Scraper' => [
|
||||
'HTTrack', 'wget', 'curl', 'python-requests',
|
||||
'python-httpx', 'Go-http-client', 'okhttp',
|
||||
'Scrapy', 'Apache-HttpClient', 'Java/',
|
||||
'ruby', 'PhantomJS', 'HeadlessChrome',
|
||||
],
|
||||
'Aggregator' => [
|
||||
'Feedly', 'Feedbin', 'FeedReader', 'Inoreader',
|
||||
'Flipboard', 'Pocket', 'Pinterest',
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($bots as $category => $patterns) {
|
||||
foreach ($patterns as $pattern) {
|
||||
if (stripos($ua, $pattern) !== false) {
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getLogs(int $lines = 100): array
|
||||
{
|
||||
if (!file_exists($this->logFile)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$content = file($this->logFile);
|
||||
$content = array_slice($content, -$lines);
|
||||
$logs = [];
|
||||
|
||||
foreach ($content as $line) {
|
||||
if (preg_match('/^\[([^\]]+)\] \[([^\]]+)\] \[([^\]]+)\] \[([^\]]*)\] \[([^\]]+)\] \[([^\]]*)\] \[([^\]]*)\]$/', trim($line), $m)) {
|
||||
$logs[] = [
|
||||
'time' => $m[1],
|
||||
'ip' => $m[2],
|
||||
'host' => $m[3],
|
||||
'lang' => $m[4],
|
||||
'page' => $m[5],
|
||||
'ua' => $m[6],
|
||||
'referrer' => $m[7],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return array_reverse($logs);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user