maxmind-geoip2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake/testtask'
4
+ require 'rubocop/rake_task'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'test'
8
+ end
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ desc 'Run tests and RuboCop'
13
+ task default: :test
14
+ task default: :rubocop
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/reader'
4
+
5
+ # rubocop:disable Style/ClassAndModuleChildren
6
+ # :nodoc: all
7
+ module MaxMind
8
+ module GeoIP2
9
+ module Record # :nodoc:
10
+ end
11
+
12
+ module Model # :nodoc:
13
+ end
14
+ end
15
+ end
16
+ # rubocop:enable Style/ClassAndModuleChildren
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MaxMind::GeoIP2
4
+ # An AddressNotFoundError means the IP address was not found in the database.
5
+ class AddressNotFoundError < RuntimeError
6
+ end
7
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/country'
4
+ require 'maxmind/geoip2/record/city'
5
+ require 'maxmind/geoip2/record/location'
6
+ require 'maxmind/geoip2/record/postal'
7
+ require 'maxmind/geoip2/record/subdivision'
8
+
9
+ module MaxMind::GeoIP2::Model
10
+ # Model class for the data returned by the GeoIP2 City web service and
11
+ # database. It is also used for GeoLite2 City lookups.
12
+ #
13
+ # The only difference between the City and Insights model classes is which
14
+ # fields in each record may be populated. See
15
+ # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
16
+ #
17
+ # See Country for inherited methods.
18
+ class City < Country
19
+ # City data for the IP address. See MaxMind::GeoIP2::Record::City.
20
+ attr_reader :city
21
+
22
+ # Location data for the IP address. See MaxMind::GeoIP2::Record::Location.
23
+ attr_reader :location
24
+
25
+ # Postal data for the IP address. See MaxMind::GeoIP2::Record::Postal.
26
+ attr_reader :postal
27
+
28
+ # An array of MaxMind::GeoIP2::Record::Subdivision objects representing the
29
+ # country subdivisions for the IP address. The number and type of
30
+ # subdivisions varies by country, but a subdivision is typically a state,
31
+ # province, country, etc. Subdivisions are ordered from most general
32
+ # (largest) to most specific (smallest). If the response did not contain
33
+ # any subdivisions, this attribute will be an empty array.
34
+ attr_reader :subdivisions
35
+
36
+ def initialize(record, locales) # :nodoc:
37
+ super(record, locales)
38
+ @city = MaxMind::GeoIP2::Record::City.new(record['city'], locales)
39
+ @location = MaxMind::GeoIP2::Record::Location.new(record['location'])
40
+ @postal = MaxMind::GeoIP2::Record::Postal.new(record['postal'])
41
+ @subdivisions = create_subdivisions(record['subdivisions'], locales)
42
+ end
43
+
44
+ # Return an object representing the most specific subdivision returned. If
45
+ # the response did not contain any subdivisions, this method returns nil.
46
+ def most_specific_subdivision
47
+ @subdivisions.last
48
+ end
49
+
50
+ private
51
+
52
+ def create_subdivisions(subdivisions, locales)
53
+ return [] if subdivisions.nil?
54
+
55
+ subdivisions.map do |s|
56
+ MaxMind::GeoIP2::Record::Subdivision.new(s, locales)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/record/continent'
4
+ require 'maxmind/geoip2/record/country'
5
+ require 'maxmind/geoip2/record/represented_country'
6
+ require 'maxmind/geoip2/record/traits'
7
+
8
+ module MaxMind::GeoIP2::Model
9
+ # Model class for the data returned by the GeoIP2 Country web service and
10
+ # database. It is also used for GeoLite2 Country lookups.
11
+ class Country
12
+ # Continent data for the IP address. See MaxMind::GeoIP2::Record::Continent.
13
+ attr_reader :continent
14
+
15
+ # Country data for the IP address. This object represents the country where
16
+ # MaxMind believes the end user is located. See
17
+ # MaxMind::GeoIP2::Record::Country.
18
+ attr_reader :country
19
+
20
+ # Registered country data for the IP address. This record represents the
21
+ # country where the ISP has registered a given IP block and may differ from
22
+ # the user's country. See MaxMind::GeoIP2::Record::Country.
23
+ attr_reader :registered_country
24
+
25
+ # Represented country data for the IP address. The represented country is
26
+ # used for things like military bases. It is only present when the
27
+ # represented country differs from the country. See
28
+ # MaxMind::GeoIP2::Record::RepresentedCountry.
29
+ attr_reader :represented_country
30
+
31
+ # Data for the traits of the IP address. See
32
+ # MaxMind::GeoIP2::Record::Traits.
33
+ attr_reader :traits
34
+
35
+ def initialize(record, locales) # :nodoc:
36
+ @continent = MaxMind::GeoIP2::Record::Continent.new(
37
+ record['continent'],
38
+ locales,
39
+ )
40
+ @country = MaxMind::GeoIP2::Record::Country.new(
41
+ record['country'],
42
+ locales,
43
+ )
44
+ @registered_country = MaxMind::GeoIP2::Record::Country.new(
45
+ record['registered_country'],
46
+ locales,
47
+ )
48
+ @represented_country = MaxMind::GeoIP2::Record::RepresentedCountry.new(
49
+ record['represented_country'],
50
+ locales,
51
+ )
52
+ @traits = MaxMind::GeoIP2::Record::Traits.new(record['traits'])
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/model/city'
4
+
5
+ module MaxMind::GeoIP2::Model
6
+ # Model class for the data returned by GeoIP2 Enterprise database lookups.
7
+ #
8
+ # The only difference between the City and Insights model classes is which
9
+ # fields in each record may be populated. See
10
+ # https://dev.maxmind.com/geoip/geoip2/web-services for more details.
11
+ #
12
+ # See City for inherited methods.
13
+ class Enterprise < City
14
+ end
15
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/db'
4
+ require 'maxmind/geoip2/errors'
5
+ require 'maxmind/geoip2/model/city'
6
+ require 'maxmind/geoip2/model/country'
7
+ require 'maxmind/geoip2/model/enterprise'
8
+
9
+ module MaxMind::GeoIP2
10
+ # Reader is a reader for the GeoIP2/GeoLite2 database format. IP addresses
11
+ # can be looked up using the database specific methods.
12
+ #
13
+ # == Example
14
+ #
15
+ # require 'maxmind/geoip2'
16
+ #
17
+ # reader = MaxMind::GeoIP2::Reader.new('GeoIP2-Country.mmdb')
18
+ #
19
+ # record = reader.country('1.2.3.4')
20
+ # puts record.country.iso_code
21
+ #
22
+ # reader.close
23
+ class Reader
24
+ # Create a Reader for looking up IP addresses in a GeoIP2/GeoLite2 database
25
+ # file.
26
+ #
27
+ # If you're performing multiple lookups, it's most efficient to create one
28
+ # Reader and reuse it.
29
+ #
30
+ # Once created, the Reader is safe to use for lookups from multiple
31
+ # threads. It is safe to use after forking only if you use
32
+ # MaxMind::DB::MODE_MEMORY or if your version of Ruby supports IO#pread.
33
+ #
34
+ # Creating the Reader may raise an exception if initialization fails.
35
+ #
36
+ # +database+ is a path to a GeoIP2/GeoLite2 database file.
37
+ #
38
+ # +locales+ is a list of locale codes to use in the name property from most
39
+ # preferred to least preferred.
40
+ #
41
+ # +options+ is an option hash where each key is a symbol. The options
42
+ # control the behavior of the Reader.
43
+ #
44
+ # The available options are:
45
+ #
46
+ # [+:mode+] defines how to open the database. It may be one of
47
+ # MaxMind::DB::MODE_AUTO, MaxMind::DB::MODE_FILE, or
48
+ # MaxMind::DB::MODE_MEMORY. If you don't provide one, the Reader uses
49
+ # MaxMind::DB::MODE_AUTO. Refer to the definition of those constants
50
+ # in MaxMind::DB for an explanation of their meaning.
51
+ #
52
+ # === Exceptions
53
+ #
54
+ # Raises a MaxMind::DB::InvalidDatabaseError if the database is corrupt or
55
+ # invalid. It can raise other exceptions, such as ArgumentError, if other
56
+ # errors occur.
57
+ def initialize(database, locales = ['en'], options = {})
58
+ @reader = MaxMind::DB.new(database, options)
59
+ @type = @reader.metadata.database_type
60
+ locales = ['en'] if locales.empty?
61
+ @locales = locales
62
+ end
63
+
64
+ # Look up the +ip_address+ in the database and returns a
65
+ # MaxMind::GeoIP2::Model::City object.
66
+ #
67
+ # +ip_address+ is a string in the standard notation. It may be IPv4 or
68
+ # IPv6.
69
+ #
70
+ # === Exceptions
71
+ #
72
+ # Raises an ArgumentError if used against a non-City database or if you
73
+ # attempt to look up an IPv6 address in an IPv4 only database.
74
+ #
75
+ # Raises an AddressNotFoundError if +ip_address+ is not found in the
76
+ # database.
77
+ #
78
+ # Raises a MaxMind::DB::InvalidDatabaseError if the database appears
79
+ # corrupt.
80
+ def city(ip_address)
81
+ model_for(Model::City, 'city', 'City', ip_address)
82
+ end
83
+
84
+ # Look up the +ip_address+ in the database and returns a
85
+ # MaxMind::GeoIP2::Model::Country object.
86
+ #
87
+ # +ip_address+ is a string in the standard notation. It may be IPv4 or
88
+ # IPv6.
89
+ #
90
+ # === Exceptions
91
+ #
92
+ # Raises an ArgumentError if used against a non-Country database or if you
93
+ # attempt to look up an IPv6 address in an IPv4 only database.
94
+ #
95
+ # Raises an AddressNotFoundError if +ip_address+ is not found in the
96
+ # database.
97
+ #
98
+ # Raises a MaxMind::DB::InvalidDatabaseError if the database appears
99
+ # corrupt.
100
+ def country(ip_address)
101
+ model_for(Model::Country, 'country', 'Country', ip_address)
102
+ end
103
+
104
+ # Look up the +ip_address+ in the database and returns a
105
+ # MaxMind::GeoIP2::Model::Enterprise object.
106
+ #
107
+ # +ip_address+ is a string in the standard notation. It may be IPv4 or
108
+ # IPv6.
109
+ #
110
+ # === Exceptions
111
+ #
112
+ # Raises an ArgumentError if used against a non-Enterprise database or if
113
+ # you attempt to look up an IPv6 address in an IPv4 only database.
114
+ #
115
+ # Raises an AddressNotFoundError if +ip_address+ is not found in the
116
+ # database.
117
+ #
118
+ # Raises a MaxMind::DB::InvalidDatabaseError if the database appears
119
+ # corrupt.
120
+ def enterprise(ip_address)
121
+ model_for(Model::Enterprise, 'enterprise', 'Enterprise', ip_address)
122
+ end
123
+
124
+ # Return the metadata associated with the database as a
125
+ # MaxMind::DB::Metadata object.
126
+ def metadata
127
+ @reader.metadata
128
+ end
129
+
130
+ # Close the Reader and return resources to the system.
131
+ #
132
+ # There is no useful return value. #close raises an exception if there is
133
+ # an error.
134
+ def close
135
+ @reader.close
136
+ end
137
+
138
+ private
139
+
140
+ def model_for(model_class, method, type, ip_address)
141
+ if !@type.include?(type)
142
+ raise ArgumentError,
143
+ "The #{method} method cannot be used with the #{@type} database."
144
+ end
145
+
146
+ record, prefix_length = @reader.get_with_prefix_length(ip_address)
147
+
148
+ if record.nil?
149
+ raise AddressNotFoundError,
150
+ "The address #{ip_address} is not in the database."
151
+ end
152
+
153
+ record['traits'] = {} if !record.key?('traits')
154
+ record['traits']['ip_address'] = ip_address
155
+ record['traits']['prefix_length'] = prefix_length
156
+
157
+ model_class.new(record, @locales)
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MaxMind::GeoIP2::Record
4
+ class Abstract # :nodoc:
5
+ def initialize(record)
6
+ @record = record
7
+ end
8
+
9
+ protected
10
+
11
+ def get(key)
12
+ if @record.nil? || !@record.key?(key)
13
+ return false if key.start_with?('is_')
14
+
15
+ return nil
16
+ end
17
+
18
+ @record[key]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/record/place'
4
+
5
+ module MaxMind::GeoIP2::Record
6
+ # City-level data associated with an IP address.
7
+ #
8
+ # This record is returned by all location services and databases besides
9
+ # Country.
10
+ #
11
+ # See Place for inherited methods.
12
+ class City < Place
13
+ # A value from 0-100 indicating MaxMind's confidence that the city is
14
+ # correct. This attribute is only available from the Insights service and
15
+ # the GeoIP2 Enterprise database. Integer but may be nil.
16
+ def confidence
17
+ get('confidence')
18
+ end
19
+
20
+ # The GeoName ID for the city. This attribute is returned by all location
21
+ # services and databases. Integer but may be nil.
22
+ def geoname_id
23
+ get('geoname_id')
24
+ end
25
+
26
+ # A Hash where the keys are locale codes (Strings) and the values are names
27
+ # (Strings). This attribute is returned by all location services and
28
+ # databases. Hash but may be nil.
29
+ def names
30
+ get('names')
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/record/place'
4
+
5
+ module MaxMind::GeoIP2::Record
6
+ # Contains data for the continent record associated with an IP address.
7
+ #
8
+ # This record is returned by all location services and databases.
9
+ #
10
+ # See Place for inherited methods.
11
+ class Continent < Place
12
+ # A two character continent code like "NA" (North America) or "OC"
13
+ # (Oceania). This attribute is returned by all location services and
14
+ # databases. String but may be nil.
15
+ def code
16
+ get('code')
17
+ end
18
+
19
+ # The GeoName ID for the continent. This attribute is returned by all
20
+ # location services and databases. String but may be nil.
21
+ def geoname_id
22
+ get('geoname_id')
23
+ end
24
+
25
+ # A Hash where the keys are locale codes (Strings) and the values are names
26
+ # (Strings). This attribute is returned by all location services and
27
+ # databases. Hash but may be nil.
28
+ def names
29
+ get('names')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'maxmind/geoip2/record/place'
4
+
5
+ module MaxMind::GeoIP2::Record
6
+ # Contains data for the country record associated with an IP address.
7
+ #
8
+ # This record is returned by all location services and databases.
9
+ #
10
+ # See Place for inherited methods.
11
+ class Country < Place
12
+ # A value from 0-100 indicating MaxMind's confidence that the country is
13
+ # correct. This attribute is only available from the Insights service and
14
+ # the GeoIP2 Enterprise database. Integer but may be nil.
15
+ def confidence
16
+ get('confidence')
17
+ end
18
+
19
+ # The GeoName ID for the country. This attribute is returned by all
20
+ # location services and databases. Integer but may be nil.
21
+ def geoname_id
22
+ get('geoname_id')
23
+ end
24
+
25
+ # This is true if the country is a member state of the European Union. This
26
+ # attribute is returned by all location services and databases. Boolean.
27
+ def in_european_union?
28
+ get('is_in_european_union')
29
+ end
30
+
31
+ # The two-character ISO 3166-1 alpha code for the country. See
32
+ # https://en.wikipedia.org/wiki/ISO_3166-1. This attribute is returned by
33
+ # all location services and databases. String but may be nil.
34
+ def iso_code
35
+ get('iso_code')
36
+ end
37
+
38
+ # A Hash where the keys are locale codes (Strings) and the values are names
39
+ # (Strings). This attribute is returned by all location services and
40
+ # databases. Hash but may be nil.
41
+ def names
42
+ get('names')
43
+ end
44
+ end
45
+ end