1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#' Progression Handler: Progress Reported via the Pushbullet Messaging Service
#'
#' A progression handler for [RPushbullet::pbPost()] of the \pkg{RPushbullet}
#' package.
#'
#' @inheritParams make_progression_handler
#' @inheritParams RPushbullet::pbPost
#'
#' @param \ldots Additional arguments passed to [make_progression_handler()].
#'
#' @example incl/handler_rpushbullet.R
#'
#' @section Requirements:
#' This progression handler requires the \pkg{RPushbullet} package, a
#' Pushbullet account, and configuration according to the instructions
#' of the \pkg{RPushbullet} package. It also requires internet access
#' from the computer where this progress handler is registered.
#'
#' @export
handler_rpushbullet <- function(intrusiveness = getOption("progressr.intrusiveness.rpushbullet", 5), target = "gui", ..., title = "Progress update from R", recipients = NULL, email = NULL, channel = NULL, apikey = NULL, devices = NULL) {
## Used for package testing purposes only when we want to perform
## everything except the last part where the backend is called
pbPost <- function(...) NULL
if (!is_fake("handler_rpushbullet")) {
pkg <- "RPushbullet"
if (!requireNamespace(pkg, quietly = TRUE)) {
stop("Package RPushbullet is not available")
}
if (is_rpushbullet_working()) {
pbPost <- get("pbPost", mode = "function", envir = getNamespace(pkg))
}
}
notifier <- function(title, message) {
args <- list(
type = "note",
title = title,
body = paste(c("", message), collapse = "")
)
if (!is.null(recipients)) args$recipients <- recipients
if (!is.null(email)) args$email <- email
if (!is.null(channel)) args$channel <- channel
if (!is.null(apikey)) args$apikey <- apikey
if (!is.null(devices)) args$devices <- devices
do.call(pbPost, args = args)
}
reporter <- local({
finished <- FALSE
list(
reset = function(...) {
finished <<- FALSE
},
initiate = function(config, state, progression, ...) {
if (!state$enabled || config$times == 1L) return()
progress_notify(title = title, step = state$step, max_steps = config$max_steps, message = state$message, notifier = notifier)
},
interrupt = function(config, state, progression, ...) {
msg <- conditionMessage(progression)
progress_notify(title = title, step = state$step, max_steps = config$max_steps, message = msg, notifier = notifier)
},
update = function(config, state, progression, ...) {
if (!state$enabled || progression$amount == 0 || config$times <= 2L) return()
progress_notify(title = title, step = state$step, max_steps = config$max_steps, message = state$message, notifier = notifier)
},
finish = function(config, state, progression, ...) {
if (finished) return()
if (!state$enabled) return()
if (state$delta > 0) progress_notify(title = title, step = state$step, max_steps = config$max_steps, message = state$message, notifier = notifier)
finished <<- TRUE
}
)
})
make_progression_handler("rpushbullet", reporter, intrusiveness = intrusiveness, target = target, ...)
}
attr(handler_rpushbullet, "validator") <- function() is_rpushbullet_working()
is_rpushbullet_working <- local({
res <- NA
pkg <- "RPushbullet"
function(quiet = TRUE) {
if (!is.na(res)) return(res)
## Assert RPushbullet package
if (!requireNamespace(pkg, quietly = TRUE)) {
warning(sprintf("Package %s is not installed", sQuote(pkg)), immediate. = TRUE)
return(FALSE)
}
## Assert internet access
curl <- "curl"
if (!requireNamespace(curl, quietly = TRUE)) {
warning(sprintf("Package %s is not installed", sQuote(curl)), immediate. = TRUE)
return(FALSE)
}
has_internet <- get("has_internet", mode = "function", envir = getNamespace(curl))
if (!has_internet()) {
warning("No internet access. The 'rpushbullet' progress handler requires working internet.", immediate. = TRUE)
return(FALSE)
}
## Validate RPushbullet configuration with 10-second timeout
timeout <- 10.0
setTimeLimit(cpu = timeout, elapsed = timeout, transient = TRUE)
on.exit({
setTimeLimit(cpu = Inf, elapsed = Inf, transient = FALSE)
})
conds <- list()
withCallingHandlers({
tryCatch({
res <<- RPushbullet::pbValidateConf()
}, error = function(ex) {
conds <<- c(conds, list(ex))
})
}, message = function(cond) {
conds <<- c(conds, list(cond))
if (quiet) invokeRestart("muffleMessage")
}, warning = function(cond) {
conds <<- c(conds, list(cond))
if (quiet) invokeRestart("muffleWarning")
})
if (is.na(res)) res <- FALSE
if (!res) {
msg <- vapply(conds, FUN.VALUE = NA_character_, FUN = conditionMessage)
msg <- gsub("\n$", "", msg)
msg <- gsub("^", " ", msg)
warning(paste(c("The 'rpushbullet' progress handler will not work, because RPushbullet is not properly configured. See help(\"pbSetup\", package = \"RPushbullet\") for instructions. RPushbullet::pbValidateConf() reported:", msg), collapse = "\n"), immediate. = TRUE)
}
res
}
})
|