virustotal_api 0.4.1 → 0.5.4

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.
Files changed (72) 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 +27 -2
  6. data/README.md +94 -56
  7. data/lib/virustotal_api.rb +7 -7
  8. data/lib/virustotal_api/analysis.rb +16 -0
  9. data/lib/virustotal_api/base.rb +41 -10
  10. data/lib/virustotal_api/domain.rb +18 -0
  11. data/lib/virustotal_api/exceptions.rb +3 -0
  12. data/lib/virustotal_api/file.rb +48 -0
  13. data/lib/virustotal_api/group.rb +18 -0
  14. data/lib/virustotal_api/ip.rb +18 -0
  15. data/lib/virustotal_api/uri.rb +2 -1
  16. data/lib/virustotal_api/url.rb +38 -0
  17. data/lib/virustotal_api/user.rb +18 -0
  18. data/lib/virustotal_api/version.rb +2 -1
  19. data/test/analysis_test.rb +26 -0
  20. data/test/base_test.rb +18 -23
  21. data/test/domain_test.rb +27 -0
  22. data/test/exceptions_test.rb +22 -0
  23. data/test/file_test.rb +63 -0
  24. data/test/fixtures/analysis.yml +544 -0
  25. data/test/fixtures/domain.yml +830 -0
  26. data/test/fixtures/domain_bad_request.yml +52 -0
  27. data/test/fixtures/file_analyse.yml +52 -0
  28. data/test/fixtures/file_find.yml +853 -0
  29. data/test/fixtures/file_not_found.yml +52 -0
  30. data/test/fixtures/file_rate_limit.yml +52 -0
  31. data/test/fixtures/file_unauthorized.yml +51 -0
  32. data/test/fixtures/file_upload.yml +54 -0
  33. data/test/fixtures/group_find.yml +216 -0
  34. data/test/fixtures/ip.yml +716 -0
  35. data/test/fixtures/unscanned_url_find.yml +44 -0
  36. data/test/fixtures/url_analyse.yml +52 -0
  37. data/test/fixtures/url_find.yml +599 -0
  38. data/test/fixtures/user_find.yml +213 -0
  39. data/test/group_test.rb +27 -0
  40. data/test/{ip_report_test.rb → ip_test.rb} +6 -4
  41. data/test/uri_test.rb +1 -1
  42. data/test/url_test.rb +47 -0
  43. data/test/user_test.rb +26 -0
  44. data/test/version_test.rb +1 -1
  45. data/virustotal_api.gemspec +10 -8
  46. metadata +102 -71
  47. data/.circleci/config.yml +0 -23
  48. data/.github/workflows/gem_publish.yml +0 -38
  49. data/lib/virustotal_api/domain_report.rb +0 -36
  50. data/lib/virustotal_api/file_report.rb +0 -37
  51. data/lib/virustotal_api/file_rescan.rb +0 -36
  52. data/lib/virustotal_api/file_scan.rb +0 -38
  53. data/lib/virustotal_api/ip_report.rb +0 -36
  54. data/lib/virustotal_api/url_report.rb +0 -41
  55. data/lib/virustotal_api/url_scan.rb +0 -36
  56. data/test/domain_report_test.rb +0 -32
  57. data/test/file_report_test.rb +0 -36
  58. data/test/file_rescan_test.rb +0 -32
  59. data/test/file_scan_test.rb +0 -30
  60. data/test/fixtures/domain_report.yml +0 -311
  61. data/test/fixtures/ip_report.yml +0 -1323
  62. data/test/fixtures/queue_unscanned_url_report.yml +0 -46
  63. data/test/fixtures/report.yml +0 -110
  64. data/test/fixtures/report_not_found.yml +0 -42
  65. data/test/fixtures/request_forbidden.yml +0 -38
  66. data/test/fixtures/rescan.yml +0 -47
  67. data/test/fixtures/scan.yml +0 -49
  68. data/test/fixtures/unscanned_url_report.yml +0 -43
  69. data/test/fixtures/url_report.yml +0 -95
  70. data/test/fixtures/url_scan.yml +0 -48
  71. data/test/url_report_test.rb +0 -57
  72. 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: 8bf33b0c496e55c74969e71e323aa64c664a4e7090db4f849601829143ee976a
4
+ data.tar.gz: 13eed4b64f8923c637e2155c3ece40f9bf55378c3f3a4cc7a321e29f58d8a357
5
5
  SHA512:
6
- metadata.gz: 30985ac7e3aec76bf9fd6ab41f9b1b1ec46edb96ba5e3ab12e9d1c993aeff665cc41fb5644db97afb26d41605208f4b0a116856fed5cfe22872571da429e3882
7
- data.tar.gz: ea9be7f207a5805fecc1e1e321c07ade17cafc1eb0b1c85416117985f54837b6951c6285562f0ffffac32933fd9ff0bd66e1561f0d15ccb6555f0998d6d8a0de
6
+ metadata.gz: 168c48232321aecaa6ad6bf5d34d07eb417cbf82f4bcd9a69ed678bb1c28c23a0121a859151662d0e810ea1ca4d8cda2dc50a771d98eaf85f5c98f424b9c4458
7
+ data.tar.gz: '021498bfce536a34eadc04c7b12766ff605b1f3ae61163be4c88e72aba5e05f2ce4be692aaa601420bdc480327d81e6e5496fd4c293c60f6fdb11f9537d68363'
@@ -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
19
+ with:
20
+ ruby-version: 2.5
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,35 @@
1
1
  # VirusTotal API Changelog
2
2
 
3
+ ## [0.5.4] - 2020-12-10
4
+ * Manage bad requests like not found
5
+ * Use strict base64 encoding
6
+ * [@crondaemon](https://github.com/crondaemon)
7
+
8
+ ## [0.5.3] = 2020-10-12
9
+
10
+ ## [0.5.2] - 2020-10-06
11
+
12
+ * Fix Fix exists? check
13
+ * Fix detected_by for File
14
+ * Fix RateLimitError
15
+ * Added User and Group API
16
+ * [@jonnynux](https://github.com/jonnynux)
17
+
18
+ ## [0.5.1] - 2020-10-06
19
+
20
+ * Downgrade ruby requirement to 2.5.
21
+ * [@crondaemon](https://github.com/crondaemon)
22
+
23
+ ## [0.5.0] - 2020-09-02
24
+
25
+ * Full rework to support API V3 [#30](https://github.com/pwelch/virustotal_api/pull/30)
26
+ * [@crondaemon](https://github.com/crondaemon) & [@jonnynux](https://github.com/jonnynux)
27
+ * Move to Ruby 2.6 for minimum Ruby version
28
+
3
29
  ## [0.4.1] - 2019-09-04
4
30
 
5
31
  * Fixed Reponse Parsing
6
- * [@jonnynux](https://github.com/jonnynux)
7
-
32
+ * [@jonnynux](https://github.com/jonnynux)
8
33
 
9
34
  ## [0.4.0] - 2019-07-23
10
35
 
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,18 +155,22 @@ 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?
171
162
  # => true
172
163
 
164
+ # URL for Report (if it exists)
165
+ vtip_report.report_url
166
+ # => "https://www.virustotal.com/api/v3/ip_addresses/8.8.8.8"
167
+
173
168
  # Report results (if they exist) are available via #report
174
169
  vtip_report.report
175
170
  # => Hash of report results
176
171
  ```
177
172
 
178
- ### Domain Report
173
+ ### Domain Find
179
174
 
180
175
  ```ruby
181
176
  require 'virustotal_api'
@@ -183,22 +178,65 @@ require 'virustotal_api'
183
178
  domain = 'virustotal.com'
184
179
  api_key = 'MY_API_KEY'
185
180
 
186
- vtdomain_report = VirustotalAPI::DomainReport.find(domain, api_key)
181
+ vtdomain_report = VirustotalAPI::Domain.find(domain, api_key)
187
182
 
188
183
  # Does the resource have any results?
189
184
  vtdomain_report.exists?
190
185
  # => true
191
186
 
187
+ # URL for Report (if it exists)
188
+ vtdomain_report.report_url
189
+ # => "https://www.virustotal.com/api/v3/domains/virustotal.com"
190
+
192
191
  # Report results (if they exist) are available via #report
193
192
  vtdomain_report.report
194
193
  # => Hash of report results
195
194
  ```
196
195
 
196
+ ### User Find
197
+
198
+ ```ruby
199
+ require 'virustotal_api'
200
+
201
+ user_key = 'user_key' # user_id or api_key
202
+ api_key = 'MY_API_KEY'
203
+
204
+ vtuser_report = VirustotalAPI::User.find(user_key, api_key)
205
+
206
+ # Does the resource have any results?
207
+ vtuser_report.exists?
208
+ # => true
209
+
210
+ # Report results (if they exist) are available via #report
211
+ vtuser_report.report
212
+ # => Hash of report results
213
+ ```
214
+
215
+ ### Group Find
216
+
217
+ ```ruby
218
+ require 'virustotal_api'
219
+
220
+ group_id = 'GROUP_id'
221
+ api_key = 'MY_API_KEY'
222
+
223
+ vtgroup_report = VirustotalAPI::Group.find(group_id, api_key)
224
+
225
+ # Does the resource have any results?
226
+ vtgroup_report.exists?
227
+ # => true
228
+
229
+ # Report results (if they exist) are available via #report
230
+ vtgroup_report.report
231
+ # => Hash of report results
232
+ ```
233
+
197
234
  ## Contributors
198
235
 
199
236
  - [@postmodern](https://github.com/postmodern)
200
237
  - [@mkunkel](https://github.com/mkunkel)
201
238
  - [@jonnynux](https://github.com/jonnynux)
239
+ - [@crondaemon](https://github.com/crondaemon/)
202
240
 
203
241
  ## Contributing
204
242
 
@@ -1,11 +1,11 @@
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/group'
7
+ require 'virustotal_api/ip'
8
+ require 'virustotal_api/url'
10
9
  require 'virustotal_api/uri'
10
+ require 'virustotal_api/user'
11
11
  require 'virustotal_api/version'
@@ -0,0 +1,16 @@
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
+ # @param [String] id The Virustotal ID to get the report for.
9
+ # @param [String] api_key The key for virustotal
10
+ # @return [VirustotalAPI::IP] Report
11
+ def self.find(id, api_key)
12
+ report = perform("/analyses/#{id}", api_key)
13
+ new(report)
14
+ end
15
+ end
16
+ end
@@ -3,22 +3,50 @@
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, :report_url, :id
13
+
14
+ def initialize(report)
15
+ @report = report
16
+ @report_url = report&.dig('data', 'links', 'self')
17
+ @id = report&.dig('data', 'id')
18
+ end
19
+
9
20
  # @return [String] string of API URI class method
10
21
  def self.api_uri
11
22
  VirustotalAPI::URI
12
23
  end
13
24
 
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
-
25
+ # The actual method performing a call to Virustotal
26
+ #
27
+ # @param [String] url The url of the API
28
+ # @param [String] api_key The key for virustotal
29
+ # @param [String] method The HTTP method to use
30
+ # @param [Hash] options Options to pass as payload
31
+ # @return [VirustotalAPI::Domain] Report Search Result
32
+ def self.perform(url, api_key, method = :get, options = {})
33
+ response = RestClient::Request.execute(
34
+ method: method,
35
+ url: api_uri + url,
36
+ headers: { 'x-apikey': api_key },
37
+ payload: options
38
+ )
21
39
  JSON.parse(response.body)
40
+ rescue RestClient::NotFound, RestClient::BadRequest
41
+ {}
42
+ rescue RestClient::Unauthorized
43
+ # Raise a custom exception not to expose the underlying
44
+ # HTTP client.
45
+ raise VirustotalAPI::Unauthorized
46
+ rescue RestClient::TooManyRequests
47
+ # Raise a custom exception not to expose the underlying
48
+ # HTTP client.
49
+ raise VirustotalAPI::RateLimitError
22
50
  end
23
51
 
24
52
  # @return [String] string of API URI instance method
@@ -27,11 +55,14 @@ module VirustotalAPI
27
55
  end
28
56
 
29
57
  # @return [Boolean] if report for resource exists
30
- # 0 => not_present, 1 => exists, -1 => invalid_ip_address
31
58
  def exists?
32
- response_code = report.fetch('response_code') { nil }
59
+ !report.empty?
60
+ end
33
61
 
34
- response_code == 1
62
+ # Generate a URL identifier.
63
+ # @see https://developers.virustotal.com/v3.0/reference#url
64
+ def self.url_identifier(url)
65
+ Base64.strict_encode64(url).strip.gsub('=', '')
35
66
  end
36
67
  end
37
68
  end