VCL component for VirusTotal Submit

Does TMS have a VCL component to submit an executable (as a file or as Hash) to VirusTotal?

Unfortunately there's currently no component available that offers built-in functionality for VirusTotal.
However this is a good suggestion and we'll consider adding this functionality in a future version of TMS FNC Cloud Pack.

Alternatively TMS FNC Cloud Pack can be used to manually implement a custom service. Further details can be found in the documentation:

https://download.tmssoftware.com/doc/tmsfnccloudpack/gettingstarted/overview/#implement-a-custom-service

Previously, I have tried it with this code:

procedure UploadFileToVirusTotal(const FilePath: string; const ApiKey: string);
var
  HTTP: TIdHTTP;
  SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
  FormData: TIdMultiPartFormDataStream;
  Response: string;
  Attempts, MaxAttempts: Integer;
  RetryAfter: Integer;
begin
  MaxAttempts := 5; // Set the maximum number of attempts
  Attempts := 0;
  RetryAfter := 1000; // Initial delay in milliseconds (1 second)

  HTTP := TIdHTTP.Create(nil);
  SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  FormData := TIdMultiPartFormDataStream.Create;
  try
    SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_2];
    HTTP.IOHandler := SSLHandler;
    HTTP.Request.CustomHeaders.Values['x-apikey'] := ApiKey;

    FormData.AddFile('file', FilePath, 'application/octet-stream');

    repeat
      try
        Inc(Attempts);
        Response := HTTP.Post('https://www.virustotal.com/api/v3/files', FormData);
        Break; // If successful, exit the loop
      except
        on E: EIdHTTPProtocolException do
        begin
          if HTTP.ResponseCode = 429 then
          begin
            CodeSite.Send('UploadFileToVirusTotal: HTTP.ResponseCode = 429');
            if Attempts >= MaxAttempts then
            begin
              CodeSite.Send('UploadFileToVirusTotal: Attempts >= MaxAttempts');
              raise; // If maximum attempts reached, rethrow the exception
            end;

            Sleep(RetryAfter); // Wait before retrying
            CodeSite.Send('UploadFileToVirusTotal: After Sleep');
            RetryAfter := RetryAfter * 2; // Exponential backoff
          end
          else
          begin
            CodeSite.Send('UploadFileToVirusTotal: HTTP.ResponseCode <> 429');
            raise; // For other HTTP errors, rethrow the exception
          end;
        end;
      end;
    until False;

    CodeSite.Send('UploadFileToVirusTotal: Response', Response);
  finally
    HTTP.Free;
    SSLHandler.Free;
    FormData.Free;
  end;
end;

But it seems the rate limit was reached - I got these CodeSite messages:

UploadFileToVirusTotal: HTTP.ResponseCode = 429
UploadFileToVirusTotal: After Sleep

UploadFileToVirusTotal: HTTP.ResponseCode = 429
UploadFileToVirusTotal: After Sleep

UploadFileToVirusTotal: HTTP.ResponseCode = 429
UploadFileToVirusTotal: After Sleep

UploadFileToVirusTotal: HTTP.ResponseCode = 429

UploadFileToVirusTotal: After Sleep

UploadFileToVirusTotal: HTTP.ResponseCode = 429
UploadFileToVirusTotal: Attempts >= MaxAttempts