trackdown 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6bef9cf45c5eb0f1cebf958c00d8b655d0840b07fe3ae3bca3732e0bdd25e2f8
4
+ data.tar.gz: ac99be87d20b6795d7ce156bc9ae50af70e0b4506fa61c00851f5c1abb690e39
5
+ SHA512:
6
+ metadata.gz: e69d703884469e3880eb06472182e00d356884a92089074a9e4ea916b8709d22bb34de22c8d5d37e16d8aada028099f96e22a2bc2a88c6aa10610a99f04c208b
7
+ data.tar.gz: 18c3f1641bcec2facfbefc038d715f434e8a2f9bf5e53b1d83d85ed12d38fa008460bbe936cf47654de2686f6bdb2412fc6a90d2836107e573783e8a9fec435a
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## [0.1.0] - 2024-10-29
2
+
3
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Javi R
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # πŸ“ `trackdown` - Ruby gem to geolocate IPs (MaxMind BYOK)
2
+
3
+ `trackdown` is a Ruby gem that easily allows you to geolocate IP addresses. It's a simple, convenient wrapper on top of MaxMind. Just bring your own MaxMind keys, and you're good to go. It keeps your MaxMind database updated regularly, and it offers a handy API for Rails applications to fetch country, city, and emoji flag information for any IP address.
4
+
5
+ Given an IP, it gives you the corresponding:
6
+ - πŸ—ΊοΈ Country (two-letter country code + country name)
7
+ - πŸ“ City
8
+ - πŸ‡ΊπŸ‡Έ Emoji flag of the country
9
+
10
+ `trackdown` is BYOK (Bring Your Own Key) – you'll need your own MaxMind keys for it to work. It's your responsibility to make sure your app complies with the license for the MaxMind database you're using. Get a MaxMind account and license key at [MaxMind](https://www.maxmind.com/).
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'trackdown'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ ```bash
23
+ bundle install
24
+ ```
25
+
26
+ ## Setup
27
+
28
+ First, run the installation generator:
29
+
30
+ ```bash
31
+ rails generate trackdown:install
32
+ ```
33
+
34
+ This will create an initializer file at `config/initializers/trackdown.rb`. Open this file and add your MaxMind license key and account ID:
35
+
36
+ ```ruby
37
+ Trackdown.configure do |config|
38
+ # Tip: do not write your plaintext keys in the code, use Rails.application.credentials instead
39
+ config.maxmind_account_id = 'your_account_id_here'
40
+ config.maxmind_license_key = 'your_license_key_here'
41
+ end
42
+ ```
43
+
44
+ > [!TIP]
45
+ > To get your MaxMind account ID and license key, you need to create an account at [MaxMind](https://www.maxmind.com/) and get a license key.
46
+
47
+ You can also configure the path where the MaxMind database will be stored. By default, it will be stored at `db/GeoLite2-City.mmdb`:
48
+
49
+ ```ruby
50
+ config.database_path = Rails.root.join('db', 'GeoLite2-City.mmdb').to_s
51
+ ```
52
+
53
+ The generator also creates a `TrackdownDatabaseRefreshJob` job for regularly updating the MaxMind database. You can just get a database the first time and just keep using it, but the information will get outdated and some IPs will become stale or inaccurate.
54
+
55
+ To keep your IP geolocation accurate, you need to make sure the `TrackdownDatabaseRefreshJob` runs regularly. How you do that, exactly, depends on the queueing system you're using.
56
+
57
+ If you're using `solid_queue` (the Rails 8 default), you can easily add it to your schedule in the `config/recurring.yml` file like this:
58
+ ```yaml
59
+ production:
60
+ refresh_maxmind_database:
61
+ class: TrackdownDatabaseRefreshJob
62
+ queue: default
63
+ schedule: every day at 4am US/Pacific
64
+ ```
65
+
66
+ After setting everything up, you can run the following command to update the MaxMind database / get the first fresh copy of it:
67
+
68
+ ```ruby
69
+ Trackdown.update_database
70
+ ```
71
+
72
+ ## Usage
73
+
74
+ To geolocate an IP address:
75
+
76
+ ```ruby
77
+ Trackdown.locate('8.8.8.8').country
78
+ # => 'United States'
79
+ ```
80
+
81
+ You can also do things like:
82
+ ```ruby
83
+ Trackdown.locate('8.8.8.8').emoji
84
+ # => 'πŸ‡ΊπŸ‡Έ'
85
+ ```
86
+
87
+ In fact, there are a few methods you can use:
88
+ ```ruby
89
+ result = Trackdown.locate('8.8.8.8')
90
+
91
+ result.country_code # => 'US'
92
+ result.country_name # => 'United States'
93
+ result.country # => 'United States' (alias for country_name)
94
+ result.country_info # => # A big hash of information about the country, from the `countries` gem
95
+ result.city # => 'Mountain View'
96
+ result.flag_emoji # => 'πŸ‡ΊπŸ‡Έ'
97
+ result.emoji # => 'πŸ‡ΊπŸ‡Έ' (alias for flag_emoji)
98
+ result.country_flag # => 'πŸ‡ΊπŸ‡Έ' (alias for flag_emoji)
99
+ ```
100
+
101
+ For `country_info` we're leveraging the [`countries`](https://github.com/countries/countries) gem, so you get a lot of information about the country, like the continent, the region, the languages spoken, the currency, and more:
102
+
103
+ ```ruby
104
+ result.country_info.alpha3 # => "USA"
105
+ result.country_info.currency_code # => "USD"
106
+ result.country_info.continent # => 'North America'
107
+ result.country_info.nationality # => 'American'
108
+ result.country_info.iso_long_name # => 'The United States of America'
109
+ ```
110
+
111
+ If you prefer, you can also get all the information as a hash:
112
+ ```ruby
113
+ result.to_h
114
+ # => {
115
+ # country_code: 'US',
116
+ # country_name: 'United States',
117
+ # city: 'Mountain View',
118
+ # flag_emoji: 'πŸ‡ΊπŸ‡Έ',
119
+ # country_info: { ... }
120
+ # }
121
+ ```
122
+
123
+ To manually update the MaxMind IP database:
124
+ ```ruby
125
+ Trackdown.update_database
126
+ ```
127
+
128
+
129
+ ## Development
130
+
131
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
132
+
133
+ To install this gem onto your local machine, run `bundle exec rake install`.
134
+
135
+ ## Contributing
136
+
137
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rameerez/trackdown. Our code of conduct is: just be nice and make your mom proud of what you do and post online.
138
+
139
+ ## License
140
+
141
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
@@ -0,0 +1,25 @@
1
+ module Trackdown
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('templates', __dir__)
5
+
6
+ def create_initializer
7
+ template 'trackdown.rb', 'config/initializers/trackdown.rb'
8
+ end
9
+
10
+ def create_database_refresh_job
11
+ template 'trackdown_database_refresh_job.rb', 'app/jobs/trackdown_database_refresh_job.rb'
12
+ end
13
+
14
+ def display_post_install_message
15
+ say "\tThe `trackdown` gem has been successfully installed!", :green
16
+ say "\nTo complete the setup:"
17
+ say " 1. Configure your MaxMind credentials in `config/initializers/trackdown.rb`"
18
+ say " 2. Run 'Trackdown.update_database' to get a fresh MaxMind IP database."
19
+ say " 3. Make sure you configure your queueing system to run the TrackdownDatabaseRefreshJob regularly so the IP database is updated regularly."
20
+ say "\nEnjoy `trackdown`!", :green
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ Trackdown.configure do |config|
4
+ # Required: Your MaxMind credentials
5
+ config.maxmind_account_id = Rails.application.credentials.dig(:maxmind, :account_id)
6
+ config.maxmind_license_key = Rails.application.credentials.dig(:maxmind, :license_key)
7
+
8
+ # Optional: Configure database location (defaults to db/GeoLite2-City.mmdb)
9
+ # config.database_path = Rails.root.join('db', 'GeoLite2-City.mmdb').to_s
10
+
11
+ # Optional: Configure timeouts and pooling (defaults shown)
12
+ # config.timeout = 3 # Timeout for individual lookups
13
+ # config.pool_size = 5 # Size of the connection pool
14
+ # config.pool_timeout = 3 # Timeout when waiting for a connection from the pool
15
+
16
+ # Optional: Configure memory mode (defaults to MODE_MEMORY)
17
+ # config.memory_mode = MaxMind::DB::MODE_FILE # Use MODE_FILE to reduce memory usage
18
+
19
+ # Optional: Configure IP validation (defaults to true)
20
+ # config.reject_private_ips = true # Reject private/local IP addresses
21
+ end
@@ -0,0 +1,7 @@
1
+ class TrackdownDatabaseRefreshJob < ApplicationJob
2
+ queue_as :default
3
+
4
+ def perform(*args)
5
+ Trackdown.update_database
6
+ end
7
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trackdown
4
+ class Configuration
5
+ attr_accessor :maxmind_license_key, :maxmind_account_id, :database_path,
6
+ :timeout, :pool_size, :pool_timeout, :memory_mode,
7
+ :reject_private_ips
8
+
9
+ def initialize
10
+ @maxmind_license_key = nil
11
+ @maxmind_account_id = nil
12
+ @database_path = defined?(Rails) ? Rails.root.join('db', 'GeoLite2-City.mmdb').to_s : 'db/GeoLite2-City.mmdb'
13
+ @timeout = 3 # seconds
14
+ @pool_size = 5
15
+ @pool_timeout = 3 # seconds
16
+ @memory_mode = MaxMind::DB::MODE_MEMORY
17
+ @reject_private_ips = true
18
+ end
19
+
20
+ def validate!
21
+ missing = []
22
+ missing << 'maxmind_license_key' if maxmind_license_key.nil?
23
+ missing << 'maxmind_account_id' if maxmind_account_id.nil?
24
+
25
+ raise Error, "Missing required configuration: #{missing.join(', ')} – Please set these in your config/initializers/trackdown.rb initializer." unless missing.empty?
26
+
27
+ validate_paths!
28
+ validate_timeouts!
29
+ end
30
+
31
+ def reject_private_ips?
32
+ @reject_private_ips
33
+ end
34
+
35
+ private
36
+
37
+ def validate_paths!
38
+ unless database_path && !database_path.empty?
39
+ raise Error, "database_path cannot be empty"
40
+ end
41
+ end
42
+
43
+ def validate_timeouts!
44
+ raise Error, "timeout must be positive" unless timeout.positive?
45
+ raise Error, "pool_timeout must be positive" unless pool_timeout.positive?
46
+ raise Error, "pool_size must be positive" unless pool_size.positive?
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,57 @@
1
+ require 'open-uri'
2
+ require 'zlib'
3
+ require 'rubygems/package'
4
+
5
+ module Trackdown
6
+ class DatabaseUpdater
7
+ DOWNLOAD_URL = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=%{license_key}&suffix=tar.gz"
8
+
9
+ class << self
10
+ def update
11
+ download_url = DOWNLOAD_URL % { license_key: Trackdown.configuration.maxmind_license_key }
12
+
13
+ options = {
14
+ http_basic_authentication: [
15
+ Trackdown.configuration.maxmind_account_id.to_s,
16
+ Trackdown.configuration.maxmind_license_key.to_s
17
+ ],
18
+ ssl_verify_mode: OpenSSL::SSL::VERIFY_PEER
19
+ }
20
+
21
+ URI.open(download_url, **options) do |remote_file|
22
+ Zlib::GzipReader.wrap(remote_file) do |gz|
23
+ Gem::Package::TarReader.new(gz) do |tar|
24
+ tar.each do |entry|
25
+ if entry.full_name.end_with?('.mmdb')
26
+ FileUtils.mkdir_p(File.dirname(Trackdown.configuration.database_path))
27
+
28
+ File.open(Trackdown.configuration.database_path, 'wb') do |file|
29
+ file.write(entry.read)
30
+ end
31
+ break
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ Rails.logger.info("MaxMind database updated successfully") if defined?(Rails)
39
+ true
40
+ rescue OpenURI::HTTPError => e
41
+ message = case e.message
42
+ when /401/
43
+ "Authentication failed. Please check your MaxMind account ID and license key."
44
+ when /403/
45
+ "Access forbidden. Your MaxMind license may not have access to this database."
46
+ else
47
+ "HTTP Error: #{e.message}"
48
+ end
49
+ Rails.logger.error("Error updating MaxMind database: #{message}") if defined?(Rails)
50
+ raise Error, message
51
+ rescue => e
52
+ Rails.logger.error("Error updating MaxMind database: #{e.message}") if defined?(Rails)
53
+ raise Error, "Failed to update database: #{e.message}"
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trackdown
4
+ class Error < StandardError; end
5
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/db'
4
+ require 'connection_pool'
5
+ require_relative 'location_result'
6
+ require_relative 'ip_validator'
7
+
8
+ module Trackdown
9
+ class IpLocator
10
+ class TimeoutError < Trackdown::Error; end
11
+ class DatabaseError < Trackdown::Error; end
12
+
13
+ class << self
14
+ def locate(ip)
15
+ IpValidator.validate!(ip)
16
+
17
+ if Trackdown.configuration.reject_private_ips? && IpValidator.private_ip?(ip)
18
+ raise IpValidator::InvalidIpError, "Private IP addresses are not allowed"
19
+ end
20
+
21
+ record = fetch_record(ip)
22
+ return LocationResult.new(nil, 'Unknown', 'Unknown', '🏳️') if record.nil?
23
+
24
+ country_code = extract_country_code(record)
25
+ country_name = extract_country_name(record)
26
+ city = extract_city(record)
27
+ flag_emoji = get_emoji_flag(country_code)
28
+
29
+ LocationResult.new(country_code, country_name, city, flag_emoji)
30
+ end
31
+
32
+ private
33
+
34
+ def fetch_record(ip)
35
+ Trackdown.ensure_database_exists!
36
+
37
+ Timeout.timeout(Trackdown.configuration.timeout) do
38
+ reader_pool.with do |reader|
39
+ reader.get(ip)
40
+ end
41
+ end
42
+ rescue Timeout::Error
43
+ raise TimeoutError, "MaxMind database lookup timed out after #{Trackdown.configuration.timeout} seconds"
44
+ rescue Trackdown::Error => e
45
+ raise e
46
+ rescue StandardError => e
47
+ Rails.logger.error("Error fetching IP data: #{e.message}") if defined?(Rails)
48
+ raise DatabaseError, "Database error: #{e.message}"
49
+ end
50
+
51
+ def reader_pool
52
+ @reader_pool ||= ConnectionPool.new(
53
+ size: Trackdown.configuration.pool_size,
54
+ timeout: Trackdown.configuration.pool_timeout
55
+ ) do
56
+ MaxMind::DB.new(
57
+ Trackdown.configuration.database_path,
58
+ mode: Trackdown.configuration.memory_mode
59
+ )
60
+ end
61
+ end
62
+
63
+ def extract_country_code(record)
64
+ record&.dig('country', 'iso_code')
65
+ end
66
+
67
+ def extract_country_name(record)
68
+ record&.dig('country', 'names', 'en') ||
69
+ (record&.dig('country', 'names')&.values&.first) ||
70
+ 'Unknown'
71
+ end
72
+
73
+ def extract_city(record)
74
+ record&.dig('city', 'names', 'en') ||
75
+ (record&.dig('city', 'names')&.values&.first) ||
76
+ 'Unknown'
77
+ end
78
+
79
+ def get_emoji_flag(country_code)
80
+ country_code ? country_code.tr('A-Z', "\u{1F1E6}-\u{1F1FF}") : "🏳️"
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ipaddr'
4
+
5
+ module Trackdown
6
+ class IpValidator
7
+ class InvalidIpError < Trackdown::Error; end
8
+
9
+ def self.validate!(ip)
10
+ return if ip.nil?
11
+
12
+ begin
13
+ IPAddr.new(ip.to_s)
14
+ rescue IPAddr::InvalidAddressError
15
+ raise InvalidIpError, "Invalid IP address format: #{ip}"
16
+ end
17
+ end
18
+
19
+ def self.private_ip?(ip)
20
+ addr = IPAddr.new(ip.to_s)
21
+ addr.private? || addr.loopback?
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'countries'
4
+
5
+ module Trackdown
6
+ class LocationResult
7
+ attr_reader :country_code, :country_name, :city, :flag_emoji
8
+
9
+ def initialize(country_code, country_name, city, flag_emoji)
10
+ @country_code = country_code
11
+ @country_name = country_name
12
+ @city = city
13
+ @flag_emoji = flag_emoji
14
+ end
15
+
16
+ alias_method :country, :country_name
17
+ alias_method :emoji, :flag_emoji
18
+ alias_method :emoji_flag, :flag_emoji
19
+ alias_method :country_flag, :flag_emoji
20
+
21
+ def country_info
22
+ return nil unless country_code
23
+ ISO3166::Country.new(country_code)
24
+ end
25
+
26
+ def to_h
27
+ {
28
+ country_code: @country_code,
29
+ country_name: @country_name,
30
+ city: @city,
31
+ flag_emoji: @flag_emoji,
32
+ country_info: country_info&.data || {}
33
+ }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trackdown
4
+ VERSION = "0.1.0"
5
+ end
data/lib/trackdown.rb ADDED
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "trackdown/error"
4
+ require_relative "trackdown/version"
5
+ require_relative "trackdown/configuration"
6
+ require_relative "trackdown/ip_validator"
7
+ require_relative "trackdown/ip_locator"
8
+ require_relative "trackdown/database_updater"
9
+ require_relative "trackdown/location_result"
10
+
11
+ module Trackdown
12
+ class << self
13
+ attr_writer :configuration
14
+ end
15
+
16
+ def self.configuration
17
+ @configuration ||= Configuration.new
18
+ end
19
+
20
+ def self.configure
21
+ yield(configuration)
22
+ configuration.validate!
23
+ end
24
+
25
+ def self.locate(ip)
26
+ ensure_database_exists!
27
+ IpLocator.locate(ip)
28
+ end
29
+
30
+ def self.update_database
31
+ DatabaseUpdater.update
32
+ end
33
+
34
+ def self.database_exists?
35
+ File.exist?(configuration.database_path)
36
+ end
37
+
38
+ def self.ensure_database_exists!
39
+ unless database_exists?
40
+ raise Error, "MaxMind database not found. Please set your MaxMind keys in config/initializers/trackdown.rb as described in the `trackdown` gem README, and then run Trackdown.update_database to download the MaxMind IP geolocation database."
41
+ end
42
+ end
43
+ end
data/sig/trackdown.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Trackdown
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trackdown
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - rameerez
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-10-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: maxmind-db
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: connection_pool
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: countries
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '7.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '7.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '13.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '13.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.21'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.21'
97
+ description: Trackdown is a Ruby gem that easily allows you to geolocate IP addresses.
98
+ It's a simple, convenient wrapper on top of the MaxMind database. Plug your MaxMind
99
+ license key and you're good to go. It keeps your MaxMind database updated regularly,
100
+ and it offers a handy API for Rails applications to fetch country, city, and emoji
101
+ flag information for any IP address.
102
+ email:
103
+ - rubygems@rameerez.com
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files: []
107
+ files:
108
+ - CHANGELOG.md
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - lib/generators/trackdown/install_generator.rb
113
+ - lib/generators/trackdown/templates/trackdown.rb
114
+ - lib/generators/trackdown/templates/trackdown_database_refresh_job.rb
115
+ - lib/trackdown.rb
116
+ - lib/trackdown/configuration.rb
117
+ - lib/trackdown/database_updater.rb
118
+ - lib/trackdown/error.rb
119
+ - lib/trackdown/ip_locator.rb
120
+ - lib/trackdown/ip_validator.rb
121
+ - lib/trackdown/location_result.rb
122
+ - lib/trackdown/version.rb
123
+ - sig/trackdown.rbs
124
+ homepage: https://github.com/rameerez/trackdown
125
+ licenses:
126
+ - MIT
127
+ metadata:
128
+ allowed_push_host: https://rubygems.org
129
+ homepage_uri: https://github.com/rameerez/trackdown
130
+ source_code_uri: https://github.com/rameerez/trackdown
131
+ changelog_uri: https://github.com/rameerez/trackdown/blob/main/CHANGELOG.md
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: 3.0.0
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubygems_version: 3.5.16
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Get country, city, and emoji flag information for IP addresses using a MaxMind
151
+ database
152
+ test_files: []