;; -*- mode: scheme; -*- (use-modules (ice-9 popen)) (use-modules (rnrs io ports)) ;; This cannot be let-bound within `job'. (define currency-file (string-append (getenv "HOME") "/.cache/currency.units")) (define* (system-to-string #:rest args) (let* ((port (apply open-pipe* OPEN_READ args)) (str (get-string-all port))) (close-pipe port) str)) (define (gpg-keyinfo) "Return GPG keyinfo as a list of list of strings. Typical output is: S KEYINFO ???????????????????????????????????????? D - - - P - - - S KEYINFO ???????????????????????????????????????? D - - 1 P - - - The \"1\" means the key is cached." (filter (lambda (info) (string= (car info) "S")) (map (lambda (s) (string-split s #\space)) (string-split (system-to-string "gpg-connect-agent" "keyinfo --list" "/bye") #\newline)))) (define (gpg-key-cached?) "Return #t if a key is cached in the GPG agent, #f otherwise." (let ((keyinfo (gpg-keyinfo))) (not (null? (filter (lambda (info) (string= (list-ref info 6) "1")) keyinfo))))) (job (lambda (current-time) (let* ((seconds-in-a-day (* 60 60 24)) (currency-time (if (not (file-exists? currency-file)) 0 (stat:mtime (stat currency-file))))) (if (< currency-time (- current-time seconds-in-a-day)) ;; Use next-minute to avoid overwhelming the system in case of failure. (next-minute) (next-hour-from (next-day) (list (tm:hour (localtime currency-time))))))) ;; A string is nicer than Scheme code for `mcron --schedule' output. ;; Otherwise we could return '(system* "units_cur" currency-file) ;; and use job's 3rd argument as a description. (string-append "units_cur " currency-file)) (job '(next-hour (range 0 24 3)) "updatedb-local") ;; (job '(next-minute (range 0 60 15)) ;; (lambda () ;; (when (gpg-key-cached?) ;; ;; Email is sync'ed from a pre-new hook. ;; (system* "notmuch" "new"))) ;; "mail")