whoisxmlapi 0.2.6 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 453ac4268c148b920859e950c1d32a21d7980a3b1800871121e1e45e43f82279
4
- data.tar.gz: af4d3856d0df53f393c15fa9f78797a5a29806d216e6581aeda0edf6d491ea40
3
+ metadata.gz: fe3b9a00715ebd01c80e1378d9f64c57051f4af98848fe8fba3b548dac9716c4
4
+ data.tar.gz: 4cbb2e345411dd433820b4ec4c465635e4cbb6c13ac4ae687175ada3d776c64d
5
5
  SHA512:
6
- metadata.gz: 674d3238730704987c9b848bc93fe2ff6817ebb24ad60a88f0aad4a99a4940c2b89681c8f55e0fac6de6629435120b8a89d362e73fff84661599603a20f1b158
7
- data.tar.gz: a8ac668ed1e44e9bf6762e1e21dbf0393d46dfd8299add120cd1496b194d6c7d75e61e2cc9ed39c077b688ed251b3c650f5efd1d3c8cc92a80e38c96a540d8ff
6
+ metadata.gz: c6be612f3c774ad9d4a0511c49bc3a78cf53b3cc592fcd47c02a7c94423be084d3ce54728f5b96b9a568194c76a4ed6d912a6ab101b9576cdef937cc45c73f22
7
+ data.tar.gz: ebe16297aa08021577cecca96c15be662cb0da4995940ccf9bcb7041ca2047854d720281434bdfd88b0c02af496e61c22ff7527d891419d02b6ea333e20c1d92
@@ -7,74 +7,126 @@ module WhoisXMLAPI
7
7
 
8
8
  class Client
9
9
 
10
+ ####################################################################################################
11
+ # Whois
12
+ ####################################################################################################
13
+
10
14
  # https://whoisapi.whoisxmlapi.com/docs
11
15
  # GET https://www.whoisxmlapi.com/whoisserver/WhoisService?apiKey=YOUR_API_KEY&domainName=google.com
12
- def whois(domain)
16
+ def whois_cacheless(domain, owner=nil)
13
17
  unless PublicSuffix.valid?(domain)
14
- res = WhoisXMLAPI::BadDomain.new
18
+ res = WhoisXMLAPI::BadDomain.new(:whoisable => owner)
15
19
  res.parse(domain)
16
20
  return res
17
21
  end
18
22
 
19
- query = WhoisXMLAPI::Result.where(:domain => domain)
20
- query = query.where(:created_at.gte => (Time.now - WhoisXMLAPI.cache_length)) if WhoisXMLAPI.cache
21
- res = query.first
22
-
23
- if res.nil? || res._type == "WhoisXMLAPI::Unavailable"
24
- params = {
25
- :apiKey => WhoisXMLAPI.api_key,
26
- :domainName => domain,
27
- :outputFormat => 'JSON'
28
- }
29
-
30
- begin
31
- r = HTTParty.get(WhoisXMLAPI.whois_path, :query => params, :timeout => 120)
32
- rescue StandardError => e
33
- WhoisXMLAPI.logger.info "WhoisXMLAPI#whois - Error getting Whois info for #{domain}: #{e}"
34
- res = WhoisXMLAPI::Unavailable.new
35
- res.parse(domain)
36
- return res
37
- end
23
+ params = {
24
+ :apiKey => WhoisXMLAPI.api_key,
25
+ :domainName => domain,
26
+ :outputFormat => 'JSON'
27
+ }
38
28
 
29
+ begin
30
+ r = HTTParty.get(WhoisXMLAPI.whois_path, :query => params, :timeout => 120)
31
+ rescue StandardError => e
32
+ WhoisXMLAPI.logger.info "WhoisXMLAPI#whois - Error getting Whois info for \'#{domain}\': #{e}"
33
+ res = WhoisXMLAPI::Unavailable.new(:whoisable => owner)
34
+ res.parse(domain) # parse will save document for Unavailable
35
+ else
39
36
  if WhoisXMLAPI.callbacks[:whois]
40
- WhoisXMLAPI.callbacks[:whois].each do |cb|
41
- cb.call
42
- end
37
+ WhoisXMLAPI.callbacks[:whois].each{ |cb| cb.call }
43
38
  end
44
-
45
39
  # WhoisXML and HTTParty are sometimes returning a Hash and not a JSON string as requested,
46
40
  # which is causing an error of "no implicit conversion of Hash into String" when we call JSON.parse.
47
41
  # Logger message is to monitor whether WhoisXML and/or HTTParty will still return a string on occasion.
48
42
  if r
49
43
  if r.parsed_response.is_a?(String)
50
- WhoisXMLAPI.logger.debug "WhoisXMLAPI#whois - WARNING: passed back parsed_response as a String instead of a Hash for #{domain}."
44
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#whois - WARNING: passed back parsed_response as a String instead of a Hash for \'#{domain}\'."
51
45
  presponse = JSON.parse(r.parsed_response)
52
46
  else
53
47
  presponse = r.parsed_response
54
48
  end
55
49
  if presponse.key? 'ErrorMessage'
56
50
  WhoisXMLAPI.logger.info "WhoisXMLAPI#whois - Error getting Whois info: #{presponse['ErrorMessage']['msg']}"
57
- res = WhoisXMLAPI::Unavailable.new
58
- res.parse(domain)
51
+ res = WhoisXMLAPI::Unavailable.new(:whoisable => owner)
52
+ res.parse(domain) # parse will save document for Unavailable
59
53
  elsif (200..299).include? r.code.to_i
60
- res = WhoisXMLAPI::Good.new
61
- res.parse(presponse['WhoisRecord'])
54
+ res = WhoisXMLAPI::Good.new(:whoisable => owner)
55
+ res.parse(presponse['WhoisRecord']) # parse will NOT save document for Good or UnParsable
62
56
  res.save
63
57
  end
64
58
  end
59
+ end
65
60
 
66
- unless res
67
- WhoisXMLAPI.logger.info "WhoisXMLAPI#whois - Unable to get Whois info for : #{domain}"
68
- res = WhoisXMLAPI::Unavailable.new
69
- res.parse(domain)
70
- end
71
-
61
+ unless res
62
+ WhoisXMLAPI.logger.info "WhoisXMLAPI#whois - Unable to get Whois info for domain: \'#{domain}\'"
63
+ res = WhoisXMLAPI::Unavailable.new(:whoisable => owner)
64
+ res.parse(domain) # parse will save document for Unavailable
72
65
  end
66
+
73
67
  return res
74
68
  end
75
69
 
76
70
 
77
- def self.send_rwhois_request(entity_name)
71
+ # https://whoisapi.whoisxmlapi.com/docs
72
+ # GET https://www.whoisxmlapi.com/whoisserver/WhoisService?apiKey=YOUR_API_KEY&domainName=google.com
73
+ def whois(domain, owner=nil)
74
+ unless PublicSuffix.valid?(domain)
75
+ res = WhoisXMLAPI::BadDomain.new
76
+ res.parse(domain)
77
+ return res
78
+ end
79
+
80
+ query = WhoisXMLAPI::Result.where(:domain => domain)
81
+ query = query.where(:created_at.gte => (Time.now - WhoisXMLAPI.cache_length)) if WhoisXMLAPI.cache
82
+ res = query.first
83
+
84
+ if res.nil? || res._type == "WhoisXMLAPI::Unavailable"
85
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#whois - no cached Whois data for \'#{domain}\': initiating API access."
86
+ res = whois_cacheless(domain, owner)
87
+ else
88
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#whois - using cached Whois data for \'#{domain}\'"
89
+ end
90
+ res
91
+ end
92
+
93
+
94
+ def exists?(domain)
95
+ params = {
96
+ :cmd => 'GET_DN_AVAILABILITY',
97
+ :domainName => domain,
98
+ :outputFormat => 'JSON',
99
+ :apiKey => WhoisXMLAPI.api_key
100
+ }
101
+ begin
102
+ r = HTTParty.get(WhoisXMLAPI.whois_path, :query => params, :timeout => 120)
103
+ rescue StandardError => e
104
+ WhoisXMLAPI.logger.info "WhoisXMLAPI#whois - Error getting Whois info for \'#{domain}\': #{e}"
105
+ res = WhoisXMLAPI::Unavailable.new
106
+ res.parse(domain)
107
+ return res
108
+ end
109
+
110
+ # WhoisXML and HTTParty are sometimes returning a Hash and not a JSON string as requested,
111
+ # which is causing an error of "no implicit conversion of Hash into String" when we call JSON.parse.
112
+ # Logger message is to monitor whether WhoisXML and/or HTTParty will still return a string on occasion.
113
+ if r.parsed_response.is_a?(String)
114
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#exists? - passed back parsed_response as a String instead of a Hash for \'#{domain}\'."
115
+ resp = JSON.parse(r.parsed_response)
116
+ else
117
+ resp = r.parsed_response
118
+ end
119
+
120
+ resp["DomainInfo"]["domainAvailability"] == "UNAVAILABLE"
121
+ end
122
+
123
+
124
+ ####################################################################################################
125
+ # Reverse Whois
126
+ ####################################################################################################
127
+
128
+
129
+ def self.send_rwhois_request(entity_name, since_dt=nil)
78
130
  params = {
79
131
  :apiKey => WhoisXMLAPI.api_key,
80
132
  :searchType => "current",
@@ -82,13 +134,15 @@ module WhoisXMLAPI
82
134
  :responseFormat => 'json',
83
135
  :basicSearchTerms => {
84
136
  :include => [entity_name] # must be an array of strings!
85
- },
137
+ }
86
138
  }
139
+ params[:createdDateFrom] = since_dt.strftime("%F") if since_dt
140
+
87
141
  begin
88
142
  # To DEBUG add ":debug_output => $stdout"
89
143
  r = HTTParty.post(WhoisXMLAPI.rwhois_path, :body => params.to_json, :timeout => 120, :headers => {'Content-Type' => 'application/json'})
90
144
  rescue StandardError => e
91
- WhoisXMLAPI.logger.info "WhoisXMLAPI#rwhois - Error getting RWhois info for #{entity_name}: #{e}"
145
+ WhoisXMLAPI.logger.info "WhoisXMLAPI#rwhois - Error getting RWhois info for \'#{entity_name}\': #{e}"
92
146
  r = nil
93
147
  end
94
148
 
@@ -104,81 +158,76 @@ module WhoisXMLAPI
104
158
 
105
159
  # https://reverse-whois-api.whoisxmlapi.com/docs
106
160
  # POST https://reverse-whois-api.whoisxmlapi.com/api/v2
107
- def rwhois(entity_name)
161
+ def rwhois_cacheless(entity_name, since_dt=nil, owner=nil)
108
162
  # entity_name is really the domain being passed in for Rwhois not the actual entity name
109
- return nil if entity_name.nil?
110
- query = WhoisXMLAPI::RWhoisResult.where(:entity_name => entity_name)
111
- query = query.where(:created_at.gte => (Time.now - WhoisXMLAPI.cache_length)) if WhoisXMLAPI.cache
112
- res = query.first
113
-
114
- if res
115
- WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois - using cached rwhois data for #{entity_name}"
116
- else
117
- WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois - no cached rwhois data for #{entity_name}"
118
- res = WhoisXMLAPI::RWhoisResult.new(:entity_name => entity_name)
119
-
120
- r = WhoisXMLAPI::Client.send_rwhois_request(entity_name)
163
+ return nil unless entity_name.present?
164
+ res = WhoisXMLAPI::RWhoisResult.new(:entity_name => entity_name, :rwhoisable => owner, :domains => [])
165
+ r = WhoisXMLAPI::Client.send_rwhois_request(entity_name, since_dt)
166
+ if r && r.parsed_response && r.parsed_response['domainsList']
167
+ res.domains = r.parsed_response['domainsList']
168
+ elsif PublicSuffix.valid?(entity_name)
169
+ # if no luck with what was passed in and we have a valid domain with TLD, try just the second-level domain.
170
+ domain_sld = PublicSuffix.parse(entity_name).sld
171
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois_cacheless - no domains found for domain \'#{entity_name}\', trying #{domain_sld}"
172
+ res.entity_name = domain_sld
173
+ r = WhoisXMLAPI::Client.send_rwhois_request(domain_sld)
121
174
  if r && r.parsed_response && r.parsed_response['domainsList']
