virustotal_api 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +26 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +12 -5
  5. data/CHANGELOG.md +7 -2
  6. data/README.md +48 -56
  7. data/lib/virustotal_api.rb +5 -7
  8. data/lib/virustotal_api/analysis.rb +24 -0
  9. data/lib/virustotal_api/base.rb +35 -10
  10. data/lib/virustotal_api/domain.rb +24 -0
  11. data/lib/virustotal_api/exceptions.rb +3 -0
  12. data/lib/virustotal_api/file.rb +56 -0
  13. data/lib/virustotal_api/ip.rb +24 -0
  14. data/lib/virustotal_api/uri.rb +2 -1
  15. data/lib/virustotal_api/url.rb +46 -0
  16. data/lib/virustotal_api/version.rb +2 -1
  17. data/test/analysis_test.rb +23 -0
  18. data/test/base_test.rb +8 -28
  19. data/test/domain_test.rb +32 -0
  20. data/test/exceptions_test.rb +14 -0
  21. data/test/file_test.rb +68 -0
  22. data/test/fixtures/analysis.yml +544 -0
  23. data/test/fixtures/domain.yml +830 -0
  24. data/test/fixtures/file_analyse.yml +52 -0
  25. data/test/fixtures/file_find.yml +1236 -0
  26. data/test/fixtures/file_unauthorized.yml +51 -0
  27. data/test/fixtures/file_upload.yml +54 -0
  28. data/test/fixtures/ip.yml +716 -0
  29. data/test/fixtures/unscanned_url_find.yml +44 -0
  30. data/test/fixtures/url_analyse.yml +52 -0
  31. data/test/fixtures/url_find.yml +599 -0
  32. data/test/{ip_report_test.rb → ip_test.rb} +4 -4
  33. data/test/uri_test.rb +1 -1
  34. data/test/url_test.rb +65 -0
  35. data/test/version_test.rb +1 -1
  36. data/virustotal_api.gemspec +10 -8
  37. metadata +86 -70
  38. data/.github/workflows/gem_publish.yml +0 -38
  39. data/lib/virustotal_api/domain_report.rb +0 -36
  40. data/lib/virustotal_api/file_report.rb +0 -37
  41. data/lib/virustotal_api/file_rescan.rb +0 -36
  42. data/lib/virustotal_api/file_scan.rb +0 -38
  43. data/lib/virustotal_api/ip_report.rb +0 -36
  44. data/lib/virustotal_api/url_report.rb +0 -41
  45. data/lib/virustotal_api/url_scan.rb +0 -36
  46. data/test/domain_report_test.rb +0 -32
  47. data/test/file_report_test.rb +0 -36
  48. data/test/file_rescan_test.rb +0 -32
  49. data/test/file_scan_test.rb +0 -30
  50. data/test/fixtures/domain_report.yml +0 -311
  51. data/test/fixtures/ip_report.yml +0 -1323
  52. data/test/fixtures/queue_unscanned_url_report.yml +0 -46
  53. data/test/fixtures/report.yml +0 -110
  54. data/test/fixtures/report_not_found.yml +0 -42
  55. data/test/fixtures/request_forbidden.yml +0 -38
  56. data/test/fixtures/rescan.yml +0 -47
  57. data/test/fixtures/scan.yml +0 -49
  58. data/test/fixtures/unscanned_url_report.yml +0 -43
  59. data/test/fixtures/url_report.yml +0 -95
  60. data/test/fixtures/url_scan.yml +0 -48
  61. data/test/url_report_test.rb +0 -57
  62. data/test/url_scan_test.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59f51d8dce27daace930afc9786485d497e79b3ba9afc6b82bffbb1ac1c98b36
4
- data.tar.gz: 1fe1adf06f5135342dd48cade1d28c78a97530885e51e6d0993d0a971e31cec4
3
+ metadata.gz: 68e1f3494830e62ef04f24a74431a540d3dd6943ee329b772b8a3629798f0856
4
+ data.tar.gz: 58e0b36a8a6745b2db5957ab4b48da429f9ec154b1116d0110933cbc54d9f456
5
5
  SHA512:
6
- metadata.gz: 30985ac7e3aec76bf9fd6ab41f9b1b1ec46edb96ba5e3ab12e9d1c993aeff665cc41fb5644db97afb26d41605208f4b0a116856fed5cfe22872571da429e3882
7
- data.tar.gz: ea9be7f207a5805fecc1e1e321c07ade17cafc1eb0b1c85416117985f54837b6951c6285562f0ffffac32933fd9ff0bd66e1561f0d15ccb6555f0998d6d8a0de
6
+ metadata.gz: 03cf94231610ed5e8002c60dde3cc6d3b3d4ab52682be470023911559c0df6f2cf9230532fe3f002bd2587268405b086742e73a9edba86a4de49eaca37ab1b6b
7
+ data.tar.gz: a831140e24d0302e971a33f3b44d7c9760aa271b27d4036bf310ada72f09aa9cd11d1c685793d2a78a0ac6814725de873f8ea6419e92461febef84bb909f2065
@@ -0,0 +1,26 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ Test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Set up Ruby
16
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
17
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
18
+ uses: ruby/setup-ruby@v1.46.0
19
+ with:
20
+ ruby-version: 2.6
21
+ - name: Install dependencies
22
+ run: bundle install
23
+ - name: Lint
24
+ run: bundle exec rake rubocop
25
+ - name: Run tests
26
+ run: bundle exec rake
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ .rake_tasks~
@@ -1,13 +1,14 @@
1
1
  # This is the configuration used to check the rubocop source code.
2
2
 
3
3
  AllCops:
4
+ NewCops: enable
4
5
  Exclude:
5
6
  - 'test/fixtures/*'
6
7
 
7
8
  Style/StringLiterals:
8
9
  Enabled: true
9
10
 
10
- Style/UnneededPercentQ:
11
+ Style/RedundantPercentQ:
11
12
  Enabled: true
12
13
 
13
14
  # Disabled Checks
@@ -20,13 +21,19 @@ Style/PercentLiteralDelimiters:
20
21
  Style/RegexpLiteral:
21
22
  Enabled: false
22
23
 
23
- Style/BracesAroundHashParameters:
24
- Enabled: false
25
-
26
24
  Lint/MissingCopEnableDirective:
27
25
  Exclude:
28
26
  - 'test/base_test.rb'
29
27
 
30
- Naming/UncommunicativeMethodParamName:
28
+ Naming/MethodParameterName:
31
29
  Exclude:
32
30
  - 'lib/virustotal_api/ip_report.rb'
31
+
32
+ Layout/LineLength:
33
+ Enabled: false
34
+
35
+ Metrics/MethodLength:
36
+ Enabled: false
37
+
38
+ Gemspec/RequiredRubyVersion:
39
+ Enabled: false
@@ -1,10 +1,15 @@
1
1
  # VirusTotal API Changelog
2
2
 
3
+ ## [0.5.0] - 2020-09-02
4
+
5
+ * Full rework to support API V3.
6
+ * [@crondaemon](https://github.com/crondaemon) & [@jonnynux](https://github.com/jonnynux)
7
+ * Move to Ruby 2.6 for minimum Ruby version
8
+
3
9
  ## [0.4.1] - 2019-09-04
4
10
 
5
11
  * Fixed Reponse Parsing
6
- * [@jonnynux](https://github.com/jonnynux)
7
-
12
+ * [@jonnynux](https://github.com/jonnynux)
8
13
 
9
14
  ## [0.4.0] - 2019-07-23
10
15
 
data/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # VirustotalAPI
2
2
 
3
- Ruby Gem for [VirusTotal](https://www.virustotal.com) [V2 API](https://www.virustotal.com/en/documentation/public-api/)
3
+ Ruby Gem for [VirusTotal](https://www.virustotal.com) [V3 API](https://developers.virustotal.com/v3.0/reference).
4
+ If you want the version 2, check out the gem versions up to [0.4.0](https://github.com/crondaemon/virustotal_api/tree/v0.4.0).
5
+
6
+ ![Ruby](https://github.com/pwelch/virustotal_api/workflows/Ruby/badge.svg)
4
7
 
5
8
  [![Gem Version](https://badge.fury.io/rb/virustotal_api.svg)](http://badge.fury.io/rb/virustotal_api)
6
- [![CircleCI](https://circleci.com/gh/pwelch/virustotal_api.svg?style=svg)](https://circleci.com/gh/pwelch/virustotal_api)
7
9
 
8
10
  ## Installation
9
11
 
@@ -27,7 +29,7 @@ VirusTotal only allows 4 queries per minute for their Public API. https://www.vi
27
29
 
28
30
  You will need a Private API Key if you require more queries per minute.
29
31
 
30
- ### File Report
32
+ ### File Find
31
33
 
32
34
  ```ruby
33
35
  require 'virustotal_api'
@@ -35,7 +37,7 @@ require 'virustotal_api'
35
37
  sha256 = '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
36
38
  api_key = 'MY_API_KEY'
37
39
 
38
- vtreport = VirustotalAPI::FileReport.find(sha256, api_key)
40
+ vtreport = VirustotalAPI::File.find(sha256, api_key)
39
41
 
40
42
  # Does the resource have any results?
41
43
  vtreport.exists?
@@ -43,14 +45,19 @@ vtreport.exists?
43
45
 
44
46
  # URL for File Report (if it exists)
45
47
  vtreport.report_url
46
- # => "https://www.virustotal.com/file/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b/analysis/1418032127/"
48
+ # => "https://www.virustotal.com/api/v3/files/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"
47
49
 
48
50
  # Report results (if they exist) are available via #report
49
- vtreport.report["scans"]["ClamAV"]
50
- # => {"detected"=>false, "version"=>"0.98.5.0", "result"=>nil, "update"=>"20141208"}
51
+ vtreport.report['data']['attributes']['last_analysis_results']['ClamAV']
52
+ # => {"category"=>"undetected", "engine_name"=>"ClamAV", "engine_update"=>"20200826",
53
+ # "engine_version"=>"0.102.4.0", "method"=>"blacklist", "result"=>nil}
54
+
55
+ # Check whether an Antivirus detected this sample or not
56
+ vtreport.detected_by('ClamAV')
57
+ # => false
51
58
  ```
52
59
 
53
- ### File Scan
60
+ ### File Upload
54
61
 
55
62
  ```ruby
56
63
  require 'virustotal_api'
@@ -58,28 +65,21 @@ require 'virustotal_api'
58
65
  file = '/path/to/file'
59
66
  api_key = 'MY_API_KEY'
60
67
 
61
- vtscan = VirustotalAPI::FileScan.scan(file, api_key)
68
+ vtscan = VirustotalAPI::File.upload(file, api_key)
62
69
 
63
- # Scan ID of file
64
- vtscan.scan_id
70
+ # Virustotal ID of file
71
+ vtscan.id
65
72
  # => "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b-1419454668"
66
73
 
67
74
  # Response results are available via #response
68
75
  vtscan.report
69
76
  # =>
70
- {
71
- "scan_id"=>"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b-1419454668",
72
- "sha1"=>"adc83b19e793491b1c6ea0fd8b46cd9f32e592fc",
73
- "resource"=>"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
74
- "response_code"=>1,
75
- "sha256"=>"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
76
- "permalink"=>"https://www.virustotal.com/file/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b/analysis/1419454668/",
77
- "md5"=>"68b329da9893e34099c7d8ad5cb9c940",
78
- "verbose_msg"=>"Scan request successfully queued, come back later for the report"
79
- }
77
+ {"data"=>
78
+ {"id"=>"MTkxNDBmMjU4ZGY1OGZiYzZjNmU2ODcyMWNhYjhkZTM6MTU5ODUzMTE5OQ==",
79
+ "type"=>"analysis"}}
80
80
  ```
81
81
 
82
- ### File Rescan
82
+ ### File Analyse
83
83
 
84
84
  ```ruby
85
85
  require 'virustotal_api'
@@ -87,25 +87,21 @@ require 'virustotal_api'
87
87
  sha256 = '01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b'
88
88
  api_key = 'MY_API_KEY'
89
89
 
90
- vtrescan = VirustotalAPI::FileRescan.rescan(sha256, api_key)
90
+ vtrescan = VirustotalAPI::File.analyse(sha256, api_key)
91
91
 
92
- # Rescan ID of file
93
- vtrescan.rescan_id
94
- # => "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b-1562684247"
92
+ # Virustotal ID of file
93
+ vtrescan.id
94
+ # => "MTkxNDBmMjU4ZGY1OGZiYzZjNmU2ODcyMWNhYjhkZTM6MTU5ODUzMTE5OQ=="
95
95
 
96
96
  # Response results are available via #response
97
97
  vtrescan.report
98
98
  # =>
99
- {
100
- "permalink": "https://www.virustotal.com/file/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b/analysis/1562684247/",
101
- "response_code": 1,
102
- "sha256": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
103
- "resource": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
104
- "scan_id": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b-1562684247"
105
- }
99
+ {"data"=>
100
+ {"id"=>"MTkxNDBmMjU4ZGY1OGZiYzZjNmU2ODcyMWNhYjhkZTM6MTU5ODUzMTE5OQ==",
101
+ "type"=>"analysis"}}
106
102
  ```
107
103
 
108
- ### URL Report
104
+ ### URL find
109
105
 
110
106
  ```ruby
111
107
  require 'virustotal_api'
@@ -113,7 +109,7 @@ require 'virustotal_api'
113
109
  url = 'http://www.google.com'
114
110
  api_key = 'MY_API_KEY'
115
111
 
116
- vturl_report = VirustotalAPI::URLReport.find(url, api_key)
112
+ vturl_report = VirustotalAPI::URL.find(url, api_key)
117
113
 
118
114
  # Does the resource have any results?
119
115
  vturl_report.exists?
@@ -121,14 +117,14 @@ vturl_report.exists?
121
117
 
122
118
  # URL for Report (if it exists)
123
119
  vturl_report.report_url
124
- # => "https://www.virustotal.com/url/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf/analysis/1419457210/"
120
+ # => "https://www.virustotal.com/api/v3/urls/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf/"
125
121
 
126
122
  # Report results (if they exist) are available via #report
127
- vturl_report.report["scans"]["Opera"]
128
- # => {"detected"=>false, "result"=>"clean site"}
123
+ vturl_report.report['data']['attributes']['last_analysis_results']['Avira']
124
+ # => {"category"=>"harmless", "engine_name"=>"Avira", "method"=>"blacklist", "result"=>"clean"}
129
125
  ```
130
126
 
131
- ### URL Scan
127
+ ### URL Upload
132
128
 
133
129
  ```ruby
134
130
  require 'virustotal_api'
@@ -136,27 +132,22 @@ require 'virustotal_api'
136
132
  url = 'http://www.google.com'
137
133
  api_key = 'MY_API_KEY'
138
134
 
139
- vturl_scan = VirustotalAPI::URLScan.scan(url, api_key)
135
+ vturl_scan = VirustotalAPI::URL.upload(url, api_key)
140
136
 
141
- # Scan ID of file
142
- vturl_scan.scan_id
143
- # => "dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1562751553"
137
+ # Virustotal ID of file
138
+ vturl_scan.id
139
+ # => "u-dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1598531929"
144
140
 
145
141
  # Response results are available via #response
146
142
  vturl_scan.report
147
143
  # =>
148
- {
149
- "permalink": "https://www.virustotal.com/url/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf/analysis/1562751553/",
150
- "resource": "http://www.google.com/",
151
- "url": "http://www.google.com/",
152
- "response_code": 1,
153
- "scan_date": "2019-07-10 09:39:13",
154
- "scan_id": "dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1562751553",
155
- "verbose_msg": "Scan request successfully queued, come back later for the report"
156
- }
144
+ {"data"=>
145
+ {"id"=>
146
+ "u-dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1598531929",
147
+ "type"=>"analysis"}}
157
148
  ```
158
149
 
159
- ### IP Report
150
+ ### IP Find
160
151
 
161
152
  ```ruby
162
153
  require 'virustotal_api'
@@ -164,7 +155,7 @@ require 'virustotal_api'
164
155
  ip = '8.8.8.8'
165
156
  api_key = 'MY_API_KEY'
166
157
 
167
- vtip_report = VirustotalAPI::IPReport.find(ip, api_key)
158
+ vtip_report = VirustotalAPI::IP.find(ip, api_key)
168
159
 
169
160
  # Does the resource have any results?
170
161
  vtip_report.exists?
@@ -175,7 +166,7 @@ vtip_report.report
175
166
  # => Hash of report results
176
167
  ```
177
168
 
178
- ### Domain Report
169
+ ### Domain Find
179
170
 
180
171
  ```ruby
181
172
  require 'virustotal_api'
@@ -183,7 +174,7 @@ require 'virustotal_api'
183
174
  domain = 'virustotal.com'
184
175
  api_key = 'MY_API_KEY'
185
176
 
186
- vtdomain_report = VirustotalAPI::DomainReport.find(domain, api_key)
177
+ vtdomain_report = VirustotalAPI::Domain.find(domain, api_key)
187
178
 
188
179
  # Does the resource have any results?
189
180
  vtdomain_report.exists?
@@ -199,6 +190,7 @@ vtdomain_report.report
199
190
  - [@postmodern](https://github.com/postmodern)
200
191
  - [@mkunkel](https://github.com/mkunkel)
201
192
  - [@jonnynux](https://github.com/jonnynux)
193
+ - [@crondaemon](https://github.com/crondaemon/)
202
194
 
203
195
  ## Contributing
204
196
 
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'virustotal_api/domain_report'
4
- require 'virustotal_api/file_report'
5
- require 'virustotal_api/file_rescan'
6
- require 'virustotal_api/file_scan'
7
- require 'virustotal_api/ip_report'
8
- require 'virustotal_api/url_report'
9
- require 'virustotal_api/url_scan'
3
+ require 'virustotal_api/analysis'
4
+ require 'virustotal_api/domain'
5
+ require 'virustotal_api/file'
6
+ require 'virustotal_api/ip'
7
+ require 'virustotal_api/url'
10
8
  require 'virustotal_api/uri'
11
9
  require 'virustotal_api/version'
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module VirustotalAPI
6
+ # A class for '/analyses' API
7
+ class Analysis < Base
8
+ attr_reader :report
9
+
10
+ # rubocop:disable Lint/MissingSuper
11
+ def initialize(report)
12
+ @report = report
13
+ end
14
+
15
+ # @param [String] id The Virustotal ID to get the report for.
16
+ # @param [String] api_key The key for virustotal
17
+ # @return [VirustotalAPI::IP] Report
18
+ def self.find(id, api_key)
19
+ report = perform("/analyses/#{id}", api_key)
20
+ new(report)
21
+ end
22
+ end
23
+ end
24
+ # rubocop:enable Lint/MissingSuper
@@ -3,22 +3,44 @@
3
3
  require 'virustotal_api/exceptions'
4
4
  require 'rest-client'
5
5
  require 'json'
6
+ require 'base64'
6
7
 
8
+ # The base VirustotalAPI module.
7
9
  module VirustotalAPI
10
+ # The base class implementing the raw calls to Virustotal API V3.
8
11
  class Base
12
+ attr_reader :report
13
+
14
+ def initialize(report)
15
+ @report = report
16
+ end
17
+
9
18
  # @return [String] string of API URI class method
10
19
  def self.api_uri
11
20
  VirustotalAPI::URI
12
21
  end
13
22
 
14
- # @param [RestClient::Response] response
15
- # @return [Hash] the parsed JSON.
16
- def self.parse(response)
17
- if response.code == 204
18
- raise(RateLimitError, 'maximum number of 4 requests per minute reached')
19
- end
20
-
23
+ # The actual method performing a call to Virustotal
24
+ #
25
+ # @param [String] url The url of the API
26
+ # @param [String] api_key The key for virustotal
27
+ # @param [String] method The HTTP method to use
28
+ # @param [Hash] options Options to pass as payload
29
+ # @return [VirustotalAPI::Domain] Report Search Result
30
+ def self.perform(url, api_key, method = :get, options = {})
31
+ response = RestClient::Request.execute(
32
+ method: method,
33
+ url: api_uri + url,
34
+ headers: { 'x-apikey': api_key },
35
+ payload: options
36
+ )
21
37
  JSON.parse(response.body)
38
+ rescue RestClient::NotFound
39
+ nil
40
+ rescue RestClient::Unauthorized
41
+ # Raise a custom exception not to expose the underlying
42
+ # HTTP client.
43
+ raise VirustotalAPI::Unauthorized
22
44
  end
23
45
 
24
46
  # @return [String] string of API URI instance method
@@ -27,11 +49,14 @@ module VirustotalAPI
27
49
  end
28
50
 
29
51
  # @return [Boolean] if report for resource exists
30
- # 0 => not_present, 1 => exists, -1 => invalid_ip_address
31
52
  def exists?
32
- response_code = report.fetch('response_code') { nil }
53
+ !report.empty?
54
+ end
33
55
 
34
- response_code == 1
56
+ # Generate a URL identifier.
57
+ # @see https://developers.virustotal.com/v3.0/reference#url
58
+ def self.url_identifier(url)
59
+ Base64.encode64(url).strip.gsub('=', '')
35
60
  end
36
61
  end
37
62
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module VirustotalAPI
6
+ # A class for '/domains' API
7
+ class Domain < Base
8
+ # rubocop:disable Lint/UselessMethodDefinition
9
+ def initialize(report)
10
+ super(report)
11
+ end
12
+
13
+ # Find a domain.
14
+ #
15
+ # @param [String] domain The domain to search
16
+ # @param [String] api_key for virustotal
17
+ # @return [VirustotalAPI::Domain] Report Search Result
18
+ def self.find(domain, api_key)
19
+ report = perform("/domains/#{domain}", api_key)
20
+ new(report)
21
+ end
22
+ end
23
+ end
24
+ # rubocop:enable Lint/UselessMethodDefinition