ip2geo 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cdf86cb50c5d08c734ea15c78ec62d0f218dae67ccdb074b9b889fb0c77681f
4
- data.tar.gz: ed6420fd62687669cf430d6525b6415326a595cd60e4fae6a65ce0aae268e182
3
+ metadata.gz: 9ee64a44d70af371c8e118e89eeb1d6f975f289835c67dfc1695e7e750985df1
4
+ data.tar.gz: 16f87bf015c8f85a14b51e22b8e336838d9cb9f12ca3ea2b125dd19f7d368ceb
5
5
  SHA512:
6
- metadata.gz: 2a7f9f99b598e068ccff78fb2ba2199835a2db6ee086f7871228fcd8e785d321b72b7187bc195a77589acbb6a7f7f170e1d3410044355b913d9e41f2766ac0e0
7
- data.tar.gz: 190301f6be0572c93262611ec8cc2ee6f4ec631c9c810755777076daa379bc87ab22eaa5f543ef959584acd46c4ab54f3529d8c6218c1acb0c70917c55bc40c7
6
+ metadata.gz: bbcb5312ccb091395e24a694deb5c4eb1118c66caf00cbd3c993d47146e29529f41d886b5aff731208df87a0de5fc64ca5600cfe0e48feb6da9da6550b4a4c81
7
+ data.tar.gz: 10502431e5289199d0e4eadbd31fb41e46707534233dbe64574e6c56d6dcf14edc0d50a8461a57b3423e18d4388166eb46c3c5bc6dea73a6880359db3d9025ae
data/LICENSE CHANGED
@@ -3,4 +3,4 @@ Copyright (c) 2024 Ip2Geo. All rights reserved.
3
3
  This software is proprietary and confidential. Unauthorized copying, distribution,
4
4
  modification, or use of this software, via any medium, is strictly prohibited.
5
5
 
6
- No license, express or implied, is granted to any person or entity for any purpose.
6
+ No license, express or implied, is granted to any person or entity for any purpose.
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <div align='center'>
2
2
  <a href='https://axios-http.com'>
3
3
  <img
4
- src='https://cdn-prod.ip2geo.dev/assets/npm/generals/ip2geo.svg'
4
+ src='https://cdn-prod.ip2geo.dev/assets/ruby/generals/ip2geo.svg'
5
5
  alt='Ip2Geo Logo'
6
6
  />
7
7
  </a>
@@ -10,7 +10,7 @@
10
10
  </div>
11
11
 
12
12
  <p align='center'>
13
- Your go-to IP-to-Geo cloud service — fast, accurate, and built for developers. Start free with 2,000 monthly stored conversions.
13
+ Your go-to IP-to-Geo cloud service — fast, accurate, and built for developers. Start free with 1,000 monthly stored conversions.
14
14
  </p>
15
15
 
16
16
  <p align='center'>
data/ip2geo.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'ip2geo'
5
- spec.version = '0.0.1'
5
+ spec.version = '0.0.2'
6
6
  spec.authors = ['Ip2Geo']
7
7
  spec.email = ['support@ip2geo.dev']
8
8
 
@@ -44,75 +44,42 @@ module Ip2Geo
44
44
  }.freeze
45
45
 
