ruby-deepviz 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e6999d5f4123bd1008e08680b767d07182a366bc
4
+ data.tar.gz: c1789782ba04e29cff292cbcf62b7829334ffd14
5
+ SHA512:
6
+ metadata.gz: b270f7c5adf1a4d60ee6b16b9ada00d2fb108b6528142610a136ffa3e28fe24cbee0f04b86e5d655325f81113be2553850379f51f09924f12e83ec44fbfd10a8
7
+ data.tar.gz: 2e68c2ebf0d5dd8be2ba88047103b65d244c4aaa50348d3f98f12263ee278bd1b9dbeeda848e0970e9189d846422acd8490a5c0eaf1b1970229fcf6ba53e9bb3
@@ -0,0 +1,274 @@
1
+ require 'deepviz/result'
2
+
3
+ class Intel
4
+
5
+ URL_INTEL_SEARCH = 'https://api.deepviz.com/intel/search'
6
+ URL_INTEL_IP = 'https://api.deepviz.com/intel/network/ip'
7
+ URL_INTEL_DOMAIN = 'https://api.deepviz.com/intel/network/domain'
8
+ URL_INTEL_SEARCH_ADVANCED = 'https://api.deepviz.com/intel/search/advanced'
9
+
10
+ def ip_info(api_key, options={})
11
+ if api_key == nil or api_key == ''
12
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
13
+ end
14
+
15
+ defaults = {
16
+ :ip => nil,
17
+ :history => false,
18
+ :time_delta => nil,
19
+ }
20
+
21
+ options = defaults.merge(options)
22
+
23
+ if (!options['ip'].kind_of?(Array) and (options['time_delta'] == nil or options['time_delta'] == '')) or (options['ip'].kind_of?(Array) and options['time_delta'] != nil and options['time_delta'] != '')
24
+ msg = 'Parameters missing or invalid. You must specify either a list of IPs or time delta'
25
+ return Result.new(status=INPUT_ERROR, msg=msg)
26
+ end
27
+
28
+ if options['history']
29
+ _history = 'true'
30
+ else
31
+ _history = 'false'
32
+ end
33
+
34
+ if options['ip'] != nil and !options['ip'].kind_of?(Array)
35
+ msg = 'You must provide one or more IPs in a list'
36
+ return Result.new(status=INPUT_ERROR, msg=msg)
37
+ else
38
+ body = {
39
+ :ip => options['ip'],
40
+ :history => _history,
41
+ :api_key => api_key,
42
+ }
43
+ end
44
+
45
+ if options['time_delta'] != nil and options['time_delta'] != ''
46
+ body = {
47
+ :time_delta => options['time_delta'],
48
+ :history => _history,
49
+ :api_key => api_key,
50
+ }
51
+ end
52
+
53
+ return do_post(body, URL_INTEL_IP)
54
+ end
55
+
56
+ def domain_info(api_key, options={})
57
+ if api_key == nil or api_key == ''
58
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
59
+ end
60
+
61
+ defaults = {
62
+ :domain => nil,
63
+ :filters => nil,
64
+ :history => false,
65
+ :time_delta => nil,
66
+ }
67
+
68
+ options = defaults.merge(options)
69
+
70
+ if (!options['domain'].kind_of?(Array) and (options['time_delta'] == nil or options['time_delta'] == '')) or (options['domain'].kind_of?(Array) and options['time_delta'] != nil and options['time_delta'] != '')
71
+ msg = 'Parameters missing or invalid. You must specify either a list of domains or time delta'
72
+ return Result.new(status=INPUT_ERROR, msg=msg)
73
+ end
74
+
75
+ if options['history']
76
+ _history = 'true'
77
+ else
78
+ _history = 'false'
79
+ end
80
+
81
+ if options['filters'] != nil and !options['filters'].kind_of?(Array)
82
+ msg = 'You must provide one or more output filters in a list'
83
+ return Result.new(status=INPUT_ERROR, msg=msg)
84
+ end
85
+
86
+ body = {}
87
+
88
+ if options['domain'].kind_of?(Array)
89
+ if options['filters'] != nil
90
+ body = {
91
+ :output_filters => options['filters'],
92
+ :domain => options['domain'],
93
+ :history => _history,
94
+ :api_key => api_key,
95
+ }
96
+ else
97
+ body = {
98
+ :domain => options['domain'],
99
+ :history => _history,
100
+ :api_key => api_key,
101
+ }
102
+ end
103
+ end
104
+
105
+ if options['time_delta'] != nil and options['time_delta'] != ''
106
+ if options['filters'] != nil
107
+ body = {
108
+ :time_delta => options['time_delta'],
109
+ :output_filters => options['filters'],
110
+ :history => _history,
111
+ :api_key => api_key,
112
+ }
113
+ else
114
+ body = {
115
+ :time_delta => options['time_delta'],
116
+ :history => _history,
117
+ :api_key => api_key,
118
+ }
119
+ end
120
+ end
121
+
122
+ return do_post(body, URL_INTEL_DOMAIN)
123
+ end
124
+
125
+ def search(api_key, search_string, options={})
126
+ if api_key == nil or api_key == ''
127
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
128
+ end
129
+
130
+ if search_string == nil or search_string == ''
131
+ return Result.new(status=INPUT_ERROR, msg='String to be searched cannot be null or empty')
132
+ end
133
+
134
+ defaults = {
135
+ :start_offset => nil,
136
+ :elements => nil,
137
+ }
138
+
139
+ options = defaults.merge(options)
140
+
141
+ if options['start_offset'] != nil and options['elements'] != nil and options['start_offset'].is_a? Integer and !options['elements'].is_a? Integer
142
+ result_set = ['start=%d' % options['start_offset'], 'rows=%d' % options['elements']]
143
+
144
+ body = {
145
+ :'result_set' => result_set,
146
+ :'string' => search_string,
147
+ :'api_key' => api_key,
148
+ }
149
+ else
150
+ body = {
151
+ :'string' => search_string,
152
+ :'api_key' => api_key,
153
+ }
154
+ end
155
+
156
+ return do_post(body, URL_INTEL_SEARCH)
157
+ end
158
+
159
+ def advanced_search(api_key, options={})
160
+ if api_key == nil or api_key == ''
161
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
162
+ end
163
+
164
+ defaults = {
165
+ :classification => nil,
166
+ :created_files => nil,
167
+ :never_seen => false,
168
+ :time_delta => nil,
169
+ :result_set => nil,
170
+ :sim_hash => nil,
171
+ :imp_hash => nil,
172
+ :ip_range => nil,
173
+ :strings => nil,
174
+ :country => nil,
175
+ :domain => nil,
176
+ :rules => nil,
177
+ :asn => nil,
178
+ :url => nil,
179
+ :ip => nil,
180
+ }
181
+
182
+ options = defaults.merge(options)
183
+
184
+ body = {
185
+ :api_key => api_key
186
+ }
187
+
188
+ if options['created_files'].kind_of?(Array)
189
+ body[:created_files] = options['created_files']
190
+ end
191
+
192
+ _never_seen = 'false'
193
+ if options[:never_seen] != nil and options[:never_seen]
194
+ _never_seen = 'true'
195
+ end
196
+ body[:never_seen] = _never_seen
197
+
198
+ if options['result_set'].kind_of?(Array)
199
+ body[:result_set] = options['result_set']
200
+ end
201
+
202
+ if options['sim_hash'].kind_of?(Array)
203
+ body[:sim_hash] = options['sim_hash']
204
+ end
205
+
206
+ if options['imp_hash'].kind_of?(Array)
207
+ body[:imp_hash] = options['imp_hash']
208
+ end
209
+
210
+ if options['strings'].kind_of?(Array)
211
+ body[:strings] = options['strings']
212
+ end
213
+
214
+ if options['country'].kind_of?(Array)
215
+ body[:country] = options['country']
216
+ end
217
+
218
+ if options['classification'] != nil
219
+ body[:classification] = options['classification']
220
+ end
221
+
222
+ if options['domain'].kind_of?(Array)
223
+ body[:domain] = options['domain']
224
+ end
225
+
226
+ if options['rules'].kind_of?(Array)
227
+ body[:rules] = options['rules']
228
+ end
229
+
230
+ if options['time_delta'] != nil
231
+ body[:time_delta] = options['time_delta']
232
+ end
233
+
234
+ if options['asn'].kind_of?(Array)
235
+ body[:asn] = options['asn']
236
+ end
237
+
238
+ if options['url'].kind_of?(Array)
239
+ body[:url] = options['url']
240
+ end
241
+
242
+ if options['ip'].kind_of?(Array)
243
+ body[:ip] = options['ip']
244
+ end
245
+
246
+ if options['ip_range'] != nil
247
+ body[:ip_range] = options['ip_range']
248
+ end
249
+
250
+ return do_post(body, URL_INTEL_SEARCH_ADVANCED)
251
+ end
252
+
253
+ def do_post(body, api_uri)
254
+ begin
255
+ response = Unirest.post(api_uri,
256
+ headers:{ 'Content-Type' => 'application/json' },
257
+ parameters:body.to_json)
258
+ rescue Exception
259
+ return Result.new(status=NETWORK_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
260
+ end
261
+
262
+ if response.code == 200
263
+ return Result.new(status=SUCCESS, msg=response.body['data'])
264
+ else
265
+ if response.code >= 500
266
+ return Result.new(status=SERVER_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
267
+ else
268
+ return Result.new(status=CLIENT_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
269
+ end
270
+ end
271
+ end
272
+
273
+ private :do_post
274
+ end
@@ -0,0 +1,27 @@
1
+ SUCCESS = 'DEEPVIZ_STATUS_SUCCESS' # Request successfully submitted
2
+ PROCESSING = 'DEEPVIZ_STATUS_PROCESSING'
3
+ INPUT_ERROR = 'DEEPVIZ_STATUS_INPUT_ERROR'
4
+ SERVER_ERROR = 'DEEPVIZ_STATUS_SERVER_ERROR' # Http 5xx
5
+ CLIENT_ERROR = 'DEEPVIZ_STATUS_CLIENT_ERROR' # Http 4xx
6
+ NETWORK_ERROR = 'DEEPVIZ_STATUS_NETWORK_ERROR' # Cannot contact Deepviz
7
+ INTERNAL_ERROR = 'DEEPVIZ_STATUS_INTERNAL_ERROR'
8
+
9
+
10
+ class Result
11
+ attr_reader :status
12
+ attr_writer :status
13
+ attr_reader :msg
14
+ attr_writer :msg
15
+
16
+ @status = nil
17
+ @msg = nil
18
+
19
+ def initialize(status, msg)
20
+ @status = status
21
+ @msg = msg
22
+ end
23
+
24
+ def to_s
25
+ 'Result(status=%s, msg=%s)' % [@status, @msg]
26
+ end
27
+ end
@@ -0,0 +1,250 @@
1
+ require 'json'
2
+ require 'unirest'
3
+ require 'deepviz/result'
4
+
5
+
6
+ class Sandbox
7
+
8
+ URL_UPLOAD_SAMPLE = 'https://api.deepviz.com/sandbox/submit'
9
+ URL_DOWNLOAD_REPORT = 'https://api.deepviz.com/general/report'
10
+ URL_DOWNLOAD_SAMPLE = 'https://api.deepviz.com/sandbox/sample'
11
+ URL_DOWNLOAD_BULK = 'https://api.deepviz.com/sandbox/sample/bulk/retrieve'
12
+ URL_REQUEST_BULK = 'https://api.deepviz.com/sandbox/sample/bulk/request'
13
+
14
+
15
+ def upload_sample(api_key, path)
16
+ if api_key == nil or api_key == ''
17
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
18
+ end
19
+
20
+ if path == nil or path == ''
21
+ return Result.new(status=INPUT_ERROR, msg='File path cannot be null or empty String')
22
+ else
23
+ if !File.exist?(path)
24
+ return Result.new(status=INPUT_ERROR, msg='File does not exists')
25
+ else
26
+ if File.directory?(path)
27
+ return Result.new(status=INPUT_ERROR, msg='Path is a directory instead of a file')
28
+ else
29
+ if !File.readable?(path)
30
+ return Result.new(status=INPUT_ERROR, msg='Cannot open file "%s"' % File.absolute_path(path))
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ begin
37
+ response = Unirest.post(URL_UPLOAD_SAMPLE,
38
+ headers:{ 'Content-Type' => 'application/json' },
39
+ parameters:{ :api_key => api_key, :source => 'ruby_deepviz', :file => File.new(path, 'rb') })
40
+ rescue Exception
41
+ return Result.new(status=NETWORK_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, body['errmsg']])
42
+ end
43
+
44
+ if response.code == 200
45
+ return Result.new(status=SUCCESS, msg=response.body['data'])
46
+ else
47
+ if response.code >= 500
48
+ return Result.new(status=SERVER_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
49
+ else
50
+ return Result.new(status=CLIENT_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
51
+ end
52
+ end
53
+ end
54
+
55
+
56
+ def upload_folder(api_key, path)
57
+ if api_key == nil or api_key == ''
58
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
59
+ end
60
+
61
+ if path == nil or path == ''
62
+ return Result.new(status=INPUT_ERROR, msg='Folder path cannot be null or empty String')
63
+ else
64
+ if !File.exist?(path)
65
+ return Result.new(status=INPUT_ERROR, msg='Directory does not exists')
66
+ else
67
+ if !File.directory?(path)
68
+ return Result.new(status=INPUT_ERROR, msg='Path is a file instead of a directory')
69
+ end
70
+ end
71
+ end
72
+
73
+ if Dir.entries(path).length <= 2
74
+ return Result.new(status=INPUT_ERROR, msg='Empty folder')
75
+ end
76
+
77
+ Dir.foreach(path) { |x|
78
+ if x != '.' and x != '..'
79
+ file_path = File.join(path, x)
80
+ result = upload_sample(api_key, file_path)
81
+ if result.status != SUCCESS
82
+ result.msg = '"Unable to upload file "%s"' % file_path
83
+ return result
84
+ end
85
+ end
86
+ }
87
+
88
+ return Result.new(status=SUCCESS, msg='Every file in folder has been uploaded')
89
+ end
90
+
91
+
92
+ def download_sample(api_key, md5, path)
93
+ if api_key == nil or api_key == ''
94
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
95
+ end
96
+
97
+ if md5 == nil or md5 == ''
98
+ return Result.new(status=INPUT_ERROR, msg='MD5 cannot be null or empty String')
99
+ end
100
+
101
+ if path == nil or path == ''
102
+ return Result.new(status=INPUT_ERROR, msg='Destination path cannot be null or empty String')
103
+ else
104
+ if File.exist?(path) and !File.directory?(path)
105
+ return Result.new(status=INPUT_ERROR, msg='Invalid destination folder')
106
+ end
107
+ end
108
+
109
+ body = {
110
+ :api_key => api_key,
111
+ :md5 => md5
112
+ }
113
+
114
+ begin
115
+ response = Unirest.post(URL_DOWNLOAD_SAMPLE,
116
+ headers:{ 'Accept' => 'application/json' },
117
+ parameters:body.to_json)
118
+ rescue Exception
119
+ return Result.new(status=NETWORK_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, body['errmsg']])
120
+ end
121
+
122
+ if response.code == 200
123
+ dest_path = File.absolute_path(File.join(path, md5))
124
+ open(dest_path, 'wb') do |file|
125
+ file.write(response.body)
126
+ end
127
+
128
+ return Result.new(status=SUCCESS, msg='Sample downloaded to "%s"' % dest_path)
129
+ else
130
+ if response.code >= 500
131
+ return Result.new(status=SERVER_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
132
+ else
133
+ return Result.new(status=CLIENT_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
134
+ end
135
+ end
136
+ end
137
+
138
+
139
+ def sample_result(api_key, md5)
140
+ return sample_report(api_key, md5, ['classification'])
141
+ end
142
+
143
+
144
+ def sample_report(api_key, md5, filters=nil)
145
+ if api_key == nil or api_key == ''
146
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
147
+ end
148
+
149
+ if md5 == nil or md5 == ''
150
+ return Result.new(status=INPUT_ERROR, msg='MD5 cannot be null or empty String')
151
+ end
152
+
153
+ if filters != nil
154
+ body = {:api_key => api_key, :md5 => md5, :output_filters => filters}
155
+ else
156
+ body = {:api_key => api_key, :md5 => md5}
157
+ end
158
+
159
+ return do_post(body, URL_DOWNLOAD_REPORT)
160
+ end
161
+
162
+
163
+ def bulk_download_request(api_key, md5_list)
164
+ if api_key == nil or api_key == ''
165
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
166
+ end
167
+
168
+ if !md5_list.kind_of?(Array)
169
+ return Result.new(status=INPUT_ERROR, msg='MD5 list empty or invalid')
170
+ end
171
+
172
+ body = {
173
+ :api_key => api_key,
174
+ :hashes => md5_list
175
+ }
176
+
177
+ return do_post(body, URL_REQUEST_BULK)
178
+ end
179
+
180
+
181
+ def bulk_download_retrieve(api_key, id_request, path)
182
+ if api_key == nil or api_key == ''
183
+ return Result.new(status=INPUT_ERROR, msg='API key cannot be null or empty String')
184
+ end
185
+
186
+ if id_request == nil or id_request == ''
187
+ return Result.new(status=INPUT_ERROR, msg='Request ID cannot be null or empty String')
188
+ end
189
+
190
+ if path == nil or path == ''
191
+ return Result.new(status=INPUT_ERROR, msg='Destination path cannot be null or empty String')
192
+ else
193
+ if File.exist?(path) and !File.directory?(path)
194
+ return Result.new(status=INPUT_ERROR, msg='Invalid destination folder')
195
+ end
196
+ end
197
+
198
+ body = {
199
+ :api_key => api_key,
200
+ :id_request => id_request.to_s
201
+ }
202
+
203
+ begin
204
+ response = Unirest.post(URL_DOWNLOAD_BULK,
205
+ headers: { 'Accept' => 'application/json' },
206
+ parameters: body.to_json)
207
+ rescue Exception
208
+ return Result.new(status=NETWORK_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, body['errmsg']])
209
+ end
210
+
211
+ if response.code == 200
212
+ dest_path = File.absolute_path(File.join(path, 'bulk_request_%s.zip' % id_request.to_s))
213
+ open(dest_path, 'wb') do |file|
214
+ file.write(response.body)
215
+ end
216
+
217
+ return Result.new(status=SUCCESS, msg='Archive downloaded to "%s"' % dest_path)
218
+ elsif response.code == 428
219
+ return Result.new(status=PROCESSING, msg='%s - Your request is being processed. Please try again in a few minutes' % response.code)
220
+ else
221
+ if response.code >= 500
222
+ return Result.new(status=SERVER_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
223
+ else
224
+ return Result.new(status=CLIENT_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
225
+ end
226
+ end
227
+ end
228
+
229
+ def do_post(body, api_uri)
230
+ begin
231
+ response = Unirest.post(api_uri,
232
+ headers:{ 'Content-Type' => 'application/json' },
233
+ parameters:body.to_json)
234
+ rescue Exception
235
+ return Result.new(status=NETWORK_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
236
+ end
237
+
238
+ if response.code == 200
239
+ return Result.new(status=SUCCESS, msg=response.body['data'])
240
+ else
241
+ if response.code >= 500
242
+ return Result.new(status=SERVER_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
243
+ else
244
+ return Result.new(status=CLIENT_ERROR, msg='%s - Error while connecting to Deepviz: %s' % [response.code, response.body['errmsg']])
245
+ end
246
+ end
247
+ end
248
+
249
+ private :do_post
250
+ end
@@ -0,0 +1,3 @@
1
+ module Deepviz
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-deepviz
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Saferbytes S.r.l.s.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.12.a
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.12.a
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: unirest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.1.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.1.2
55
+ description:
56
+ email: info@deepviz.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/deepviz/intel.rb
62
+ - lib/deepviz/result.rb
63
+ - lib/deepviz/sandbox.rb
64
+ - lib/deepviz/version.rb
65
+ homepage: https://www.deepviz.com
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.2.2
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: ruby-deepviz is a Ruby wrapper for deepviz.com REST APIs
89
+ test_files: []