122
175
  res.domains = r.parsed_response['domainsList']
123
- elsif PublicSuffix.valid?(entity_name)
124
- # if no luck with what was passed in and we have a valid domain with TLD, try just the second-level domain.
125
- domain = PublicSuffix.parse(entity_name)
126
- domain_sld = domain.sld
127
- WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois - no domains found for domain #{entity_name}, trying #{domain_sld}"
128
- res = WhoisXMLAPI::RWhoisResult.new(:entity_name => domain_sld)
129
-
130
- r = WhoisXMLAPI::Client.send_rwhois_request(domain_sld)
131
- if r && r.parsed_response && r.parsed_response['domainsList']
132
- res.domains = r.parsed_response['domainsList']
133
- else
134
- res.domains = []
135
- end
136
- else
137
- WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois - no domains found for #{entity_name}!"
138
- res.domains = []
139
- end
140
- res.save
141
- if res.errors.any?
142
- WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois - ERROR saving RWhoisResult: #{res.errors.full_messages.join('; ')} - #{res}!"
143
176
  end
177
+ else
178
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois_cacheless - no domains found for \'#{entity_name}\'!"
179
+ end
180
+ unless res.save
181
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois_cacheless - ERROR saving RWhoisResult: #{res.errors.full_messages.join('; ')} - #{res}!"
144
182
  end
145
183
  res
146
184
  end
147
185
 
148
186
 
149
- def exists?(domain)
150
- params = {
151
- :cmd => 'GET_DN_AVAILABILITY',
152
- :domainName => domain,
153
- :outputFormat => 'JSON',
154
- :apiKey => WhoisXMLAPI.api_key
155
- }
156
- begin
157
- r = HTTParty.get(WhoisXMLAPI.whois_path, :query => params, :timeout => 120)
158
- rescue StandardError => e
159
- WhoisXMLAPI.logger.info "WhoisXMLAPI#whois - Error getting Whois info for #{domain}: #{e}"
160
- res = WhoisXMLAPI::Unavailable.new
161
- res.parse(domain)
162
- return res
163
- end
187
+ # https://reverse-whois-api.whoisxmlapi.com/docs
188
+ # POST https://reverse-whois-api.whoisxmlapi.com/api/v2
189
+ def rwhois(entity_name, since_dt=nil, owner=nil)
190
+ # entity_name is really the domain being passed in for Rwhois not the actual entity name
191
+ return nil if entity_name.nil?
192
+ query = WhoisXMLAPI::RWhoisResult.where(:entity_name => entity_name, :rwhoisable => owner)
193
+ query = query.where(:created_at.gte => (Time.now - WhoisXMLAPI.cache_length)) if WhoisXMLAPI.cache
194
+ res = query.first
164
195
 
165
- # WhoisXML and HTTParty are sometimes returning a Hash and not a JSON string as requested,
166
- # which is causing an error of "no implicit conversion of Hash into String" when we call JSON.parse.
167
- # Logger message is to monitor whether WhoisXML and/or HTTParty will still return a string on occasion.
168
- if r.parsed_response.is_a?(String)
169
- WhoisXMLAPI.logger.debug "WhoisXMLAPI#exists? - passed back parsed_response as a String instead of a Hash for #{domain}."
170
- resp = JSON.parse(r.parsed_response)
196
+ if res.nil?
197
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois - no cached RWhois data for \'#{entity_name}\': initiating API access."
198
+ res = rwhois_cacheless(entity_name, since_dt, owner)
171
199
  else
