diff --git a/Gemfile b/Gemfile index 88747c0..db09839 100644 --- a/Gemfile +++ b/Gemfile @@ -35,7 +35,7 @@ gem 'redis', '>= 4.0.1' gem 'chartkick' gem 'devise' gem 'font-awesome-sass', '~> 6.5.2' -gem 'offline_geocoder' +gem 'geocoder' gem 'groupdate' gem 'mini_magick' gem 'sidekiq' diff --git a/Gemfile.lock b/Gemfile.lock index 953baf5..4ac7bd9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,6 +113,7 @@ GEM concurrent-ruby (1.3.3) connection_pool (2.4.1) crass (1.0.6) + csv (3.3.0) date (3.3.4) debug (1.9.2) irb (~> 1.10) @@ -140,18 +141,14 @@ GEM ffi (1.17.0-x86-linux-gnu) ffi (1.17.0-x86_64-darwin) ffi (1.17.0-x86_64-linux-gnu) - ffi-compiler (1.3.2) - ffi (>= 1.15.5) - rake font-awesome-sass (6.5.2) sassc (~> 2.0) fugit (1.11.1) et-orbi (~> 1, >= 1.2.11) raabro (~> 1.4) - geokdtree (0.2.0) - ffi - ffi-compiler - rake + geocoder (1.8.3) + base64 (>= 0.1.0) + csv (>= 3.0.0) globalid (1.2.1) activesupport (>= 6.1) groupdate (6.4.0) @@ -208,8 +205,6 @@ GEM racc (~> 1.4) nokogiri (1.16.6-x86_64-linux) racc (~> 1.4) - offline_geocoder (0.2.0) - geokdtree (~> 0.2) orm_adapter (0.5.0) psych (5.1.2) stringio @@ -390,11 +385,11 @@ DEPENDENCIES devise factory_bot_rails font-awesome-sass (~> 6.5.2) + geocoder groupdate importmap-rails jbuilder mini_magick - offline_geocoder puma (>= 5.0) rails (~> 7.1.3, >= 7.1.3.4) redis (>= 4.0.1) diff --git a/README.md b/README.md index 5abb7f1..72941b3 100644 --- a/README.md +++ b/README.md @@ -286,6 +286,16 @@ The restore process: 2. Loads the specified backup file. 3. Applies any pending migrations. +## Geolocation + +Geolocation is currently a mandatory feature in Linkarooie. It uses the `geocoder` gem to provide location-based insights for link clicks and page views. + +To enable geolocation: +1. Obtain a free API key from [ipapi](https://ipapi.com). +2. Set the `GEOCODER_API_KEY` environment variable with your API key. + +Future plans include making geolocation optional to cater to different privacy preferences. + ## Customization Linkarooie is designed to be highly customizable: diff --git a/app/middleware/page_view_tracker.rb b/app/middleware/page_view_tracker.rb index 78ecb9c..acc0cac 100644 --- a/app/middleware/page_view_tracker.rb +++ b/app/middleware/page_view_tracker.rb @@ -26,8 +26,9 @@ def track_page_view(request) # Extract the original IP from the Cloudflare headers if available real_ip = request.headers['CF-Connecting-IP'] || request.headers['X-Forwarded-For']&.split(',')&.first || request.ip - location = OFFLINE_GEOCODER.search(real_ip) - + # Use Geocoder to find the location based on the real IP + location = Geocoder.search(real_ip).first + PageView.create( user: user, path: request.path, @@ -36,13 +37,13 @@ def track_page_view(request) visited_at: Time.current, ip_address: real_ip, session_id: request.session[:session_id], - country: location[:country], - city: location[:name], - state: location[:admin1], - county: location[:admin2], - latitude: location[:lat], - longitude: location[:lon], - country_code: location[:cc] + country: location&.country, + city: location&.city, + state: location&.state, + county: location&.county, + latitude: location&.latitude, + longitude: location&.longitude, + country_code: location&.country_code ) end rescue ActiveRecord::RecordNotUnique diff --git a/config/initializers/geocoder.rb b/config/initializers/geocoder.rb new file mode 100644 index 0000000..aeb30fc --- /dev/null +++ b/config/initializers/geocoder.rb @@ -0,0 +1,30 @@ +Geocoder.configure( + # Geocoding options + timeout: 5, # geocoding service timeout (secs) + lookup: :google, # name of geocoding service (symbol) + ip_lookup: :ipinfo_io, # name of IP address geocoding service (you can choose a service) + language: :en, # ISO-639 language code + + # Use HTTPS for lookup requests + use_https: true, + + # API key for geocoding service + api_key: ENV['GEOCODER_API_KEY'], # Geocoder API key from environment variable + + # Caching + cache: Redis.new, # cache object (e.g. Redis.new) + cache_prefix: "geocoder:", # prefix for cache keys + + # Exceptions that should not be rescued by default + # (if you want to handle them yourself) + always_raise: [ + Geocoder::OverQueryLimitError, + Geocoder::RequestDenied, + Geocoder::InvalidRequest, + Geocoder::InvalidApiKey + ], + + # Calculation options + units: :km, # :km for kilometers or :mi for miles + distances: :linear # :spherical or :linear +) diff --git a/config/initializers/offline_geocoder.rb b/config/initializers/offline_geocoder.rb deleted file mode 100644 index e59fd43..0000000 --- a/config/initializers/offline_geocoder.rb +++ /dev/null @@ -1,2 +0,0 @@ -require 'offline_geocoder' -OFFLINE_GEOCODER = OfflineGeocoder.new \ No newline at end of file