verifip 0.1.4 → 0.2.0

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: 976d3bc6eb7004ffb3dcec07a331edfe33fc134799ddc67a863e5a56d1d7cd53
4
- data.tar.gz: cee1aef34074819ce6226be796ba1e24c34430b586921e7a94bc3da5cae85c03
3
+ metadata.gz: e99ded51e832b1176e27fad783ead281c84558bc6068281a3c3b0d592bba427a
4
+ data.tar.gz: 392d5354097484e8300e83aae37861a86a4569f5b629e5511b325591078c89fa
5
5
  SHA512:
6
- metadata.gz: f54e009ed0b87b3d2fb7c99f0da390dd85d9c14f653c55d160b236d7b428184b213eb90e906849e828abf1df45487a9f97f0a861e2f24cc9bc6939143e0da0cb
7
- data.tar.gz: fef5d94aec23f5a6f270670790cdf005e3782f39470cf4e2f86739be1ab93c10740b64ed48cbcf268195938c5d7ea5d4e561a6b9f0579046bd68b8d3c33191e3
6
+ metadata.gz: d028b0428cfb862608aeaa9ab614c2cb0b0f9f7b1ef65cfb0e0334656aeb619baf415a880750120c7c11e7b09519570c042b4bfd4863e0f664c661e2dcd83d18
7
+ data.tar.gz: 4403542ed7c9a49ec9d47ce17a847617e7ec95716a90c5fac13fb5a41adf9b1aff38235a5e59d33a3016012cdf7b36359dcd47dc0fda5ee871e432c5cf3a82a9
@@ -78,6 +78,89 @@ module VerifIP
78
78
  HealthResponse.from_hash(data)
79
79
  end
80
80
 
81
+ # Check an email address for fraud risk.
82
+ #
83
+ # @param email [String] email address to check
84
+ # @return [EmailResponse]
85
+ def check_email(email)
86
+ raise ArgumentError, "email is required" if email.nil? || email.empty?
87
+
88
+ data = request(:get, "/v1/email?email=#{URI.encode_uri_component(email)}", auth: true)
89
+ EmailResponse.from_hash(data)
90
+ end
91
+
92
+ # Check a phone number for fraud risk.
93
+ #
94
+ # @param phone [String] phone number to check
95
+ # @return [PhoneResponse]
96
+ def check_phone(phone)
97
+ raise ArgumentError, "phone is required" if phone.nil? || phone.empty?
98
+
99
+ data = request(:get, "/v1/phone?phone=#{URI.encode_uri_component(phone)}", auth: true)
100
+ PhoneResponse.from_hash(data)
101
+ end
102
+
103
+ # Check a URL for fraud risk.
104
+ #
105
+ # @param url [String] URL to check
106
+ # @return [URLResponse]
107
+ def check_url(url)
108
+ raise ArgumentError, "url is required" if url.nil? || url.empty?
109
+
110
+ data = request(:get, "/v1/url?url=#{URI.encode_uri_component(url)}", auth: true)
111
+ URLResponse.from_hash(data)
112
+ end
113
+
114
+ # Perform a WHOIS lookup for an IP address.
115
+ #
116
+ # @param ip [String] IPv4 or IPv6 address
117
+ # @return [WHOISResponse]
118
+ def check_whois(ip)
119
+ raise ArgumentError, "ip is required" if ip.nil? || ip.empty?
120
+
121
+ data = request(:get, "/v1/whois?ip=#{URI.encode_uri_component(ip)}", auth: true)
122
+ WHOISResponse.from_hash(data)
123
+ end
124
+
125
+ # Submit a fraud report for an IP address.
126
+ #
127
+ # @param ip [String] IPv4 or IPv6 address
128
+ # @param is_fraud [Boolean] whether the IP was used for fraud
129
+ # @param category [String] optional fraud category
130
+ # @param comment [String] optional comment
131
+ # @return [ReportResponse]
132
+ def report(ip, is_fraud, category: "", comment: "")
133
+ raise ArgumentError, "ip is required" if ip.nil? || ip.empty?
134
+
135
+ payload = { ip: ip, is_fraud: is_fraud }
136
+ payload[:category] = category unless category.empty?
137
+ payload[:comment] = comment unless comment.empty?
138
+
139
+ body = JSON.generate(payload)
140
+ data = request(:post, "/v1/report", body: body, auth: true)
141
+ ReportResponse.from_hash(data)
142
+ end
143
+
144
+ # Perform a multi-signal risk assessment.
145
+ #
146
+ # @param ip [String] optional IP address
147
+ # @param email [String] optional email address
148
+ # @param phone [String] optional phone number
149
+ # @param url [String] optional URL
150
+ # @return [AssessResponse]
151
+ def assess(ip: "", email: "", phone: "", url: "")
152
+ params = []
153
+ params << "ip=#{URI.encode_uri_component(ip)}" unless ip.empty?
154
+ params << "email=#{URI.encode_uri_component(email)}" unless email.empty?
155
+ params << "phone=#{URI.encode_uri_component(phone)}" unless phone.empty?
156
+ params << "url=#{URI.encode_uri_component(url)}" unless url.empty?
157
+
158
+ raise ArgumentError, "at least one parameter is required" if params.empty?
159
+
160
+ data = request(:get, "/v1/assess?#{params.join('&')}", auth: true)
161
+ AssessResponse.from_hash(data)
162
+ end
163
+
81
164
  def to_s = "VerifIP::Client(base_url=#{@base_url})"
