Update copyright year to 2016
[gnus] / lisp / gnus-notifications.el
index 348bbbe..54a75b6 100644 (file)
@@ -1,6 +1,6 @@
 ;; gnus-notifications.el -- Send notification on new message in Gnus
 
-;; Copyright (C) 2012 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
 
 ;; Author: Julien Danjou <julien@danjou.info>
 ;; Keywords: news
 
 ;;; Code:
 
-(require 'notifications)
+(ignore-errors
+  (require 'notifications))
 (require 'gnus-sum)
 (require 'gnus-group)
 (require 'gnus-int)
 (require 'gnus-art)
 (require 'gnus-util)
-(require 'google-contacts nil t)        ; Optional
+(ignore-errors
+  (require 'google-contacts))        ; Optional
+(require 'gnus-fun)
 
 (defgroup gnus-notifications nil
   "Send notifications on new message in Gnus."
+  :version "24.3"
   :group 'gnus)
 
 (defcustom gnus-notifications-use-google-contacts t
@@ -58,15 +62,63 @@ not get notifications."
   :type 'integer
   :group 'gnus-notifications)
 
+(defcustom gnus-notifications-timeout nil
+  "Timeout used for notifications sent via `notifications-notify'."
+  :type '(choice (const :tag "Server default" nil)
+                 (integer :tag "Milliseconds"))
+  :group 'gnus-notifications)
+
 (defvar gnus-notifications-sent nil
   "Notifications already sent.")
 
+(defvar gnus-notifications-id-to-msg nil
+  "Map notifications ids to messages.")
+
+(defun gnus-notifications-action (id key)
+  (let ((group-article (assoc id gnus-notifications-id-to-msg)))
+    (when group-article
+      (let ((group (cadr group-article))
+            (article (nth 2 group-article)))
+        (cond ((string= key "read")
+               (gnus-fetch-group group (list article))
+               (gnus-select-frame-set-input-focus (selected-frame)))
+              ((string= key "mark-read")
+               (gnus-update-read-articles
+                group
+                (delq article (gnus-list-of-unread-articles group)))
+               ;; gnus-group-refresh-group
+               (gnus-group-update-group group)))))))
+
+(defun gnus-notifications-notify (from subject photo-file)
+  "Send a notification about a new mail.
+Return a notification id if any, or t on success."
+  (if (fboundp 'notifications-notify)
+      (gnus-funcall-no-warning
+       'notifications-notify
+       :title from
+       :body subject
+       :actions '("read" "Read" "mark-read" "Mark As Read")
+       :on-action 'gnus-notifications-action
+       :app-icon (gnus-funcall-no-warning
+                  'image-search-load-path "gnus/gnus.png")
+       :image-path photo-file
+       :app-name "Gnus"
+       :category "email.arrived"
+       :timeout gnus-notifications-timeout)
+    (message "New message from %s: %s" from subject)
+    ;; Don't return an id
+    t))
+
+(declare-function gravatar-retrieve-synchronously "gravatar.el"
+                 (mail-address))
+
 (defun gnus-notifications-get-photo (mail-address)
   "Get photo for mail address."
   (let ((google-photo (when (and gnus-notifications-use-google-contacts
                                  (fboundp 'google-contacts-get-photo))
                         (ignore-errors
-                          (google-contacts-get-photo mail-address)))))
+                          (gnus-funcall-no-warning
+                          'google-contacts-get-photo mail-address)))))
     (if google-photo
         google-photo
       (when gnus-notifications-use-gravatar
@@ -87,7 +139,7 @@ Returns nil if no image found."
       (let ((photo-file (make-temp-file "gnus-notifications-photo-"))
             (coding-system-for-write 'binary))
         (with-temp-file photo-file
-            (insert photo))
+          (insert photo))
         photo-file))))
 
 ;;;###autoload
@@ -124,24 +176,25 @@ This is typically a function to add in
                 (article-decode-encoded-words) ; to decode mail addresses, subjects, etc
                 (let* ((address-components (mail-extract-address-components
                                             (or (mail-fetch-field "From") "")))
-                       (address (cadr address-components))
-                       (photo-file (gnus-notifications-get-photo-file
-                                    address)))
-                  (when (or
-                         ;; Ignore mails from ourselves
-                         (gnus-string-match-p gnus-ignored-from-addresses
-                                              address)
-                         (notifications-notify :title (concat "New message from "
-                                                              (or (car address-components) address))
-                                               :body (mail-fetch-field "Subject")
-                                               :app-icon (image-search-load-path "gnus/gnus.png")
-                                               :app-name "Gnus"
-                                               :category "email.arrived"
-                                               :image-path photo-file))
-                    ;; Register that we did notify this message
-                    (setcdr group-notifications (cons article (cdr group-notifications))))
-                  (when photo-file
-                    (delete-file photo-file)))))))))))
+                       (address (cadr address-components)))
+                  ;; Ignore mails from ourselves
+                  (unless (and gnus-ignored-from-addresses
+                               address
+                               (gnus-string-match-p gnus-ignored-from-addresses
+                                                    address))
+                    (let* ((photo-file (gnus-notifications-get-photo-file address))
+                           (notification-id (gnus-notifications-notify
+                                             (or (car address-components) address)
+                                             (mail-fetch-field "Subject")
+                                             photo-file)))
+                      (when notification-id
+                        ;; Register that we did notify this message
+                        (setcdr group-notifications (cons article (cdr group-notifications)))
+                        (unless (eq notification-id t)
+                          ;; Register the notification id for later actions
+                          (add-to-list 'gnus-notifications-id-to-msg (list notification-id group article))))
+                      (when photo-file
+                        (delete-file photo-file)))))))))))))
 
 (provide 'gnus-notifications)