Compare commits

..

3 Commits

2 changed files with 26 additions and 7 deletions

View File

@ -26,9 +26,12 @@
(defvar org-reminder-ntfy-base "https://ntfy.unbl.ink"
"Base URL of the ntfy server.")
(defvar org-reminder-ntfy-topic "org-tasks"
(defvar org-reminder-ntfy-topic "reminders"
"ntfy topic to publish task reminders to.")
(defvar org-reminder-ntfy-priority "4"
"ntfy priority for task reminders (1 min, 2 low, 3 default, 4 high, 5 urgent).")
(defvar org-reminder-state-file "~/.cache/org-reminders.el"
"File persisting already-sent reminders.")
@ -49,6 +52,17 @@ Set to \"none\" to disable the default entirely.")
(defvar org-reminder-last-refresh 0
"Timestamp of the last org-agenda-files refresh.")
(defvar org-reminder-run-hosts nil
"Hostnames (as reported by `system-name') allowed to send reminders.
nil means run on every host. Set to a list like (\"mundilfari\") to
restrict reminder delivery to specific machines.")
(defun org-reminder-host-enabled-p ()
"Return non-nil if this host is allowed to send reminders."
(or (null org-reminder-run-hosts)
(member (downcase (system-name))
(mapcar #'downcase org-reminder-run-hosts))))
(defun org-reminder-parse-intervals (str)
"Parse reminder offset string STR into a list of (LABEL . SECONDS).
STR looks like \"2d 3h 30m\" (also accepts commas or semicolons).
@ -113,7 +127,7 @@ Each spec is (ID HEADING FIRE-TIME LABEL SECONDS)."
(let ((subtree-end (save-excursion (org-end-of-subtree t t))))
(if (and (org-get-todo-state) (not (org-entry-is-done-p)))
(let* ((heading (string-trim (org-get-heading t t t t)))
(id (or (org-entry-get nil "ID" t)
(id (or (org-entry-get nil "ID")
(format "%s|%s" file heading)))
(rem (org-entry-get nil "REMINDER" t))
(anchor (progn
@ -176,6 +190,7 @@ Uses an mtime cache so unchanged files are not re-parsed."
"-s" "-f"
"-H" (format "Title: %s" (substring-no-properties title))
"-H" "Tags: bell"
"-H" (format "Priority: %s" org-reminder-ntfy-priority)
"-d" body
url)))
(unless (zerop exit)
@ -216,7 +231,8 @@ Uses an mtime cache so unchanged files are not re-parsed."
(defun org-reminder-check ()
"Send any due org task reminders via ntfy."
(interactive)
(condition-case err
(if (org-reminder-host-enabled-p)
(condition-case err
(let ((now (float-time)))
(dolist (spec (org-reminder-collect))
(pcase spec
@ -226,7 +242,7 @@ Uses an mtime cache so unchanged files are not re-parsed."
(< now (+ fire (* org-reminder-grace-minutes 60)))
(not (gethash key org-reminder-state)))
(org-reminder-send
(format "Reminder: %s" heading)
(format "🔔 %s" heading)
(format "Due %s — %s away"
(format-time-string "%a %b %e %H:%M" (+ fire secs))
(org-reminder-human-delta (- (+ fire secs) now))))
@ -234,12 +250,14 @@ Uses an mtime cache so unchanged files are not re-parsed."
(org-reminder-state-save)
(message "org-reminders: sent '%s' (%s)" heading label)))))
(org-reminder-prune-state now)))
(error (message "org-reminders: check failed: %S" err))))
(error (message "org-reminders: check failed: %S" err)))
(message "org-reminders: host %s not enabled for reminders, skipping" (system-name))))
(defun org-reminder-start ()
"Load state and start the periodic reminder check."
"Load state and start the periodic reminder check on this host."
(org-reminder-state-load)
(run-with-timer 60 60 #'org-reminder-check))
(when (org-reminder-host-enabled-p)
(run-with-timer 60 60 #'org-reminder-check)))
(provide '+org-reminders)

View File

@ -43,6 +43,7 @@
(load! "+agenda-fix")
(load! "+org-reminders")
(setq org-reminder-run-hosts '("mundilfari"))
(defun vulpea-agenda-files-update (&rest _)
(setq org-agenda-files vulpea-project-files))