82
165
  def inspect = to_s
83
166
 
@@ -115,6 +115,246 @@ module VerifIP
115
115
  def inspect = to_s
116
116
  end
117
117
 
118
+ # Response from an email risk check.
119
+ class EmailResponse
120
+ FIELDS = %i[
121
+ request_id email risk_score valid_syntax mx_found is_disposable
122
+ is_free_provider is_role_based domain_age_days domain
123
+ signal_breakdown error
124
+ ].freeze
125
+
126
+ attr_reader(*FIELDS)
127
+
128
+ def initialize(**kwargs)
129
+ @request_id = kwargs.fetch(:request_id, "")
130
+ @email = kwargs.fetch(:email, "")
131
+ @risk_score = kwargs.fetch(:risk_score, 0)
132
+ @valid_syntax = kwargs.fetch(:valid_syntax, false)
133
+ @mx_found = kwargs.fetch(:mx_found, false)
134
+ @is_disposable = kwargs.fetch(:is_disposable, false)
135
+ @is_free_provider = kwargs.fetch(:is_free_provider, false)
136
+ @is_role_based = kwargs.fetch(:is_role_based, false)
137
+ @domain_age_days = kwargs.fetch(:domain_age_days, 0)
138
+ @domain = kwargs.fetch(:domain, "")
139
+ @signal_breakdown = kwargs.fetch(:signal_breakdown, {})
140
+ @error = kwargs.fetch(:error, nil)
141
+ end
142
+
143
+ def self.from_hash(hash)
144
+ hash = _symbolize(hash)
145
+ new(**hash.slice(*FIELDS))
146
+ end
147
+
148
+ def to_h
149
+ FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
150
+ end
151
+
152
+ def to_s = "EmailResponse(email=#{@email}, risk_score=#{@risk_score})"
153
+ def inspect = to_s
154
+
155
+ def self._symbolize(hash)
156
+ hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
157
+ end
158
+ private_class_method :_symbolize
159
+ end
160
+
161
+ # Response from a phone number risk check.
162
+ class PhoneResponse
163
+ FIELDS = %i[
164
+ request_id phone risk_score valid country_code carrier
165
+ line_type is_voip signal_breakdown error
166
+ ].freeze
167
+
168
+ attr_reader(*FIELDS)
169
+
170
+ def initialize(**kwargs)
171
+ @request_id = kwargs.fetch(:request_id, "")
172
+ @phone = kwargs.fetch(:phone, "")
173
+ @risk_score = kwargs.fetch(:risk_score, 0)
174
+ @valid = kwargs.fetch(:valid, false)
175
+ @country_code = kwargs.fetch(:country_code, "")
176
+ @carrier = kwargs.fetch(:carrier, "")
177
+ @line_type = kwargs.fetch(:line_type, "")
178
+ @is_voip = kwargs.fetch(:is_voip, false)
179
+ @signal_breakdown = kwargs.fetch(:signal_breakdown, {})
180
+ @error = kwargs.fetch(:error, nil)
181
+ end
182
+
183
+ def self.from_hash(hash)
184
+ hash = _symbolize(hash)
185
+ new(**hash.slice(*FIELDS))
186
+ end
187
+
188
+ def voip? = @is_voip
189
+
190
+ def to_h
191
+ FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
192
+ end
193
+
194
+ def to_s = "PhoneResponse(phone=#{@phone}, risk_score=#{@risk_score})"
195
+ def inspect = to_s
196
+
197
+ def self._symbolize(hash)
198
+ hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
199
+ end
200
+ private_class_method :_symbolize
201
+ end
202
+
203
+ # Response from a URL risk check.
204
+ class URLResponse
205
+ FIELDS = %i[
206
+ request_id url risk_score is_phishing is_malware
207
+ safe_browsing_threat in_phishtank spamhaus_dbl domain_age_days
208
+ ssl_valid ssl_issuer signal_breakdown error
209
+ ].freeze
210
+
211
+ attr_reader(*FIELDS)
212
+
213
+ def initialize(**kwargs)
214
+ @request_id = kwargs.fetch(:request_id, "")
215
+ @url = kwargs.fetch(:url, "")
216
+ @risk_score = kwargs.fetch(:risk_score, 0)
217
+ @is_phishing = kwargs.fetch(:is_phishing, false)
218
+ @is_malware = kwargs.fetch(:is_malware, false)
219
+ @safe_browsing_threat = kwargs.fetch(:safe_browsing_threat, "")
220
+ @in_phishtank = kwargs.fetch(:in_phishtank, false)
221
+ @spamhaus_dbl = kwargs.fetch(:spamhaus_dbl, false)
222
+ @domain_age_days = kwargs.fetch(:domain_age_days, 0)
223
+ @ssl_valid = kwargs.fetch(:ssl_valid, false)
224
+ @ssl_issuer = kwargs.fetch(:ssl_issuer, "")
225
+ @signal_breakdown = kwargs.fetch(:signal_breakdown, {})
226
+ @error = kwargs.fetch(:error, nil)
227
+ end
228
+
229
+ def self.from_hash(hash)
230
+ hash = _symbolize(hash)
231
+ new(**hash.slice(*FIELDS))
232
+ end
233
+
234
+ def phishing? = @is_phishing
235
+ def malware? = @is_malware
236
+
237
+ def to_h
238
+ FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
239
+ end
240
+
241
+ def to_s = "URLResponse(url=#{@url}, risk_score=#{@risk_score})"
242
+ def inspect = to_s
243
+
244
+ def self._symbolize(hash)
245
+ hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
246
+ end
247
+ private_class_method :_symbolize
248
+ end
249
+
250
+ # Response from a WHOIS lookup.
251
+ class WHOISResponse
252
+ FIELDS = %i[
253
+ request_id ip network_cidr network_name org_name abuse_contact
254
+ rir allocation_date country_code asn asn_org
255
+ ].freeze
256
+
257
+ attr_reader(*FIELDS)
258
+
259
+ def initialize(**kwargs)
260
+ @request_id = kwargs.fetch(:request_id, "")
261
+ @ip = kwargs.fetch(:ip, "")
262
+ @network_cidr = kwargs.fetch(:network_cidr, "")
263
+ @network_name = kwargs.fetch(:network_name, "")
264
+ @org_name = kwargs.fetch(:org_name, "")
265
+ @abuse_contact = kwargs.fetch(:abuse_contact, "")
266
+ @rir = kwargs.fetch(:rir, "")
267
+ @allocation_date = kwargs.fetch(:allocation_date, "")
268
+ @country_code = kwargs.fetch(:country_code, "")
269
+ @asn = kwargs.fetch(:asn, 0)
270
+ @asn_org = kwargs.fetch(:asn_org, "")
271
+ end
272
+
273
+ def self.from_hash(hash)
274
+ hash = _symbolize(hash)
275
+ new(**hash.slice(*FIELDS))
276
+ end
277
+
278
+ def to_h
279
+ FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
280
+ end
281
+
282
+ def to_s = "WHOISResponse(ip=#{@ip}, network_cidr=#{@network_cidr})"
283
+ def inspect = to_s
284
+
285
+ def self._symbolize(hash)
286
+ hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
287
+ end
288
+ private_class_method :_symbolize
289
+ end
290
+
291
+ # Response from a fraud report submission.
292
+ class ReportResponse
293
+ FIELDS = %i[request_id status message].freeze
294
+
295
+ attr_reader(*FIELDS)
296
+
297
+ def initialize(**kwargs)
298
+ @request_id = kwargs.fetch(:request_id, "")
299
+ @status = kwargs.fetch(:status, "")
300
+ @message = kwargs.fetch(:message, "")
301
+ end
302
+
303
+ def self.from_hash(hash)
304
+ hash = _symbolize(hash)
305
+ new(**hash.slice(*FIELDS))
306
+ end
307
+
308
+ def to_h
309
+ FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
310
+ end
311
+
312
+ def to_s = "ReportResponse(status=#{@status}, message=#{@message})"
313
+ def inspect = to_s
314
+
315
+ def self._symbolize(hash)
316
+ hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
317
+ end
318
+ private_class_method :_symbolize
319
+ end
320
+
321
+ # Response from a multi-signal risk assessment.
322
+ class AssessResponse
323
+ FIELDS = %i[request_id overall_risk ip email phone url].freeze
324
+
325
+ attr_reader(*FIELDS)
326
+
327
+ def initialize(**kwargs)
328
+ @request_id = kwargs.fetch(:request_id, "")
329
+ @overall_risk = kwargs.fetch(:overall_risk, 0)
330
+ @ip = kwargs.fetch(:ip, nil)
331
+ @email = kwargs.fetch(:email, nil)
332
+ @phone = kwargs.fetch(:phone, nil)
333
+ @url = kwargs.fetch(:url, nil)
334
+ end
335
+
336
+ def self.from_hash(hash)
337
+ hash = _symbolize(hash)
338
+ hash[:ip] = CheckResponse.from_hash(hash[:ip]) if hash[:ip].is_a?(Hash)
339
+ hash[:email] = EmailResponse.from_hash(hash[:email]) if hash[:email].is_a?(Hash)
340
+ hash[:phone] = PhoneResponse.from_hash(hash[:phone]) if hash[:phone].is_a?(Hash)
341
+ hash[:url] = URLResponse.from_hash(hash[:url]) if hash[:url].is_a?(Hash)
342
+ new(**hash.slice(*FIELDS))
343
+ end
344
+
345
+ def to_h
346
+ FIELDS.each_with_object({}) { |f, h| h[f] = send(f) }
347
+ end
348
+
349
+ def to_s = "AssessResponse(overall_risk=#{@overall_risk})"
350
+ def inspect = to_s
351
+
352
+ def self._symbolize(hash)
353
+ hash.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
354
+ end
355
+ private_class_method :_symbolize
356
+ end
357
+
118
358
  # Rate limit information parsed from response headers.
119
359
  class RateLimitInfo
120
360
  # @return [Integer] maximum requests in the current window
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module VerifIP
4
- VERSION = "0.1.4"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verifip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - VerifIP
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-22 00:00:00.000000000 Z
11
+ date: 2026-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec