cleaned up tracking

This commit is contained in:
JurajKubrican
2025-08-20 09:06:12 +02:00
parent 1e00e24e5d
commit 3e5513a590
8 changed files with 69 additions and 25 deletions

1
go.mod
View File

@@ -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

2
go.sum
View File

@@ -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=

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)
}

12
src/tracking/useragent.go Normal file
View File

@@ -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
}

View File

@@ -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
}

View File

@@ -154,8 +154,6 @@
</table>
</div>
</main>
<script src="/js/global.d.ts?v={{.BuildNumber}}" integrity="{{index .Integrity.JS "global.d.ts" }}" crossorigin="anonymous"></script>
</body>
</html>
{{end}}