46
46
  SELECT = {
47
- CONVERSION: {
48
- ID: 'id',
49
- UNIQUE_ID: 'uniqueId',
50
- DATA: 'data',
51
- STATUS: 'status',
52
- STARTED_AT: 'startedAt',
53
- COMPLETED_AT: 'completedAt',
54
- CREATED_AT: 'createdAt',
55
- CREDITED: 'credited',
56
- CONVERT_ONLY: 'convertOnly'
57
- }.freeze,
58
- DATA: {
59
- IP: 'data.ip',
60
- TYPE: 'data.type',
61
- IS_EU: 'data.is_eu',
62
- CONTINENT: {
63
- NAME: 'data.continent.name',
64
- CODE: 'data.continent.code',
65
- GEONAME_ID: 'data.continent.geoname_id',
66
- COUNTRY: {
67
- NAME: 'data.continent.country.name',
68
- CODE: 'data.continent.country.code',
69
- GEONAME_ID: 'data.continent.country.geoname_id',
70
- PHONE_CODE: 'data.continent.country.phone_code',
71
- CAPITAL: 'data.continent.country.capital',
72
- TLD: 'data.continent.country.tld',
73
- SUBDIVISION: {
74
- NAME: 'data.continent.country.subdivision.name',
75
- CODE: 'data.continent.country.subdivision.code'
76
- }.freeze,
77
- CITY: {
78
- NAME: 'data.continent.country.city.name',
79
- GEONAME_ID: 'data.continent.country.city.geoname_id',
80
- LATITUDE: 'data.continent.country.city.latitude',
81
- LONGITUDE: 'data.continent.country.city.longitude',
82
- ACCURACY_RADIUS: 'data.continent.country.city.accuracy_radius',
83
- METRO_CODE: 'data.continent.country.city.metro_code',
84
- POSTAL_CODE: 'data.continent.country.city.postal_code',
85
- TIMEZONE: {
86
- NAME: 'data.continent.country.city.timezone.name',
87
- TIME_NOW: 'data.continent.country.city.timezone.time_now'
88
- }.freeze
89
- }.freeze,
90
- FLAG: {
91
- IMG: 'data.continent.country.flag.img',
92
- EMOJI: 'data.continent.country.flag.emoji',
93
- EMOJI_UNICODE: 'data.continent.country.flag.emoji_unicode'
94
- }.freeze,
95
- CURRENCY: {
96
- NAME: 'data.continent.country.currency.name',
97
- CODE: 'data.continent.country.currency.code',
98
- SYMBOL: 'data.continent.country.currency.symbol'
99
- }.freeze
100
- }.freeze
101
- }.freeze,
102
- REGISTERED_COUNTRY: {
103
- NAME: 'data.registered_country.name',
104
- CODE: 'data.registered_country.code',
105
- GEONAME_ID: 'data.registered_country.geoname_id'
106
- }.freeze,
107
- ASN: {
108
- NUMBER: 'data.asn.number',
109
- NAME: 'data.asn.name'
110
- }.freeze,
111
- COMPLETION_TIME: {
112
- MILISECONDS: 'data.completion_time.miliseconds',
113
- SECONDS: 'data.completion_time.seconds'
114
- }.freeze
115
- }.freeze
47
+ IP: 'ip',
48
+ TYPE: 'type',
49
+ IS_EU: 'is_eu',
50
+ CONTINENT_NAME: 'continent.name',
51
+ CONTINENT_CODE: 'continent.code',
52
+ CONTINENT_GEONAME_ID: 'continent.geoname_id',
53
+ COUNTRY_NAME: 'continent.country.name',
54
+ COUNTRY_CODE: 'continent.country.code',
55
+ COUNTRY_GEONAME_ID: 'continent.country.geoname_id',
56
+ COUNTRY_PHONE_CODE: 'continent.country.phone_code',
57
+ COUNTRY_CAPITAL: 'continent.country.capital',
58
+ COUNTRY_TLD: 'continent.country.tld',
59
+ SUBDIVISION_NAME: 'continent.country.subdivision.name',
60
+ SUBDIVISION_CODE: 'continent.country.subdivision.code',
61
+ CITY_NAME: 'continent.country.city.name',
62
+ CITY_GEONAME_ID: 'continent.country.city.geoname_id',
63
+ CITY_LATITUDE: 'continent.country.city.latitude',
64
+ CITY_LONGITUDE: 'continent.country.city.longitude',
65
+ CITY_ACCURACY_RADIUS: 'continent.country.city.accuracy_radius',
66
+ CITY_METRO_CODE: 'continent.country.city.metro_code',
67
+ CITY_POSTAL_CODE: 'continent.country.city.postal_code',
68
+ TIMEZONE_NAME: 'continent.country.city.timezone.name',
69
+ TIMEZONE_TIME_NOW: 'continent.country.city.timezone.time_now',
70
+ FLAG_IMG: 'continent.country.flag.img',
71
+ FLAG_EMOJI: 'continent.country.flag.emoji',
72
+ FLAG_EMOJI_UNICODE: 'continent.country.flag.emoji_unicode',
73
+ CURRENCY_NAME: 'continent.country.currency.name',
74
+ CURRENCY_CODE: 'continent.country.currency.code',
75
+ CURRENCY_SYMBOL: 'continent.country.currency.symbol',
76
+ REGISTERED_COUNTRY_NAME: 'registered_country.name',
77
+ REGISTERED_COUNTRY_CODE: 'registered_country.code',
78
+ REGISTERED_COUNTRY_GEONAME_ID: 'registered_country.geoname_id',
79
+ ASN_NUMBER: 'asn.number',
80
+ ASN_NAME: 'asn.name',
81
+ COMPLETION_TIME_MILISECONDS: 'completion_time.miliseconds',
82
+ COMPLETION_TIME_SECONDS: 'completion_time.seconds'
116
83
  }.freeze
