# frozen_string_literal: true namespace :geoip do desc "Update the GeoIP database" task update: :environment do puts "Updating GeoIP database..." success = GeoIpService.update_database! if success puts "✅ GeoIP database successfully updated" else puts "❌ Failed to update GeoIP database" end end desc "Lookup country for a specific IP address" task :lookup, [:ip_address] => :environment do |_t, args| ip_address = args[:ip_address] if ip_address.blank? puts "❌ Please provide an IP address: rails geoip:lookup[8.8.8.8]" exit 1 end puts "Looking up country for #{ip_address}..." begin country = GeoIpService.lookup_country(ip_address) if country.present? puts "📍 #{ip_address} → #{country}" else puts "❓ No country found for #{ip_address}" end rescue => e puts "❌ Error looking up #{ip_address}: #{e.message}" end end desc "Show GeoIP database status" task status: :environment do puts "GeoIP Database Status" puts "=" * 40 geo_service = GeoIpService.new database_info = geo_service.database_info if geo_service.database_available? && database_info puts "✅ Active database found:" puts " Type: #{database_info[:type]}" puts " Version: #{database_info[:version]}" puts " Size: #{number_to_human_size(database_info[:size])}" puts " Modified: #{database_info[:modified_at].strftime('%Y-%m-%d %H:%M:%S UTC')}" puts " Age: #{database_info[:age_days]} days" puts " Path: #{database_info[:file_path]}" puts " Valid: #{geo_service.database_available? ? '✅' : '❌'}" if database_info[:age_days] > Rails.application.config.maxmind.max_age_days puts " ⚠️ Database is outdated (older than #{Rails.application.config.maxmind.max_age_days} days)" end else puts "❌ No active GeoIP database found" puts "" puts "To download the database, run:" puts " rails geoip:update" end puts "" puts "Configuration:" config = Rails.application.config.maxmind puts " Auto-updates: #{config.auto_update_enabled ? '✅' : '❌'}" puts " Update interval: #{config.update_interval_days} days" puts " Max age: #{config.max_age_days} days" puts " Storage path: #{config.storage_path}" end desc "Enrich existing events missing country codes" task enrich_missing: :environment do puts "Finding events without country codes..." events_without_country = Event.where(country_code: [nil, '']) .where.not(ip_address: [nil, '']) .limit(1000) # Process in batches if events_without_country.empty? puts "✅ No events found missing country codes" exit 0 end puts "Found #{events_without_country.count} events without country codes" puts "Processing batch..." geo_service = GeoIpService.new updated_count = 0 events_without_country.find_each do |event| country = geo_service.lookup_country(event.ip_address) if country.present? event.update!(country_code: country) updated_count += 1 end # Add small delay to avoid overwhelming the service sleep(0.01) if updated_count % 100 == 0 end puts "✅ Updated #{updated_count} events with country codes" end desc "Test GeoIP service with sample IPs" task test: :environment do puts "Testing GeoIP service..." puts "=" * 30 test_ips = [ '8.8.8.8', # Google DNS (US) '1.1.1.1', # Cloudflare DNS (US) '208.67.222.222', # OpenDNS (US) '9.9.9.9', # Quad9 DNS (US) '8.8.4.4', # Google DNS (US) '1.0.0.1', # Cloudflare DNS (AU) '64.6.64.6', # Verisign DNS (US) '94.140.14.14', # AdGuard DNS (DE) '2001:4860:4860::8888', # Google DNS IPv6 '2606:4700:4700::1111' # Cloudflare DNS IPv6 ] geo_service = GeoIpService.new if !geo_service.database_available? puts "❌ GeoIP database not available. Please run 'rails geoip:update' first." exit 1 end puts "Database info:" info = geo_service.database_info puts " Type: #{info[:type]}" puts " Version: #{info[:version]}" puts " Size: #{number_to_human_size(info[:size])}" puts "" test_ips.each do |ip| begin country = geo_service.lookup_country(ip) puts "#{ip.ljust(30)} → #{country || 'Unknown'}" rescue => e puts "#{ip.ljust(30)} → Error: #{e.message}" end end end private def number_to_human_size(bytes) units = %w[B KB MB GB TB] size = bytes.to_f unit_index = 0 while size >= 1024 && unit_index < units.length - 1 size /= 1024 unit_index += 1 end "#{size.round(2)} #{units[unit_index]}" end end