diff --git a/core/chat/server.go b/core/chat/server.go index 25729b4ca..d2dcf7afa 100644 --- a/core/chat/server.go +++ b/core/chat/server.go @@ -14,6 +14,7 @@ import ( "github.com/owncast/owncast/core/data" "github.com/owncast/owncast/core/user" "github.com/owncast/owncast/core/webhooks" + "github.com/owncast/owncast/geoip" "github.com/owncast/owncast/utils" ) @@ -64,12 +65,12 @@ func (s *ChatServer) Run() { } // Addclient registers new connection as a User. -func (s *ChatServer) Addclient(conn *websocket.Conn, user *user.User, accessToken string, userAgent string) *ChatClient { +func (s *ChatServer) Addclient(conn *websocket.Conn, user *user.User, accessToken string, userAgent string, ipAddress string) *ChatClient { client := &ChatClient{ server: s, conn: conn, User: user, - ipAddress: conn.RemoteAddr().String(), + ipAddress: ipAddress, accessToken: accessToken, send: make(chan []byte, 256), UserAgent: userAgent, @@ -96,6 +97,11 @@ func (s *ChatServer) Addclient(conn *websocket.Conn, user *user.User, accessToke s.sendWelcomeMessageToClient(client) } + // Asynchronously, optionally, fetch GeoIP data. + go func(client *ChatClient) { + client.Geo = geoip.GetGeoFromIP(ipAddress) + }(client) + return client } @@ -172,8 +178,9 @@ func (s *ChatServer) HandleClientConnection(w http.ResponseWriter, r *http.Reque } userAgent := r.UserAgent() + ipAddress := utils.GetIPAddressFromRequest(r) - s.Addclient(conn, user, accessToken, userAgent) + s.Addclient(conn, user, accessToken, userAgent, ipAddress) } // Broadcast sends message to all connected clients. diff --git a/geoip/geoip.go b/geoip/geoip.go index 73bc9eeba..0f02d2611 100644 --- a/geoip/geoip.go +++ b/geoip/geoip.go @@ -37,62 +37,62 @@ func GetGeoFromIP(ip string) *GeoDetails { } } - return nil + return fetchGeoForIP(ip) } -// FetchGeoForIP makes an API call to get geo details for an IP address. -func FetchGeoForIP(ip string) { +// fetchGeoForIP makes an API call to get geo details for an IP address. +func fetchGeoForIP(ip string) *GeoDetails { // If GeoIP has been disabled then don't try to access it. if !_enabled { - return + return nil } // Don't re-fetch if we already have it. - if _, ok := _geoIPCache[ip]; ok { - return + if geoDetails, ok := _geoIPCache[ip]; ok { + return &geoDetails } - go func() { - db, err := geoip2.Open(geoIPDatabasePath) - if err != nil { - log.Traceln("GeoIP support is disabled. visit http://owncast.online/docs/geoip to learn how to enable.", err) - _enabled = false - return + db, err := geoip2.Open(geoIPDatabasePath) + if err != nil { + log.Traceln("GeoIP support is disabled. visit http://owncast.online/docs/geoip to learn how to enable.", err) + _enabled = false + return nil + } + + defer db.Close() + + ipObject := net.ParseIP(ip) + + record, err := db.City(ipObject) + if err != nil { + log.Warnln(err) + return nil + } + + // If no country is available then exit + if record.Country.IsoCode == "" { + return nil + } + + // If we believe this IP to be anonymous then no reason to report it + if record.Traits.IsAnonymousProxy { + return nil + } + + var regionName = "Unknown" + if len(record.Subdivisions) > 0 { + if region, ok := record.Subdivisions[0].Names["en"]; ok { + regionName = region } + } - defer db.Close() + response := GeoDetails{ + CountryCode: record.Country.IsoCode, + RegionName: regionName, + TimeZone: record.Location.TimeZone, + } - ipObject := net.ParseIP(ip) + _geoIPCache[ip] = response - record, err := db.City(ipObject) - if err != nil { - log.Warnln(err) - return - } - - // If no country is available then exit - if record.Country.IsoCode == "" { - return - } - - // If we believe this IP to be anonymous then no reason to report it - if record.Traits.IsAnonymousProxy { - return - } - - var regionName = "Unknown" - if len(record.Subdivisions) > 0 { - if region, ok := record.Subdivisions[0].Names["en"]; ok { - regionName = region - } - } - - response := GeoDetails{ - CountryCode: record.Country.IsoCode, - RegionName: regionName, - TimeZone: record.Location.TimeZone, - } - - _geoIPCache[ip] = response - }() + return &response }