117
84
  end
118
85
  end
@@ -4,16 +4,20 @@ module Ip2Geo
4
4
  module Data
5
5
  class State
6
6
  class << self
7
- attr_accessor :auth_key, :version_update_message, :is_version_checked
7
+ attr_accessor :auth_key, :version_update_message, :is_version_checked,
8
+ :cache, :cache_max_size, :cache_ttl
8
9
 
9
10
  def reset!
10
11
  @auth_key = nil
11
12
  @version_update_message = true
12
13
  @is_version_checked = false
14
+ @cache = true
15
+ @cache_max_size = 1000
16
+ @cache_ttl = 300
13
17
  end
14
18
  end
15
19
 
16
20
  reset!
17
21
  end
18
22
  end
19
- end
23
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ip2Geo
4
+ module Helpers
5
+ class Cache
6
+ @mutex = Mutex.new
7
+
8
+ class << self
9
+ def get(key)
10
+ @mutex.synchronize do
11
+ entry = store[key]
12
+ return nil unless entry
13
+
14
+ if expired?(entry)
15
+ store.delete(key)
16
+ access_order.delete(key)
17
+ return nil
18
+ end
19
+
20
+ update_access_order(key)
21
+ entry[:data]
22
+ end
23
+ end
24
+
25
+ def set(key, data)
26
+ @mutex.synchronize do
27
+ store[key] = { data: data, timestamp: Time.now.to_f }
28
+ update_access_order(key)
29
+ evict_if_needed
30
+ end
31
+ end
32
+
33
+ def clear
34
+ @mutex.synchronize do
35
+ @store = {}
36
+ @access_order = []
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def store
43
+ @store ||= {}
44
+ end
45
+
46
+ def access_order
47
+ @access_order ||= []
48
+ end
49
+
50
+ def update_access_order(key)
51
+ access_order.delete(key)
52
+ access_order.push(key)
53
+ end
54
+
55
+ def evict_if_needed
56
+ while store.size > Data::State.cache_max_size && access_order.any?
57
+ oldest = access_order.shift
58
+ store.delete(oldest) if oldest
59
+ end
60
+ end
61
+
62
+ def expired?(entry)
63
+ (Time.now.to_f - entry[:timestamp]) > Data::State.cache_ttl
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -8,12 +8,9 @@ module Ip2Geo
8
8
  #
9
9
  # @param options [Hash] The options for the conversion
10
10
  # @option options [String] :ip The IP address to retrieve geo information for (required)
11
- # @option options [Boolean] :convert_only If true, stores minimal data and charges $0.001 per conversion
12
- # instead of $0.0005 (default: false)
13
11
  # @return [Hash, nil] The API response containing geo data, or nil if the request fails
14
12
  def call(options = {})
15
13
  ip = options[:ip]
16
- convert_only = options.fetch(:convert_only, false)
17
14
 
18
15
  unless ip
19
16
  return error_response(
@@ -29,7 +26,28 @@ module Ip2Geo
29
26
  )
30
27
  end
31
28
 
