locality 0.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
+ SHA1:
3
+ metadata.gz: cc08ca579c909a36f517e55af8c15dbc8b3e7bf6
4
+ data.tar.gz: 5eb0d6c9e2e211110857db7fb3be22e4d22fb1f3
5
+ SHA512:
6
+ metadata.gz: 5d1b4079773f7ec8b22c2687a9e10ca2861eba4f8bb48a9512a1ee0b016af10b5deee0e20c4ccb88d489d7eb5009fcdd203441a1106ddc6b2d867ff2d37c31bc
7
+ data.tar.gz: 1f3157cf23f35c5b8a221631dcc8fd5c717c92167013c1bfe67b2cc945d16eac5bd985c39669d45c233ed0573c5756bb3bfaaee96e7abb2f6574b074c86b099d
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # Locality
2
+
3
+ ## Swedish A-Region
4
+
5
+ See https://sv.wikipedia.org/wiki/A-region
6
+
7
+ ### Installation
8
+
9
+ ```bash
10
+ # Go and buy the rec2LK database from postnummerservice.se
11
+ # Put it in the ./db directory
12
+ ```
13
+
14
+ ### Configuration
15
+
16
+ ```ruby
17
+ Locality.configure do |config|
18
+
19
+ # By default, locality will look for the rec2LK database in
20
+ # these locations: `Locality.config.postnummerfilen_paths`
21
+ # You can add a custom location like so:
22
+ config.postnummerfilen_path = '/some/custom/rec2LK.csv'
23
+
24
+ end
25
+
26
+ ```
27
+ ### Usage
28
+
29
+ ```ruby
30
+ lookup = Locality::Aregion.new 21 # Gotland
31
+
32
+ lookup.zip_codes # => Array of Integers
33
+ # More to come...
34
+ ```
35
+
36
+ ## IP Lookup
37
+
38
+ ### Installation
39
+
40
+ ```bash
41
+ # Get the libmaxminddb, e.g. via homebrew on Mac OS
42
+ brew install libmaxminddb
43
+ # Tell bundler where to find it
44
+ bundle config build.hive_geoip2 --with-opt-dir=$(brew --prefix)
45
+ # Download and extract the MaxMind GeoIp2 database
46
+ curl http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz -o ./db && gunzip ./db/GeoLite2-City.mmdb.gz
47
+ ```
48
+
49
+ ### Configuration
50
+
51
+ ```ruby
52
+ Locality.configure do |config|
53
+
54
+ # By default, locality will look for the maxmind database in
55
+ # these locations: `Locality.config.maxmind_geoip2_path`
56
+ # You can add a custom location like so:
57
+ config.maxmind_geoip2_path = '/some/custom/maxmind_geolite2.mmdb'
58
+
59
+ # If you want, you can add custom lookups like so:
60
+ config.add_custom_ip_location '198.51.100.99/24', city_name: 'Main Office', country_name: 'Australia'
61
+ end
62
+ ```
63
+
64
+ ### Usage
65
+
66
+ ```ruby
67
+ lookup = Locality::IP.new '198.51.100.55'
68
+
69
+ # All these attributes return either a String or nil.
70
+ lookup.ip
71
+ lookup.city_name
72
+ lookup.province_name
73
+ lookup.state_name
74
+ lookup.country_name
75
+ lookup.human_readable_name
76
+
77
+ # Get them all combined in a Hash
78
+ lookup.to_hash
79
+ ```
80
+
@@ -0,0 +1,22 @@
1
+ require 'locality/postnummerservice'
2
+
3
+ module Locality
4
+ # See https://sv.wikipedia.org/wiki/A-region
5
+ class Aregion
6
+
7
+ def initialize(raw_code)
8
+ @raw_code = raw_code
9
+ end
10
+
11
+ def zip_codes
12
+ @zip_codes ||= backend.aregions[1].map(&:zip_code)
13
+ end
14
+
15
+ private
16
+
17
+ def backend
18
+ Locality::Postnummerservice
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ require 'locality/configuration'
2
+
3
+ module Locality
4
+ module Configurable
5
+
6
+ # Public: Returns the the configuration instance.
7
+ #
8
+ def config
9
+ @config ||= Configuration.new
10
+ end
11
+
12
+ # Public: Yields the configuration instance.
13
+ #
14
+ def configure(&block)
15
+ yield config
16
+ end
17
+
18
+ # Public: Reset the configuration (useful for testing)
19
+ #
20
+ def reset!
21
+ @config = nil
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,68 @@
1
+ require 'pathname'
2
+
3
+ module Locality
4
+ class Configuration
5
+
6
+ # IP
7
+
8
+ attr_writer :maxmind_geoip2_path
9
+
10
+ def custom_ip_locations
11
+ @custom_ip_locations ||= {}
12
+ end
13
+
14
+ def add_custom_ip_location(ip, data)
15
+ custom_ip_locations[IPAddr.new(ip)] = data.to_hash
16
+ end
17
+
18
+ def maxmind_geoip2_path
19
+ maxmind_geoip2_paths.detect &:readable?
20
+ end
21
+
22
+ def maxmind_geoip2_paths
23
+ paths maxmind_geoip2_filename, custom_maxmind_geoip2_path
24
+ end
25
+
26
+ # Postnummerservice
27
+
28
+ attr_writer :postnummerfilen_path
29
+
30
+ def postnummerfilen_path
31
+ postnummerfilen_paths.detect &:readable?
32
+ end
33
+
34
+ def postnummerfilen_paths
35
+ paths postnummerfilen_filename, custom_postnummerfilen_path
36
+ end
37
+
38
+ private
39
+
40
+ def maxmind_geoip2_filename
41
+ 'GeoLite2-City.mmdb'
42
+ end
43
+
44
+ def postnummerfilen_filename
45
+ 'rec2LK.csv'
46
+ end
47
+
48
+ def custom_maxmind_geoip2_path
49
+ return unless @maxmind_geoip2_path
50
+ Pathname.new @maxmind_geoip2_path
51
+ end
52
+
53
+ def custom_postnummerfilen_path
54
+ return unless @postnummerfilen_path
55
+ Pathname.new @postnummerfilen_path
56
+ end
57
+
58
+ def paths(appendix = nil, additional = nil)
59
+ result = []
60
+ result << Rails.root.join('db', appendix) if defined?(Rails)
61
+ result << Pathname.new('/mnt').join('databases', appendix)
62
+ result << Pathname.new(Dir.pwd).join('db', appendix)
63
+ result << additional
64
+ result.compact
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,96 @@
1
+ require 'active_support/core_ext/object/blank'
2
+ require 'ipaddr'
3
+ require 'operation'
4
+ require 'trouble'
5
+ require 'geocoder'
6
+
7
+ require 'locality/configurable'
8
+
9
+ module Locality
10
+ class IP
11
+
12
+ def initialize(raw_ip)
13
+ @raw_ip = raw_ip
14
+ end
15
+
16
+ def to_hash
17
+ {
18
+ ip: ip.to_s,
19
+ city_name: city_name,
20
+ province_name: province_name,
21
+ state_name: state_name,
22
+ country_name: country_name,
23
+ human_readable_location: human_readable_location,
24
+ }
25
+ end
26
+
27
+ def ip
28
+ @ip ||= ::IPAddr.new raw_ip
29
+ rescue => exception
30
+ nil
31
+ end
32
+
33
+ def human_readable_location
34
+ city_name || province_name || state_name || country_name
35
+ end
36
+
37
+ def city_name
38
+ return unless lookup
39
+ lookup.city.presence
40
+ end
41
+
42
+ def province_name
43
+ return unless lookup
44
+ lookup.province.presence
45
+ end
46
+
47
+ def state_name
48
+ return unless lookup
49
+ lookup.state.presence
50
+ end
51
+
52
+ def country_name
53
+ return unless lookup
54
+ lookup.country.presence
55
+ end
56
+
57
+ private
58
+
59
+ attr_reader :raw_ip
60
+
61
+ def lookup
62
+ @lookup ||= custom_lookup! || lookup!
63
+ end
64
+
65
+ def lookup!
66
+ return unless ip.present?
67
+ ensure_upstream_configuration
68
+ Geocoder::Lookup.get(:geoip2).search(ip.to_s).first
69
+
70
+ rescue IOError => exception
71
+ Trouble.notify exception
72
+ configure_upstream! # Maybe the database file just moved somewhere else, repair by force-reconfiguring
73
+ nil
74
+ end
75
+
76
+ def custom_lookup!
77
+ ::Locality.config.custom_ip_locations.each do |key, value|
78
+ next unless key.include? ip
79
+ input = Hashie::Mash.new value
80
+ # Quacking like Geocoder::Result::GeoIP2
81
+ return Hashie::Mash.new(city: input.city_name, province: input.province_name, state: input.state_name, country: input.country_name)
82
+ end
83
+ nil
84
+ end
85
+
86
+ def ensure_upstream_configuration
87
+ return if Geocoder.config[:ip_lookup] == :geoip2
88
+ configure_upstream!
89
+ end
90
+
91
+ def configure_upstream!
92
+ Geocoder.configure ip_lookup: :geoip2, units: :km, geoip2: { cache: Hash.new, lib: 'hive_geoip2', file: ::Locality.config.maxmind_geoip2_path }
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,35 @@
1
+ module Locality
2
+ module Postnummerservice
3
+ class Entry < Array
4
+
5
+ def zip_code
6
+ self[0].to_i
7
+ end
8
+
9
+ def city_name
10
+ self[1]
11
+ end
12
+
13
+ def state_code
14
+ self[2]
15
+ end
16
+
17
+ def state_name
18
+ self[3]
19
+ end
20
+
21
+ def province_name
22
+ self[4]
23
+ end
24
+
25
+ def province_code
26
+ self[5]
27
+ end
28
+
29
+ def aregion
30
+ self[6].to_i
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,40 @@
1
+ require 'csv'
2
+ require 'locality/postnummerservice/entry'
3
+
4
+ module Locality
5
+ module Postnummerservice
6
+
7
+ def self.aregions
8
+ load
9
+ @aregions
10
+ end
11
+
12
+ private
13
+
14
+ def self.load
15
+ load! unless loaded?
16
+ end
17
+
18
+ def self.loaded?
19
+ !!@loaded
20
+ end
21
+
22
+ def self.load!
23
+ @aregions = {}
24
+
25
+ ::CSV.foreach(::Locality.config.postnummerfilen_path, encoding: encoding) do |row|
26
+ next if row.blank?
27
+ entry = Entry.new(row)
28
+ @aregions[entry.aregion] ||= []
29
+ @aregions[entry.aregion] << entry
30
+ end
31
+
32
+ @loaded = true
33
+ end
34
+
35
+ def self.encoding
36
+ 'ISO-8859-1:UTF-8' # from:to
37
+ end
38
+
39
+ end
40
+ end
data/lib/locality.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'locality/aregion'
2
+ require 'locality/configurable'
3
+ require 'locality/ip'
4
+ require 'locality/aregion'
5
+
6
+ module Locality
7
+ extend Configurable
8
+ end
metadata ADDED
@@ -0,0 +1,205 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: locality
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - bukowskis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: geocoder
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.6
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.2.6
41
+ - !ruby/object:Gem::Dependency
42
+ name: hashie
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: hive_geoip2
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.1.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: i18n
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: operation
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: trouble
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rb-fsevent
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: webmock
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: See https://github.com/bukowskis/locality
168
+ email:
169
+ executables: []
170
+ extensions: []
171
+ extra_rdoc_files: []
172
+ files:
173
+ - README.md
174
+ - lib/locality.rb
175
+ - lib/locality/aregion.rb
176
+ - lib/locality/configurable.rb
177
+ - lib/locality/configuration.rb
178
+ - lib/locality/ip.rb
179
+ - lib/locality/postnummerservice.rb
180
+ - lib/locality/postnummerservice/entry.rb
181
+ homepage: https://github.com/bukowskis/locality
182
+ licenses: []
183
+ metadata: {}
184
+ post_install_message:
185
+ rdoc_options: []
186
+ require_paths:
187
+ - lib
188
+ required_ruby_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ required_rubygems_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ requirements: []
199
+ rubyforge_project:
200
+ rubygems_version: 2.2.2
201
+ signing_key:
202
+ specification_version: 4
203
+ summary: Wrapping databases provided by maxmind.com and postnummerservice.se
204
+ test_files: []
205
+ has_rdoc: