feat: implement comprehensive reading analytics system with bot detection
Features: - Add article view tracking with automatic deduplication (per user/IP) - Implement intelligent bot detection (35+ patterns: Google, Bing, Baidu, GPTBot, etc) - Create admin analytics dashboard with statistics and filtering - Display view count and comment count on article cards - Add search-based article filter (replaced dropdown for scalability) Analytics Dashboard: - Global stats: total views, human/bot views, unique IPs/users - Top 20 articles ranking with detailed metrics - Detailed view records with time, article, user, IP, user-agent - Filters: article title search, IP search, show/hide bots - Pagination support (50 records per page) Technical Implementation: - Async view recording (non-blocking) - Dual deduplication (application + database layer) - Database indexes for performance optimization - Batch query for comment counts - Full i18n support (Chinese/English) Files Added: - models/article_view.go: View tracking model - models/bot_detector.go: Bot detection logic - handlers/admin_analytics.go: Analytics page handler - templates/admin/analytics_views.html: Analytics UI - test_analytics.sh: Testing script - Documentation: implementation guide, usage guide, changelog Files Modified: - handlers/home.go: Add view recording and comment count queries - models/db.go: Add ArticleView to auto-migration - main.go: Add analytics routes - i18n/i18n.go: Add 35+ translation keys - templates/admin/dashboard.html: Add analytics entry link - templates/pages/home.html: Display view/comment counts on cards Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// botPatterns contains common bot/crawler/spider User-Agent patterns.
|
||||
var botPatterns = []string{
|
||||
"bot", "crawler", "spider", "scraper", "scraping",
|
||||
"googlebot", "bingbot", "baiduspider", "yandexbot",
|
||||
"duckduckbot", "slurp", "teoma", "ia_archiver",
|
||||
"facebookexternalhit", "facebot", "twitterbot",
|
||||
"whatsapp", "telegram", "slackbot", "discordbot",
|
||||
"linkedinbot", "pinterestbot", "tumblr",
|
||||
"semrushbot", "ahrefsbot", "mj12bot", "dotbot",
|
||||
"archive.org_bot", "serpstatbot", "dataforseo",
|
||||
"petalbot", "gptbot", "claudebot", "anthropic-ai",
|
||||
"bytespider", "applebot", "seznambot",
|
||||
"headless", "phantom", "selenium", "puppeteer",
|
||||
}
|
||||
|
||||
// IsBot checks if the given User-Agent string matches known bot patterns.
|
||||
// It performs a case-insensitive substring match against common bot identifiers.
|
||||
func IsBot(userAgent string) bool {
|
||||
if userAgent == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
ua := strings.ToLower(userAgent)
|
||||
|
||||
for _, pattern := range botPatterns {
|
||||
if strings.Contains(ua, pattern) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user