Skip to content

Commit

Permalink
offline geocoder
Browse files Browse the repository at this point in the history
  • Loading branch information
loftwah committed Sep 14, 2024
1 parent a5a303b commit ac3202c
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 63 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ gem 'redis', '>= 4.0.1'
gem 'chartkick'
gem 'devise'
gem 'font-awesome-sass', '~> 6.5.2'
gem 'geocoder'
gem 'maxmind-geoip2'
gem 'groupdate'
gem 'mini_magick'
gem 'sidekiq'
Expand Down
27 changes: 22 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ 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)
Expand All @@ -125,6 +124,7 @@ GEM
responders
warden (~> 1.2.3)
diff-lcs (1.5.1)
domain_name (0.6.20240107)
drb (2.2.1)
dry-cli (1.1.0)
erubi (1.13.0)
Expand All @@ -141,18 +141,27 @@ 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)
geocoder (1.8.3)
base64 (>= 0.1.0)
csv (>= 3.0.0)
globalid (1.2.1)
activesupport (>= 6.1)
groupdate (6.4.0)
activesupport (>= 6.1)
http (5.2.0)
addressable (~> 2.8)
base64 (~> 0.1)
http-cookie (~> 1.0)
http-form_data (~> 2.2)
llhttp-ffi (~> 0.5.0)
http-cookie (1.0.7)
domain_name (~> 0.5)
http-form_data (2.3.0)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
importmap-rails (2.0.1)
Expand All @@ -167,6 +176,9 @@ GEM
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jmespath (1.6.2)
llhttp-ffi (0.5.0)
ffi-compiler (~> 1.0)
rake (~> 13.0)
logger (1.6.0)
loofah (2.22.0)
crass (~> 1.0.2)
Expand All @@ -178,6 +190,11 @@ GEM
net-smtp
marcel (1.0.4)
matrix (0.4.2)
maxmind-db (1.2.0)
maxmind-geoip2 (1.2.0)
connection_pool (~> 2.2)
http (>= 4.3, < 6.0)
maxmind-db (~> 1.2)
mini_magick (5.0.1)
mini_mime (1.1.5)
minitest (5.24.1)
Expand Down Expand Up @@ -385,10 +402,10 @@ DEPENDENCIES
devise
factory_bot_rails
font-awesome-sass (~> 6.5.2)
geocoder
groupdate
importmap-rails
jbuilder
maxmind-geoip2
mini_magick
puma (>= 5.0)
rails (~> 7.1.3, >= 7.1.3.4)
Expand Down
10 changes: 0 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,16 +286,6 @@ 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:
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/analytics_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ def fetch_cached_data(key, &block)
def fetch_location_data
@user.page_views.group(:country, :city).count.map do |location, count|
{
country: location[0],
city: location[1],
country: location[0] || 'Unknown', # Fallback to 'Unknown' if no country
city: location[1] || 'Unknown', # Fallback to 'Unknown' if no city
count: count
}
end.sort_by { |location| -location[:count] }.take(10)
end
end

# Update this method to exclude hidden links
def fetch_link_analytics
Expand Down
39 changes: 26 additions & 13 deletions app/middleware/page_view_tracker.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
require 'maxmind/geoip2'

class PageViewTracker
def initialize(app)
@app = app
# Load MaxMind readers for ASN, City, and Country databases
@asn_reader = MaxMind::GeoIP2::Reader.new('db/GeoLite2-ASN.mmdb') # ASN database
@city_reader = MaxMind::GeoIP2::Reader.new('db/GeoLite2-City.mmdb') # City database
@country_reader = MaxMind::GeoIP2::Reader.new('db/GeoLite2-Country.mmdb') # Country database
end

def call(env)
Expand All @@ -25,10 +31,16 @@ def track_page_view(request)
if user
# 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

# Use Geocoder to find the location based on the real IP
location = Geocoder.search(real_ip).first


# ASN lookup
asn_record = @asn_reader.asn(real_ip) rescue nil

# City lookup
city_record = @city_reader.city(real_ip) rescue nil

# Country lookup (fallback if city is not found)
country_record = @country_reader.country(real_ip) rescue nil

PageView.create(
user: user,
path: request.path,
Expand All @@ -37,18 +49,19 @@ def track_page_view(request)
visited_at: Time.current,
ip_address: real_ip,
session_id: request.session[:session_id],
country: location&.country,
city: location&.city,
state: location&.state,
county: location&.county,
latitude: location&.latitude,
longitude: location&.longitude,
country_code: location&.country_code
country: city_record&.country&.iso_code || country_record&.country&.iso_code,
city: city_record&.city&.name,
state: city_record&.subdivisions&.first&.iso_code,
latitude: city_record&.location&.latitude,
longitude: city_record&.location&.longitude,
country_code: city_record&.country&.iso_code || country_record&.country&.iso_code,
asn: asn_record&.autonomous_system_number,
asn_org: asn_record&.autonomous_system_organization
)
end
rescue ActiveRecord::RecordNotUnique
Rails.logger.info "Duplicate page view detected and ignored"
rescue => e
Rails.logger.error "Error tracking page view: #{e.message}"
end
end
end
end
30 changes: 0 additions & 30 deletions config/initializers/geocoder.rb

This file was deleted.

Binary file added db/GeoLite2-ASN.mmdb
Binary file not shown.
Binary file added db/GeoLite2-City.mmdb
Binary file not shown.
Binary file added db/GeoLite2-Country.mmdb
Binary file not shown.
6 changes: 6 additions & 0 deletions db/migrate/20240914124058_add_asn_fields_to_page_views.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddAsnFieldsToPageViews < ActiveRecord::Migration[7.1]
def change
add_column :page_views, :asn, :string
add_column :page_views, :asn_org, :string
end
end
4 changes: 3 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ac3202c

Please sign in to comment.