ip_lookup 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3fc773650faa6ffc425dca036e1e2ca80bacafd51548eb16754720ca8c5b07ec
4
+ data.tar.gz: b260b88a05a4366df81d10a5d44271c8d7c11d0650c3997d76e242d64003f3f2
5
+ SHA512:
6
+ metadata.gz: 4b2c9138cde92e92ef7e795a3845c5e8a4fb097b7a236d83085cd00ef9270be86d32adc780c4b538d27594736dcd80aff82c2b04f07de46cc76ad01ef6daab6e
7
+ data.tar.gz: 3dec5779bc48e845223983eacc66050abc6e5e37e6d78d7f6c6f94ec616fbc932982555c777e6ff9e7c6fe6fb699ef2b040f6c482bbe1459ce97bc7680900ed2
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # IPLookup
2
+
3
+ IPLookup uses [GeoIP2 MaxMind DB](http://maxmind.github.io/MaxMind-DB/) to lookup the country, timezone, coordinates and subdivision for a given ip address.
4
+
5
+ ## Dependencies
6
+
7
+ * Uses the gem [maxminddb](https://github.com/yhirose/maxminddb) as a database reader.
8
+ * Uses the gem [TZInfo](https://github.com/tzinfo/tzinfo) for timezone lookup.
9
+ * Uses the gem [Zlib](https://github.com/ruby/zlib) to decompress database file.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'ip_lookup'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install ip_lookup
24
+
25
+ ### Configuration
26
+
27
+ Before using the gem the db file needs to be downloaded / updated.
28
+
29
+
30
+ ```ruby
31
+ # download / update database
32
+ IPLookup.DB.update update_period: 30, update_uri: "http://path_to_database_GeoLite2-City.mmdb.gz"
33
+ ```
34
+
35
+ - default update_period (in days): 30
36
+ - default update_uri: http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz
37
+
38
+ *NOTE: The gem provides a RubyGems post-install hook to download / update the db.*
39
+
40
+ ### Usage
41
+
42
+ ```ruby
43
+ ip_lookup = IPLookup.new "213.61.214.178", silent_exceptions: false
44
+
45
+ ip_lookup.country
46
+ # => "de"
47
+
48
+ ip_lookup.timezone
49
+ # => "Europe/Berlin"
50
+
51
+ ip_lookup.coordinates
52
+ # => [51.2993, 9.491]
53
+
54
+ ip_lookup.subdivision
55
+ # => "be"
56
+ ```
57
+
58
+ *Defaults:*
59
+ - silent_exceptions: false
60
+
61
+ ## Development
62
+
63
+ 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.
64
+
65
+ To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
66
+
67
+ ## License
68
+
69
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
70
+
71
+ ## Code of Conduct
72
+
73
+ Everyone interacting in the IPLookup project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/blinkist/ip-lookup/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "rubocop/rake_task"
4
+
5
+ RuboCop::RakeTask.new
6
+ RSpec::Core::RakeTask.new :spec
7
+
8
+ task default: %i[rubocop spec]
data/lib/ip-lookup.rb ADDED
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "maxminddb"
4
+ require "tzinfo"
5
+
6
+ require_relative "ip_lookup/db"
7
+ require_relative "ip_lookup/defaults"
8
+ require_relative "ip_lookup/errors"
9
+
10
+ class IPLookup
11
+ attr_reader :result
12
+ attr_reader :silent_exceptions
13
+
14
+ def initialize(ip_address, silent_exceptions: false)
15
+ @silent_exceptions = silent_exceptions
16
+ @result = DB.new(silent_exceptions).lookup(ip_address)
17
+ end
18
+
19
+ def country
20
+ error_handler(DEFAULT_COUNTRY) do
21
+ iso_code = result.country.iso_code
22
+ iso_code ? iso_code.downcase : DEFAULT_COUNTRY
23
+ end
24
+ end
25
+
26
+ def timezone
27
+ error_handler(DEFAULT_TIMEZONE) do
28
+ timezone = result.location.time_zone
29
+
30
+ timezone ||= timezone_for result.country.iso_code if result.country.iso_code
31
+
32
+ timezone || DEFAULT_TIMEZONE
33
+ end
34
+ end
35
+
36
+ def coordinates
37
+ error_handler(DEFAULT_COORDINATES) do
38
+ [result.location.latitude, result.location.longitude]
39
+ end
40
+ end
41
+
42
+ def subdivision
43
+ error_handler(DEFAULT_SUBDIVISION) do
44
+ result.subdivisions.any? ? result.subdivisions.first.iso_code.downcase : DEFAULT_SUBDIVISION
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def timezone_for(iso_code)
51
+ tz = TZInfo::Country.get iso_code
52
+ tz.zone_identifiers.first if tz.zone_identifiers.any?
53
+ end
54
+
55
+ def error_handler(default)
56
+ result&.found? ? yield : default
57
+ rescue IPAddr::InvalidAddressError, IPAddr::AddressFamilyError
58
+ raise e unless silent_exceptions
59
+
60
+ default
61
+ end
62
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+ require "net/http"
5
+
6
+ class IPLookup
7
+ class DB
8
+ DEFAULT_UPDATE_PERIOD_IN_DAYS = 30
9
+ DEFAULT_UPDATE_URI = "https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz"
10
+
11
+ attr_reader :silent_exceptions
12
+
13
+ def initialize(silent_exceptions)
14
+ @silent_exceptions = silent_exceptions
15
+ end
16
+
17
+ def lookup(ip_address)
18
+ db.lookup ip_address
19
+ rescue Errno::ENOENT
20
+ raise DBFileNotFoundError, "Couldn't find DB file. Please update DB before using lookup." unless silent_exceptions
21
+ end
22
+
23
+ def self.mutex
24
+ @mutex ||= Mutex.new
25
+ end
26
+
27
+ private
28
+
29
+ def db
30
+ self.class.mutex.synchronize do
31
+ @db ||= begin
32
+ MaxMindDB.new self.class.db_path
33
+ end
34
+ end
35
+ end
36
+
37
+ class << self
38
+ def update(update_period: DEFAULT_UPDATE_PERIOD_IN_DAYS, update_uri: DEFAULT_UPDATE_URI)
39
+ return unless update_db? update_period
40
+
41
+ save_db fetch_db(update_uri)
42
+ end
43
+
44
+ def fetch_db(update_uri)
45
+ uri = URI(update_uri)
46
+
47
+ response = Net::HTTP.get(uri)
48
+
49
+ sio_response = StringIO.new(response)
50
+ gz = Zlib::GzipReader.new(sio_response)
51
+ gz.read
52
+ end
53
+
54
+ def save_db(result)
55
+ File.open(db_path, 'w') do |file|
56
+ flock(file) do |f|
57
+ f.write(result)
58
+ end
59
+ end
60
+ end
61
+
62
+ def flock(file)
63
+ # return and don't update db if file is locked, because db is already been updated
64
+ return unless file.flock(File::LOCK_EX | File::LOCK_NB)
65
+
66
+ if file.flock(File::LOCK_EX)
67
+ begin
68
+ yield file
69
+ ensure
70
+ file.flock(File::LOCK_UN)
71
+ end
72
+ end
73
+ end
74
+
75
+ def update_db?(update_period)
76
+ !db_exists? || (update_period >= 0 && db_age > update_period)
77
+ end
78
+
79
+ def db_exists?
80
+ File.file? db_path
81
+ end
82
+
83
+ def db_age
84
+ (Time.now - File.mtime(db_path)) / (24 * 60 * 60)
85
+ end
86
+
87
+ def db_path
88
+ File.join(Gem.loaded_specs["ip_lookup"].full_gem_path, "/support/geolite-city.mmdb")
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class IPLookup
4
+ DEFAULT_COUNTRY = "us"
5
+ DEFAULT_TIMEZONE = "America/Swift_Current"
6
+ DEFAULT_COORDINATES = [40.0, 74.0].freeze # NYC
7
+ DEFAULT_SUBDIVISION = nil
8
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class IPLookup
4
+ class DBFileNotFoundError < StandardError; end
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class IPLookup
4
+ VERSION = "1.0.1"
5
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "ip_lookup"
2
+
3
+ Gem.post_install do
4
+ puts "Started IPLookup database update."
5
+
6
+ IpLookup.DB.update
7
+
8
+ puts "Finished IPLookup database update."
9
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ip_lookup
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ole Richter
8
+ - Tomek Poderski
9
+ - Sebastian Schleicher
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2018-08-13 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: maxminddb
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: tzinfo
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: zlib
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: bundler
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '1.16'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '1.16'
71
+ - !ruby/object:Gem::Dependency
72
+ name: byebug
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: json
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: rake
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: '10.0'
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: '10.0'
113
+ - !ruby/object:Gem::Dependency
114
+ name: rspec
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '3.0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - "~>"
125
+ - !ruby/object:Gem::Version
126
+ version: '3.0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: rubocop
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ description: IPLookup uses GeoIP2 MaxMind DB to lookup the country, timezone, coordinates
142
+ and locale for ip adresses.
143
+ email:
144
+ - ole@blinkist.com
145
+ - tomek@blinkist.com
146
+ - sj@blinkist.com
147
+ executables: []
148
+ extensions: []
149
+ extra_rdoc_files: []
150
+ files:
151
+ - README.md
152
+ - Rakefile
153
+ - lib/ip-lookup.rb
154
+ - lib/ip_lookup/db.rb
155
+ - lib/ip_lookup/defaults.rb
156
+ - lib/ip_lookup/errors.rb
157
+ - lib/ip_lookup/version.rb
158
+ - lib/rubygems_plugin.rb
159
+ homepage: https://github.com/blinkist/ip-lookup
160
+ licenses:
161
+ - MIT
162
+ metadata: {}
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements: []
178
+ rubyforge_project:
179
+ rubygems_version: 2.7.7
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: IPLookup uses GeoIP2 MaxMind DB to lookup the country, timezone, coordinates
183
+ and locale for ip adresses.
184
+ test_files: []