From 3e5513a590b4323488e7b3e37e1332f2dde3ddca Mon Sep 17 00:00:00 2001 From: JurajKubrican Date: Wed, 20 Aug 2025 09:06:12 +0200 Subject: [PATCH] cleaned up tracking --- go.mod | 1 + go.sum | 2 ++ src/main.go | 5 +++- src/tracking/middleware.go | 42 +++++++++++++++++----------------- src/tracking/tracking-store.go | 14 +++++++++++- src/tracking/useragent.go | 12 ++++++++++ src/tracking/util.go | 16 +++++++++++++ views/tracking.html | 2 -- 8 files changed, 69 insertions(+), 25 deletions(-) create mode 100644 src/tracking/useragent.go diff --git a/go.mod b/go.mod index c7ec811..c3f8ff6 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mileusna/useragent v1.3.5 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/prometheus/client_model v0.6.2 // indirect diff --git a/go.sum b/go.sum index 2833817..e620551 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mileusna/useragent v1.3.5 h1:SJM5NzBmh/hO+4LGeATKpaEX9+b4vcGg2qXGLiNGDws= +github.com/mileusna/useragent v1.3.5/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= diff --git a/src/main.go b/src/main.go index 4442060..a285498 100644 --- a/src/main.go +++ b/src/main.go @@ -102,7 +102,10 @@ func main() { } // MY supper tracking - e.Use(tracking.Echo) + e.Use(tracking.EchoWithConfig(tracking.TrackingConfig{ + IgnorePaths: []string{"/tracking", "/metrics", "/css/*", "/js/*"}, + IgnoreUserAgents: []string{"Prometheus", "UptimeRobot"}, + })) trackingGroup := e.Group("/tracking") trackingGroup.GET("", tracking.BasicTrackingHandler) diff --git a/src/tracking/middleware.go b/src/tracking/middleware.go index 5697847..6d686ea 100644 --- a/src/tracking/middleware.go +++ b/src/tracking/middleware.go @@ -1,9 +1,6 @@ package tracking import ( - "fmt" - "strings" - "github.com/labstack/echo/v4" "knet.sk/src/util" ) @@ -35,32 +32,35 @@ type PageStat struct { var ts *TrackingService -var ignorePaths = []string{ - "/tracking", - "/metrics", +type TrackingConfig struct { + IgnorePaths []string + IgnoreUserAgents []string } -var ignoreUserAgents = []string{ - "Prometheus", - "UptimeRobot", +type TrackingMiddleware struct { + Config TrackingConfig } -func Echo(next echo.HandlerFunc) echo.HandlerFunc { +var middleware *TrackingMiddleware + +func EchoWithConfig(config TrackingConfig) func(next echo.HandlerFunc) echo.HandlerFunc { + middleware = &TrackingMiddleware{ + Config: config, + } + return middleware.Echo +} + +func (mw TrackingMiddleware) Echo(next echo.HandlerFunc) echo.HandlerFunc { ts = StartTrackingService() return func(c echo.Context) error { - fmt.Printf("Tracking visit: %s %s\n", c.RealIP(), c.Request().URL.Path) - // Check if the path is in the ignore list - for _, path := range ignorePaths { - if c.Request().URL.Path == path { - return next(c) // Skip tracking for ignored paths - } + ignorePathsRegex := getRegexFromWildcard(mw.Config.IgnorePaths) + if ignorePathsRegex.Match([]byte(c.Request().URL.Path)) { + return next(c) // Skip tracking for ignored paths } - // Check if the user agent is in the ignore list - for _, ua := range ignoreUserAgents { - if strings.Contains(c.Request().UserAgent(), ua) { - return next(c) // Skip tracking for ignored user agents - } + ignoreUserAgentsRegex := getRegexFromWildcard(mw.Config.IgnoreUserAgents) + if ignoreUserAgentsRegex.Match([]byte(c.Request().UserAgent())) { + return next(c) // Skip tracking for ignored user agents } go ts.AddVisit(c) return next(c) diff --git a/src/tracking/tracking-store.go b/src/tracking/tracking-store.go index 6afe2d2..4f401f5 100644 --- a/src/tracking/tracking-store.go +++ b/src/tracking/tracking-store.go @@ -3,6 +3,7 @@ package tracking import ( "database/sql" "sync" + "time" "github.com/labstack/echo/v4" _ "modernc.org/sqlite" @@ -175,10 +176,21 @@ func (ts *TrackingService) GetRecentVisits(limit int) []VisitDisplay { var visits []VisitDisplay for rows.Next() { var visit VisitDisplay - if err := rows.Scan(&visit.Timestamp, &visit.IPAddress, &visit.Path, &visit.UserAgent, &visit.Referrer); err != nil { + var rawTimestamp string + if err := rows.Scan(&rawTimestamp, &visit.IPAddress, &visit.Path, &visit.UserAgent, &visit.Referrer); err != nil { println("Error scanning visit:", err.Error()) continue } + + // Parse and format the timestamp + if t, err := time.Parse("2006-01-02 15:04:05", rawTimestamp); err == nil { + visit.Timestamp = t.Format("Jan 2, 2006 at 3:04 PM") + } else { + // Fallback to original timestamp if parsing fails + visit.Timestamp = rawTimestamp + } + + visit.UserAgent = parseUserAgent(visit.UserAgent) visits = append(visits, visit) } diff --git a/src/tracking/useragent.go b/src/tracking/useragent.go new file mode 100644 index 0000000..e0fec75 --- /dev/null +++ b/src/tracking/useragent.go @@ -0,0 +1,12 @@ +package tracking + +import ( + "github.com/mileusna/useragent" +) + +func parseUserAgent(ua string) string { + + parsedUA := useragent.Parse(ua) + + return parsedUA.Name + " " + parsedUA.OS + " " + parsedUA.Version +} diff --git a/src/tracking/util.go b/src/tracking/util.go index cafd90f..ffca81f 100644 --- a/src/tracking/util.go +++ b/src/tracking/util.go @@ -1,6 +1,9 @@ package tracking import ( + "regexp" + "strings" + "github.com/labstack/echo/v4" ) @@ -13,3 +16,16 @@ func getFingerprint(c echo.Context) string { // Combine them into a fingerprint string return ip + userAgent + acceptLanguage } + +func getRegexFromWildcard(wildcards []string) *regexp.Regexp { + escapedWildcards := make([]string, len(wildcards)) + for i, wildcard := range wildcards { + escapedWildcards[i] = regexp.QuoteMeta(wildcard) + escapedWildcards[i] = strings.ReplaceAll(escapedWildcards[i], `\*`, ".*") // Replace escaped wildcard with regex equivalent + } + pattern := "^(" + strings.Join(escapedWildcards, "|") + ")$" + + // Compile the regex + regex := regexp.MustCompile(pattern) + return regex +} diff --git a/views/tracking.html b/views/tracking.html index 78188df..06d4d89 100644 --- a/views/tracking.html +++ b/views/tracking.html @@ -154,8 +154,6 @@ - - {{end}}