32
- url = "#{Data::API_ENDPOINT}#{Data::ENDPOINTS[:CONVERT]}?ip=#{ip}&convertOnly=#{convert_only}"
29
+ url = "#{Data::API_ENDPOINT}#{Data::ENDPOINTS[:CONVERT]}?ip=#{ip}"
30
+
31
+ if Data::State.cache
32
+ cache_key = "convert:#{ip}"
33
+ cached = Helpers::Cache.get(cache_key)
34
+
35
+ if cached
36
+ Thread.new do
37
+ fresh = Helpers::Http.request(url)
38
+ Helpers::Cache.set(cache_key, fresh) if fresh && fresh['success']
39
+ rescue StandardError
40
+ # silently ignore background refresh errors
41
+ end
42
+
43
+ return cached
44
+ end
45
+
46
+ response = Helpers::Http.request(url)
47
+ Helpers::Cache.set(cache_key, response) if response && response['success']
48
+ return response
49
+ end
50
+
33
51
  Helpers::Http.request(url)
34
52
  rescue StandardError => e
35
53
  warn "[Ip2Geo::ConvertIP] Error: #{e.message}"
@@ -53,4 +71,4 @@ module Ip2Geo
53
71
  end
54
72
  end
55
73
  end
56
- end
74
+ end
@@ -8,12 +8,9 @@ module Ip2Geo
8
8
  #
9
9
  # @param options [Hash] The options for the conversion
10
10
  # @option options [Array<String>] :ips An array of IP addresses to retrieve geo information for (required)
11
- # @option options [Boolean] :convert_only If true, stores minimal data and charges $0.001 per conversion
12
- # instead of $0.0005 (default: false)
13
11
  # @return [Hash, nil] The API response containing geo data for all IPs, or nil if the request fails
14
12
  def call(options = {})
15
13
  ips = options[:ips]
16
- convert_only = options.fetch(:convert_only, false)
17
14
 
18
15
  unless ips.is_a?(Array) && !ips.empty?
