ip_lookup 1.0.1

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: 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: []