Nothing
#' Rate Limiting for VirusTotal API
#'
#' @description
#' Modern rate limiting implementation that properly manages API request limits.
#' VirusTotal public API allows 4 requests per minute.
#'
#' @name rate-limiting
#' @keywords internal
#' @family rate limiting
NULL
.virustotal_state <- new.env(parent = emptyenv())
#' Initialize rate limiting state
#'
#' @keywords internal
init_rate_limit <- function() {
.virustotal_state$requests <- numeric(0)
.virustotal_state$window_size <- 60
.virustotal_state$max_requests <- 4
.virustotal_state$initialized <- TRUE
}
#' Check if rate limiting is properly initialized
#'
#' @keywords internal
is_rate_limit_initialized <- function() {
!is.null(.virustotal_state$initialized) &&
!is.null(.virustotal_state$requests) &&
!is.null(.virustotal_state$window_size) &&
!is.null(.virustotal_state$max_requests)
}
#' Modern rate limiting implementation
#'
#' Uses a sliding window approach to track requests and enforce limits.
#' This replaces the old environment variable-based approach.
#'
#' @param force_wait Logical. If TRUE, will wait even if under limit
#' @return Invisible TRUE
#' @keywords internal
#' @family rate limiting
rate_limit <- function(force_wait = FALSE) {
if (!is_rate_limit_initialized()) {
init_rate_limit()
}
current_time <- as.numeric(Sys.time())
window_size <- .virustotal_state$window_size
if (is.null(window_size)) window_size <- 60
window_start <- current_time - window_size
requests <- .virustotal_state$requests
if (is.null(requests)) requests <- numeric(0)
if (length(requests) > 0) {
active_requests <- requests[requests > window_start]
} else {
active_requests <- numeric(0)
}
.virustotal_state$requests <- active_requests
max_requests <- .virustotal_state$max_requests
if (is.null(max_requests)) max_requests <- 4
if (length(.virustotal_state$requests) >= max_requests || force_wait) {
if (length(.virustotal_state$requests) > 0) {
oldest_request <- min(active_requests)
wait_time <- max(0, window_size - (current_time - oldest_request))
if (wait_time > 0) {
message(sprintf("Rate limit reached. Waiting %.1f seconds...",
wait_time))
Sys.sleep(wait_time + 0.1)
current_time <- as.numeric(Sys.time())
window_start <- current_time - window_size
requests_after_wait <- .virustotal_state$requests
if (!is.null(requests_after_wait) && length(requests_after_wait) > 0) {
keep <- requests_after_wait > window_start
active_after <- requests_after_wait[keep]
} else {
active_after <- numeric(0)
}
.virustotal_state$requests <- active_after
}
}
}
.virustotal_state$requests <- c(.virustotal_state$requests, current_time)
invisible(TRUE)
}
#' Get current rate limit status
#'
#' @return List with current status information
#' @keywords internal
#' @family rate limiting
get_rate_limit_status <- function() {
if (!is_rate_limit_initialized()) {
init_rate_limit()
}
current_time <- as.numeric(Sys.time())
window_size <- .virustotal_state$window_size
if (is.null(window_size)) window_size <- 60
max_requests <- .virustotal_state$max_requests
if (is.null(max_requests)) max_requests <- 4
requests <- .virustotal_state$requests
if (is.null(requests)) requests <- numeric(0)
window_start <- current_time - window_size
if (length(requests) > 0) {
active_requests <- requests[requests > window_start]
} else {
active_requests <- numeric(0)
}
list(
requests_used = length(active_requests),
max_requests = max_requests,
window_size = window_size,
requests_remaining = max_requests - length(active_requests),
window_reset_time = if (length(active_requests) > 0) {
min(active_requests) + window_size
} else {
current_time
}
)
}
#' Reset rate limiting state
#'
#' Clears all rate limiting history. Useful for testing.
#'
#' @keywords internal
#' @family rate limiting
reset_rate_limit <- function() {
init_rate_limit()
message("Rate limiting state reset.")
invisible(TRUE)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.