virustotal_api 0.4.1 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
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