172
- resp = r.parsed_response
200
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#rwhois - using cached RWhois data for \'#{entity_name}\'"
173
201
  end
174
-
175
- resp["DomainInfo"]["domainAvailability"] == "UNAVAILABLE"
202
+ res
176
203
  end
177
204
 
178
205
 
206
+ ####################################################################################################
207
+ # Account Balance
208
+ ####################################################################################################
209
+
210
+
179
211
  #
180
212
  # GET https://user.whoisxmlapi.com/service/account-balance?apiKey=YOUR_API_KEY
213
+ # wc.account_balance
214
+ # =>
215
+ # {
216
+ # "Email Verification API" => {:product_id => 7, :credits => 1000},
217
+ # "IP Geolocation API" => {:product_id => 8, :credits => 1000},
218
+ # "Domain Research Suite" => {:product_id => 14, :credits => 100},
219
+ # "WHOIS API" => {:product_id => 1, :credits => 1000},
220
+ # "Domain Reputation API" => {:product_id => 20, :credits => 100},
221
+ # "IP Netblocks API" => {:product_id => 23, :credits => 1000},
222
+ # "Domain Availability API" => {:product_id => 25, :credits => 100},
223
+ # "Screenshot API" => {:product_id => 27, :credits => 500},
224
+ # "Website Categorization API" => {:product_id => 21, :credits => 100},
225
+ # "Website Contacts API" => {:product_id => 29, :credits => 100},
226
+ # "DNS Lookup API" => {:product_id => 26, :credits => 500}
227
+ # }
228
+
181
229
  def account_balance
230
+ result = nil
182
231
  params = {
183
232
  :apiKey => WhoisXMLAPI.api_key
184
233
  }
@@ -190,15 +239,30 @@ module WhoisXMLAPI
190
239
  r = nil
191
240
  end
192
241
 
193
- # WhoisXML and HTTParty are sometimes returning a Hash and not a JSON string as requested,
194
- # which is causing an error of "no implicit conversion of Hash into String" when we call JSON.parse.
195
- # Logger message is to monitor whether WhoisXML and/or HTTParty will still return a string on occasion.
196
- if r.parsed_response.is_a?(String)
197
- WhoisXMLAPI.logger.debug "WhoisXMLAPI#account_balance - passed back parsed_response as a String instead of a Hash."
198
- JSON.parse(r.parsed_response)
199
- end
242
+ if r.response.is_a? Net::HTTPOK
243
+ if r && r.parsed_response
244
+ # WhoisXML and HTTParty are sometimes returning a Hash and not a JSON string as requested,
245
+ # which is causing an error of "no implicit conversion of Hash into String" when we call JSON.parse.
246
+ # Logger message is to monitor whether WhoisXML and/or HTTParty will still return a string on occasion.
247
+ if r.parsed_response.is_a?(String)
248
+ WhoisXMLAPI.logger.debug "WhoisXMLAPI#account_balance - passed back parsed_response as a String instead of a Hash."
249
+ JSON.parse(r.parsed_response)
250
+ end
200
251
 
201
- r ? r.parsed_response : nil
252
+ if r.parsed_response["error"]
253
+ result = {:error => {message: r.parsed_response["error"]}}
254
+ elsif r.parsed_response["data"]
255
+ result = {}
256
+ r.parsed_response["data"].each do |datum|
257
+ key = datum["product"]["name"]
258
+ result[key] = {product_id: datum["product_id"], credits: datum["credits"]}
259
+ end
260
+ end
261
+ end
262
+ else
263
+ result = {:error =>{code: r.response.code, message: r.response.message}}
264
+ end
265
+ result
202
266
  end
203
267
 
204
268
 
@@ -5,6 +5,9 @@ module WhoisXMLAPI
5
5
  include Mongoid::Document
