Class: VirustotalApiService

Inherits:
Object
  • Object
show all
Defined in:
app/services/virustotal_api_service.rb

Constant Summary collapse

API_KEY =
Rails.application.credentials.virus_total_api_key
API_URL =
'https://www.virustotal.com/api/v3'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeVirustotalApiService

Returns a new instance of VirustotalApiService.



5
6
7
# File 'app/services/virustotal_api_service.rb', line 5

def initialize
  # No instance variables needed, but allows instantiation for controller use
end

Class Method Details

.soft_parse(body) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
# File 'app/services/virustotal_api_service.rb', line 84

def soft_parse(body)
  case body
  when Hash
    body
  when String
    JSON.parse(body)
  else
    body || {}
  end
rescue StandardError
  {}
end

Instance Method Details

#check_scan_result(analysis_id) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'app/services/virustotal_api_service.rb', line 32

def check_scan_result(analysis_id)
  raise ArgumentError, 'No analysis ID provided' unless analysis_id.present?

  response = Faraday.get(
    "#{API_URL}/analyses/#{analysis_id}",
    {},
    { 'x-apikey' => API_KEY }
  )

  handle_response(response)
rescue StandardError => e
  raise e
end

#scan_file(file_path) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'app/services/virustotal_api_service.rb', line 9

def scan_file(file_path)
  file = File.open(file_path, 'rb')

  begin
    filename = File.basename(file_path)
    upload_io = Faraday::UploadIO.new(file, 'application/octet-stream', filename)
    payload = { file: upload_io }
    headers = { 'x-apikey' => API_KEY }

    connection = conn
    response = connection.post('/api/v3/files', payload, headers)

    raise "VirusTotal API redirected to #{response.headers['location']}" if [301, 302].include?(response.status)
    raise 'VirusTotal API returned empty response body' if response.body.nil? || response.body == ''

    self.class.soft_parse(response.body)
  rescue Faraday::Error => e
    raise e
  ensure
    file.close
  end
end