19
16
  return error_response(
@@ -45,7 +42,27 @@ module Ip2Geo
45
42
  end
46
43
 
47
44
  url = "#{Data::API_ENDPOINT}#{Data::ENDPOINTS[:CONVERT]}"
48
- body = { ips: ips, convertOnly: convert_only }
45
+ body = { ips: ips }
46
+
47
+ if Data::State.cache
48
+ cache_key = "convert-multi:#{ips.sort.join(',')}"
49
+ cached = Helpers::Cache.get(cache_key)
50
+
51
+ if cached
52
+ Thread.new do
53
+ fresh = Helpers::Http.request(url, body)
54
+ Helpers::Cache.set(cache_key, fresh) if fresh && fresh['success']
55
+ rescue StandardError
56
+ # silently ignore background refresh errors
57
+ end
58
+
59
+ return cached
60
+ end
61
+
62
+ response = Helpers::Http.request(url, body)
63
+ Helpers::Cache.set(cache_key, response) if response && response['success']
64
+ return response
65
+ end
49
66
 
50
67
  Helpers::Http.request(url, body)
51
68
  rescue StandardError => e
@@ -70,4 +87,4 @@ module Ip2Geo
70
87
  end
71
88
  end
72
89
  end
73
- end
90
+ end
@@ -21,7 +21,7 @@ module Ip2Geo
21
21
  end
22
22
 
23
23
  params = []
24
- params << "select=#{select.join(',')}" if select.is_a?(Array) && !select.empty?
24
+ params << "select=#{select.map { |f| "data.#{f}" }.join(',')}" if select.is_a?(Array) && !select.empty?
25
25
 
26
26
  query_string = params.empty? ? '' : "?#{params.join('&')}"
27
27
  url = "#{Data::API_ENDPOINT}#{Data::ENDPOINTS[:CONVERSIONS][:GET]}#{query_string}"
@@ -21,7 +21,7 @@ module Ip2Geo
21
21
  end
22
22
 
23
23
  params = []
24
- params << "select=#{select.join(',')}" if select.is_a?(Array) && !select.empty?
24
+ params << "select=#{select.map { |f| "data.#{f}" }.join(',')}" if select.is_a?(Array) && !select.empty?
25
25
 
26
26
  query_string = params.empty? ? '' : "?#{params.join('&')}"
27
27
  url = "#{Data::API_ENDPOINT}#{Data::ENDPOINTS[:CONVERSIONS][:GET]}#{query_string}"
@@ -9,11 +9,55 @@ module Ip2Geo
9
9
  # @param key [String] The API key used to authenticate with Ip2Geo
10
10
  # @param options [Hash] Optional configuration
11
11
  # @option options [Boolean] :version_update_message Whether to display version update messages (default: true)
12
+ # @option options [Boolean] :cache Whether to enable caching for successful conversions (default: true)
13
+ # @option options [Integer] :cache_max_size Maximum cached entries, min: 10, max: 50000 (default: 1000)
14
+ # @option options [Integer] :cache_ttl Cache TTL in seconds, min: 30, max: 86400 (default: 300)
12
15
  # @return [Boolean] Whether the initialization was successful
13
16
  def call(key, options = {})
14
17
  Data::State.auth_key = key
15
18
  Data::State.version_update_message = options.fetch(:version_update_message, true)
16
19
 
20
+ if options.key?(:cache)
21
+ unless options[:cache] == true || options[:cache] == false
22
+ raise ArgumentError, 'Init: "cache" must be a boolean.'
23
+ end
24
+
25
+ Data::State.cache = options[:cache]
26
+ end
27
+
28
+ if options.key?(:cache_max_size)
29
+ unless options[:cache_max_size].is_a?(Integer)
30
+ raise ArgumentError, 'Init: "cache_max_size" must be an integer.'
31
+ end
32
+
33
+ if options[:cache_max_size] < 10
34
+ raise ArgumentError, 'Init: "cache_max_size" must be at least 10.'
35
+ end
36
+
37
+ if options[:cache_max_size] > 50_000
38
+ raise ArgumentError, 'Init: "cache_max_size" must be at most 50000.'
39
+ end
40
+
41
+ Data::State.cache_max_size = options[:cache_max_size]
42
+ end
43
+
44
+ if options.key?(:cache_ttl)
45
+ unless options[:cache_ttl].is_a?(Integer)
46
+ raise ArgumentError, 'Init: "cache_ttl" must be an integer (seconds).'
47
+ end
48
+
49
+ if options[:cache_ttl] < 30
50
+ raise ArgumentError, 'Init: "cache_ttl" must be at least 30 (30 seconds).'
51
+ end
52
+
53
+ if options[:cache_ttl] > 86_400
54
+ raise ArgumentError, 'Init: "cache_ttl" must be at most 86400 (1 day).'
55
+ end
56
+
57
+ Data::State.cache_ttl = options[:cache_ttl]
58
+ end
59
+
60
+ Helpers::Cache.clear unless Data::State.cache
17
61
  Helpers::CheckVersion.call
18
62
 
19
63
  true
@@ -25,4 +69,4 @@ module Ip2Geo
25
69
  end
26
70
  end
27
71
  end
28
- end
72
+ end
@@ -21,7 +21,7 @@ module Ip2Geo
21
21
  params = []
22
22
  params << "offset=#{offset}" if offset.positive?
23
23
  params << "limit=#{limit}" if limit != 50
24
- params << "select=#{select.join(',')}" if select.is_a?(Array) && !select.empty?
24
+ params << "select=#{select.map { |f| "data.#{f}" }.join(',')}" if select.is_a?(Array) && !select.empty?
25
25
  params << "ipSearch=#{ip_search}" if ip_search
26
26
 
27
27
  query_string = params.empty? ? '' : "?#{params.join('&')}"
data/lib/ip2geo.rb CHANGED
@@ -21,6 +21,7 @@
21
21
  require_relative 'ip2geo/data/constants'
22
22
  require_relative 'ip2geo/data/states'
23
23
  require_relative 'ip2geo/data/messages'
24
+ require_relative 'ip2geo/helpers/cache'
24
25
  require_relative 'ip2geo/helpers/http'
25
26
  require_relative 'ip2geo/helpers/ip_validation'
26
27
  require_relative 'ip2geo/helpers/check_version'
@@ -40,11 +41,15 @@ module Ip2Geo
40
41
  # @param key [String] The API key used to authenticate with Ip2Geo
41
42
  # @param options [Hash] Optional configuration
42
43
  # @option options [Boolean] :version_update_message Whether to display version update messages (default: true)
44
+ # @option options [Boolean] :cache Whether to enable caching for successful conversions (default: true)
45
+ # @option options [Integer] :cache_max_size Maximum cached entries, min: 10, max: 50000 (default: 1000)
46
+ # @option options [Integer] :cache_ttl Cache TTL in seconds, min: 30, max: 86400 (default: 300)
43
47
  # @return [Boolean] Whether the initialization was successful
44
48
  #
45
49
  # @example
46
50
  # Ip2Geo.init('your-api-key')
47
51
  # Ip2Geo.init('your-api-key', version_update_message: false)
52
+ # Ip2Geo.init('your-api-key', cache_max_size: 500, cache_ttl: 60)
48
53
  def init(key, options = {})
49
54
  Methods::Init.call(key, options)
50
55
  end
@@ -53,12 +58,10 @@ module Ip2Geo
53
58
  #
54
59
  # @param options [Hash] The options for the conversion
55
60
  # @option options [String] :ip The IP address to retrieve geo information for (required)
56
- # @option options [Boolean] :convert_only If true, stores minimal data (default: false)
57
61
  # @return [Hash, nil] The API response containing geo data
58
62
  #
59
63
  # @example
60
64
  # result = Ip2Geo.convert_ip(ip: '8.8.8.8')
61
- # result = Ip2Geo.convert_ip(ip: '8.8.8.8', convert_only: true)
62
65
  def convert_ip(options = {})
63
66
  Methods::ConvertIP.call(options)
64
67
  end
@@ -67,7 +70,6 @@ module Ip2Geo
67
70
  #
68
71
  # @param options [Hash] The options for the conversion
69
72
  # @option options [Array<String>] :ips An array of IP addresses (required)
70
- # @option options [Boolean] :convert_only If true, stores minimal data (default: false)
71
73
  # @return [Hash, nil] The API response containing geo data for all IPs
72
74
  #
73
75
  # @example
@@ -85,7 +87,7 @@ module Ip2Geo
85
87
  #
86
88
  # @example
87
89
  # result = Ip2Geo.get_conversion(conversion_id: 'abc123')
88
- # result = Ip2Geo.get_conversion(conversion_id: 'abc123', select: ['id', 'data.ip'])
90
+ # result = Ip2Geo.get_conversion(conversion_id: 'abc123', select: ['ip', 'continent.country.name'])
89
91
  def get_conversion(options = {})
90
92
  Methods::GetConversion.call(options)
91
93
  end
@@ -137,10 +139,8 @@ module Ip2Geo
137
139
  # @return [Hash] The SELECT constants
138
140
  #
139
141
  # @example
140
- # Ip2Geo.select[:CONVERSION][:ID]
141
- # # => 'id'
142
- # Ip2Geo.select[:DATA][:CONTINENT][:COUNTRY][:NAME]
143
- # # => 'data.continent.country.name'
142
+ # Ip2Geo.select[:COUNTRY_NAME]
143
+ # # => 'continent.country.name'
144
144
  def select
145
145
  Data::SELECT
146
146
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ip2geo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ip2Geo
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 2026-01-30 00:00:00.000000000 Z
11
+ date: 2026-04-19 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: json
@@ -39,6 +40,7 @@ files:
39
40
  - lib/ip2geo/data/constants.rb
40
41
  - lib/ip2geo/data/messages.rb
41
42
  - lib/ip2geo/data/states.rb
43
+ - lib/ip2geo/helpers/cache.rb
42
44
  - lib/ip2geo/helpers/check_version.rb
43
45
  - lib/ip2geo/helpers/http.rb
44
46
  - lib/ip2geo/helpers/ip_validation.rb
@@ -55,6 +57,7 @@ metadata:
55
57
  homepage_uri: https://ip2geo.dev
56
58
  changelog_uri: https://docs.ip2geo.dev/changelog
57
59
  documentation_uri: https://docs.ip2geo.dev
60
+ post_install_message:
58
61
  rdoc_options: []
59
62
  require_paths:
60
63
  - lib
@@ -69,7 +72,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
72
  - !ruby/object:Gem::Version
70
73
  version: '0'
71
74
  requirements: []
72
- rubygems_version: 3.6.3
75
+ rubygems_version: 3.0.3.1
76
+ signing_key:
73
77
  specification_version: 4
74
78
  summary: Official Ruby SDK for Ip2Geo - IP to Geolocation API.
75
79
  test_files: []