;;; gnuslog.el --- Gnus Splitting Log Facility
;; Copyright (C) 2003
;; Author: Johan Bockgård
;;
;; Maintainer: Adrian Aichner
;; Version: 1.5
;; Keywords: gnus log splitting
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; Hooks into gnus splitting functions and writes a log to file. The
;; log file can be viewed in Gnus as a Document Group.
;;; Disclaimer: I only use the nnfolder back end.
;;; Usage:
;; Load the code by putting (require 'gnuslog) in your ~/.gnus file.
;; Create a document group for the log file using G f ~/.gnuslog RET
;; in the summary buffer.
;;; Code:
;;; Nndoc Type Definition
;; Avoid miscompiling macro `gnus-gethash' and other macros in absence
;; of loaded definition from 'gnus.
;; See 2004-03-15_23-01_macro_err_1.txt in
;; http://labb.contactor.se/~matsl/smoketest/logs/
;; or newer results for miscompiled macros.
(eval-when-compile (require 'gnus))
(defun nndoc-gnuslog-type-p ()
;; This is slightly ugly
(equal (expand-file-name gnuslog-file) nndoc-address))
(nndoc-add-type '(gnuslog (article-begin . "^From")) 'last)
;;; Logging
(defvar gnuslog-file "~/.gnuslog")
(defvar gnuslog-file-coding-system
(if (featurep 'xemacs)
'binary
'emacs-mule))
(defun gnuslog-setup-hook ()
(unless
(gnus-gethash
(format "nndoc+%s:%s"
(expand-file-name gnuslog-file)
(file-name-nondirectory gnuslog-file))
gnus-newsrc-hashtb)
(cond
((gnus-group-make-doc-group gnuslog-file 'gnuslog)
(message "gnuslog-file %S has now been subscribed to."
gnuslog-file))
(t
(error "gnuslog-file %S has not been subscribed to."))))
(defadvice nnmail-article-group (after nnmail-log activate)
;; Catch the return value (group-art-list)
(gnuslog-log ad-return-value)))
; In the current implementation it's critical to use the appropriate
; hook:
; gnus-newsrc-hashtb needs to be set up already and no mail must have
; been processed yet!
(add-hook 'gnus-read-newsrc-el-hook
'gnuslog-setup-hook
'append)
;; If we don't want to catch duplicates we could just use
;; nnmail-spool-hook, called as
;; (run-hook-with-args 'nnmail-spool-hook id grp subject)
(defun gnuslog-log (group-art-list)
;; Is this call inside `nnmail-check-duplication'? that means(?)
;; this is incoming mail.
(when (boundp 'duplication)
;; Use (boundp 'gnus-command-method),
;; bound during `B r', not by `B q' or `B t'?.
(let ((msg (save-excursion
(save-restriction
(article-narrow-to-head)
(concat
(mapconcat (lambda (field)
(concat field ": " (message-fetch-field field)))
'("From" "To" "Subject" "Date")
"\n")
(format "\nReferences: %s"
(message-fetch-field "Message-ID"))
"\nX-Gnus-Groups: "
(when (and
(boundp 'gnus-command-method)
gnus-command-method)
(mapconcat
(lambda (group-art)
(let ((server (second gnus-command-method))
(backend
(symbol-name (first gnus-command-method)))
;; (article-number (cdr group-art))
(group-name (car group-art)))
(format "%s%s:%s"
backend
(if (string-equal server "")
server
(format "+%s" server))
group-name)))
group-art-list ", ")))))))
(with-temp-buffer
;; Or coding-system-for-write
(let ((buffer-file-coding-system
gnuslog-file-coding-system))
(insert msg "\n\n")
(append-to-file (point-min) (point-max) gnuslog-file))))))
;;; Summary Formatting
;; This is what *I* use. You may want to adapt it.
(defvar gnuslog-summary-line-format
"%U%R%z%I%(%[%4L: %-23,23f%]%) %-12u&gnus-groups; %s\n"
;; "%ua%U%R%4N %6&user-date; %1{%[%} %(%-20,20f%)%* %1{%]%} %0{%S%} => %u&gnus-groups;\n"
)
(defun gnus-user-format-function-gnus-groups (header)
;; Fetch the X-Gnus-Groups header
(let ((folder (cdr (assq 'X-Gnus-Groups
(mail-header-extra header)))))
(if (or (not folder)
(string= "" folder))
(propertize "(none)" 'face gnus-face-1)
folder)))
(add-hook 'gnus-started-hook
(lambda ()
(add-to-list 'gnus-extra-headers 'X-Gnus-Groups)))
(add-to-list 'gnus-parameters
'("^nndoc.*\\.gnuslog$"
(gnus-summary-line-format gnuslog-summary-line-format)
(gnus-summary-highlight nil)))
(defun gnuslog-goto-destination-article ()
"Fetch destination article from gnuslog article and display it.
Headers X-Gnus-Groups and References are examined to find destination
article.
"
(interactive)
(let (x-gnus-groups groups message-id)
(save-excursion
(gnus-summary-select-article t 'force)
(set-buffer gnus-original-article-buffer)
(save-restriction
(message-narrow-to-head)
(setq x-gnus-groups (message-fetch-field "X-Gnus-Groups"))
(setq message-id (message-fetch-field "References"))))
(if (null x-gnus-groups)
(message
"gnuslog-goto-destination-article cannot find X-Gnus-Groups header")
(setq groups (split-string x-gnus-groups "\\s-*,\\s-*" t))
(gnus-group-read-group 50 t (first groups))
(if (null message-id)
(message
"gnuslog-goto-destination-article cannot find References header")
(flet
(
;; Disable searching outside current group.
;; Variable gnus-refer-article-method gets ignored, when
;; set to nil!
(gnus-refer-article-methods ()))
(unless
(gnus-summary-goto-article message-id nil t)
(gnus-summary-rescan-group)
(gnus-summary-goto-article message-id nil t)))))))
(provide 'gnuslog)
;;; gnuslog.el ends here