6
6
  include Mongoid::Timestamps
7
7
 
8
+ # https://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html
9
+ belongs_to :whoisable, :polymorphic => true, optional: true
10
+
8
11
  field :domain
9
12
  field :record_created
10
13
  field :record_updated
@@ -15,12 +18,10 @@ module WhoisXMLAPI
15
18
  field :status
16
19
 
17
20
  has_one :registrant, :as => :contactable, :class_name => "WhoisXMLAPI::Contact", :autosave => true
18
- has_one :admin, :as => :contactable, :class_name => "WhoisXMLAPI::Contact", :autosave => true
19
- has_one :tech, :as => :contactable, :class_name => "WhoisXMLAPI::Contact", :autosave => true
20
- has_one :billing, :as => :contactable, :class_name => "WhoisXMLAPI::Contact", :autosave => true
21
+ has_one :admin, :as => :contactable, :class_name => "WhoisXMLAPI::Contact", :autosave => true
22
+ has_one :tech, :as => :contactable, :class_name => "WhoisXMLAPI::Contact", :autosave => true
23
+ has_one :billing, :as => :contactable, :class_name => "WhoisXMLAPI::Contact", :autosave => true
21
24
 
22
- # https://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html
23
- belongs_to :whoisable, :polymorphic => true, optional: true
24
25
  # Actual indexing is performed in db_mongoid_extend.rake
25
26
  # index([
26
27
  # [ :whoisable_id, Mongo::ASCENDING ],
@@ -28,6 +29,7 @@ module WhoisXMLAPI
28
29
  # ])
29
30
  index({whoisable_id: 1, whoisable_type: 1})
30
31
 
32
+
31
33
  def parse(record)
32
34
  self.domain = record['domainName']
33
35
  self.data_error = record['dataError'] ? record['dataError'] : nil
@@ -64,15 +66,41 @@ module WhoisXMLAPI
64
66
  self.billing = WhoisXMLAPI::Contact.selectively_create_from_hash(billing_data) if billing_data
65
67
  end
66
68
 
69
+
67
70
  def complete?
68
71
  ( self.domain and self.registrar and ( self.registrant or self.admin or self.tech) )
69
72
  end
70
73
 
74
+
71
75
  def private?
72
76
  %w/networksolutionsprivateregistration.com domainprivacygroup.com/.each do |priv|
73
77
  return true if self.registrant.email =~ /#{priv}/
74
78
  end
75
79
  false
76
80
  end
81
+
82
+
83
+ def contact_email(contact)
84
+ case contact
85
+ when :registrant
86
+ registrant ? registrant.email : nil
87
+ when :admin
88
+ admin ? admin.email : nil
89
+ when :tech
90
+ tech ? tech.email : nil
91
+ when :billing
92
+ billing ? billing.email : nil
93
+ else
94
+ nil
95
+ end
96
+ end
97
+
98
+
99
+ def contact_email_host(contact)
100
+ email = contact_email(contact)
101
+ host = email.squish.split("@").last.downcase if email.present? && email.include?("@")
102
+ PublicSuffix.valid?(host) ? host : nil
103
+ end
104
+
77
105
  end
78
106
  end
@@ -5,9 +5,10 @@ module WhoisXMLAPI
5
5
 
6
6
  # https://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html
7
7
  belongs_to :rwhoisable, :polymorphic => true, optional: true
8
+
8
9
  # Actual indexing is performed in db_mongoid_extend.rake
9
- field :entity_name, :type => String # , index: true
10
- field :domains, :type => Array
11
10
 
11
+ field :entity_name, :type => String # , index: true
12
+ field :domains, :type => Array
12
13
  end
13
14
  end
@@ -1,3 +1,3 @@
1
1
  module WhoisXMLAPI
2
- VERSION = "0.2.6"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whoisxmlapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Hillard
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2019-11-19 00:00:00.000000000 Z
14
+ date: 2020-08-19 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activesupport