*** empty log message ***
[gnus] / lisp / nnslashdot.el
index b9fc562..c28e35c 100644 (file)
 (defvoo nnslashdot-active-url "http://slashdot.org/search.pl?section=&min=%d"
   "Where nnslashdot will fetch the active file from.")
 
-(defvoo nnslashdot-comments-url "http://slashdot.org/comments.pl?sid=%s&threshold=%d&commentsort=4&mode=flat&startat=%d"
+(defvoo nnslashdot-comments-url "http://slashdot.org/comments.pl?sid=%s&threshold=%d&commentsort=%d&mode=flat&startat=%d"
   "Where nnslashdot will fetch comments from.")
 
 (defvoo nnslashdot-article-url
     "http://slashdot.org/article.pl?sid=%s&mode=nocomment"
   "Where nnslashdot will fetch the article from.")
 
-(defvoo nnslashdot-threshold 0
+(defvoo nnslashdot-threshold -1
   "The article threshold.")
 
-(defvoo nnslashdot-group-number 30
-  "The number of groups to keep updated.")
+(defvoo nnslashdot-threaded t
+  "Whether the nnslashdot groups should be threaded or not.")
+
+(defvoo nnslashdot-group-number 0
+  "The number of non-fresh groups to keep updated.")
+
+(defvoo nnslashdot-login-name ""
+  "The login name to use when posting.")
+
+(defvoo nnslashdot-password ""
+  "The password to use when posting.")
 
 ;;; Internal variables
 
 
 (nnoo-define-basics nnslashdot)
 
-(deffoo nnslashdot-thread-retrieve-headers (articles &optional group server fetch-old)
+(deffoo nnslashdot-retrieve-headers (articles &optional group server fetch-old)
   (nnslashdot-possibly-change-server group server)
+  (unless gnus-nov-is-evil
+    (if nnslashdot-threaded
+       (nnslashdot-threaded-retrieve-headers articles group)
+      (nnslashdot-sane-retrieve-headers articles group))))
+  
+(deffoo nnslashdot-threaded-retrieve-headers (articles group)
   (let ((last (car (last articles)))
        (did nil)
        (start 1)
        (sid (caddr (assoc group nnslashdot-groups)))
-       headers article subject score from date lines parent point
-       startats s)
-    (unless gnus-nov-is-evil
-      (save-excursion
-       (set-buffer nnslashdot-buffer)
-       (let ((case-fold-search t))
-         (erase-buffer)
-         (when (= start 1)
-           (nnweb-insert (format nnslashdot-article-url sid))
-           (goto-char (point-min))
-           (search-forward "Posted by ")
-           (when (looking-at "<a[^>]+>\\([^<]+\\)")
-             (setq from (match-string 1)))
-           (search-forward " on ")
-           (setq date (nnslashdot-date-to-date
-                       (buffer-substring (point) (1- (search-forward "<")))))
-           (forward-line 2)
-           (setq lines (count-lines
-                        (point)
-                        (search-forward
-                         "A href=http://slashdot.org/article.pl")))
-           (push
-            (cons
-             1
-             (make-full-mail-header
-              1 group from date (concat "<" sid "%1@slashdot>")
-              "" 0 lines nil nil))
-            headers)
-           (goto-char (point-max))
-           (while (re-search-backward "startat=\\([0-9]+\\)" nil t)
-             (setq s (match-string 1))
-             (unless (memq s startats)
-               (push s startats)))
-           (unless startats
-             (push 1 startats)))
-         (setq startats (sort startats '<))
-         (while (and (setq start (pop startats))
-                     (< start last))
-           (setq point (goto-char (point-max)))
-           (nnweb-insert
-            (format nnslashdot-comments-url sid nnslashdot-threshold start))
-           (goto-char point)
-           (while (re-search-forward
-                   "<a name=\"\\([0-9]+\\)\"><b>\\([^<]+\\)</b>.*score:\\([^)]+\\))"
-                   nil t)
-             (setq article (string-to-number (match-string 1))
-                   subject (match-string 2)
-                   score (match-string 3))
-             (when (string-match "^Re: *" subject)
-               (setq subject (concat "Re: " (substring subject (match-end 0)))))
-             (forward-line 1)
-             (if (looking-at
-                  "by <a[^>]+>\\([^<]+\\)</a>[ \t\n]*.*(\\([^)]+\\))")
-                 (setq from (concat (match-string 1)
-                                    " <" (match-string 2) ">"))
-               (looking-at "by \\(.+\\) on ")
-               (setq from (match-string 1)))
-             (goto-char (- (match-end 0) 5))
-             (search-forward " on ")
-             (setq date
-                   (nnslashdot-date-to-date
-                    (buffer-substring (point) (progn (end-of-line) (point)))))
-             (setq lines (/ (abs (- (search-forward "<td ")
-                                    (search-forward "</td>")))
-                            70))
-             (forward-line 2)
-             (setq parent
-                   (if (looking-at ".*cid=\\([0-9]+\\)")
-                       (match-string 1)
-                     nil))
-             (setq did t)
-             (push
-              (cons
-               (1+ article)
-               (make-full-mail-header
-                (1+ article) subject
-                from date
-                (concat "<" sid "%"
-                        (number-to-string (1+ article)) 
-                        "@slashdot>")
-                (if parent
-                    (concat "<" sid "%"
-                            (number-to-string (1+ (string-to-number parent)))
-                            "@slashdot>")
-                  "")
-                0 (string-to-number score) nil nil))
-              headers)))))
-      (setq nnslashdot-headers
-           (sort headers (lambda (s1 s2) (< (car s1) (car s2)))))
-      (save-excursion
-       (set-buffer nntp-server-buffer)
-       (erase-buffer)
-       (dolist (header nnslashdot-headers)
-         (nnheader-insert-nov (cdr header))))
-      'nov)))
-
-(deffoo nnslashdot-retrieve-headers (articles &optional group
-                                             server fetch-old)
-  (unless gnus-nov-is-evil
-    (nnslashdot-possibly-change-server group server)
-    (let ((last (car (last articles)))
-         (did nil)
-         (start (max (1- (car articles)) 1))
-         (sid (caddr (assoc group nnslashdot-groups)))
-         headers article subject score from date lines parent point)
-      (save-excursion
-       (set-buffer nnslashdot-buffer)
+       (first-comments t)
+       (startats '(1))
+       headers article subject score from date lines parent point s)
+    (save-excursion
+      (set-buffer nnslashdot-buffer)
+      (let ((case-fold-search t))
        (erase-buffer)
        (when (= start 1)
          (nnweb-insert (format nnslashdot-article-url sid))
          (setq date (nnslashdot-date-to-date
                      (buffer-substring (point) (1- (search-forward "<")))))
          (forward-line 2)
-         (setq lines (count-lines (point)
-                                  (search-forward
-                                   "A href=http://slashdot.org/article.pl")))
+         (setq lines (count-lines
+                      (point)
+                      (search-forward
+                       "A href=http://slashdot.org/article.pl")))
          (push
           (cons
            1
             1 group from date (concat "<" sid "%1@slashdot>")
             "" 0 lines nil nil))
           headers))
-       (while (or (not article)
-                  (and did
-                       (< article last)))
-         (when article
-           (setq start (1+ article)))
+       (while (and (setq start (pop startats))
+                   (< start last))
          (setq point (goto-char (point-max)))
          (nnweb-insert
-          (format nnslashdot-comments-url sid nnslashdot-threshold start))
+          (format nnslashdot-comments-url sid nnslashdot-threshold 0 start))
+         (when first-comments
+           (setq first-comments nil)
+           (goto-char (point-max))
+           (while (re-search-backward "startat=\\([0-9]+\\)" nil t)
+             (setq s (string-to-number (match-string 1)))
+             (unless (memq s startats)
+               (push s startats)))
+           (setq startats (sort startats '<)))
          (goto-char point)
          (while (re-search-forward
-                 "<a name=\"\\([0-9]+\\)\"><b>\\([^<]+\\)</b>.*score\\([^)]+\\))"
+                 "<a name=\"\\([0-9]+\\)\"><b>\\([^<]+\\)</b>.*score:\\([^)]+\\))"
                  nil t)
            (setq article (string-to-number (match-string 1))
                  subject (match-string 2)
                  score (match-string 3))
+           (when (string-match "^Re: *" subject)
+             (setq subject (concat "Re: " (substring subject (match-end 0)))))
            (forward-line 1)
            (if (looking-at
                 "by <a[^>]+>\\([^<]+\\)</a>[ \t\n]*.*(\\([^)]+\\))")
-               (setq from (concat (match-string 1) " <" (match-string 2) ">"))
+               (setq from (concat (match-string 1)
+                                  " <" (match-string 2) ">"))
              (looking-at "by \\(.+\\) on ")
              (setq from (match-string 1)))
            (goto-char (- (match-end 0) 5))
             (cons
              (1+ article)
              (make-full-mail-header
-              (1+ article) (concat subject " (" score ")")
+              (1+ article)
+              (concat subject " (" score ")")
               from date
               (concat "<" sid "%"
                       (number-to-string (1+ article)) 
                           "@slashdot>")
                 "")
               0 lines nil nil))
-            headers))))
-      (setq nnslashdot-headers
-           (sort headers (lambda (s1 s2) (< (car s1) (car s2)))))
-      (save-excursion
-       (set-buffer nntp-server-buffer)
-       (erase-buffer)
-       (dolist (header nnslashdot-headers)
-         (nnheader-insert-nov (cdr header))))
-      'nov)))
+            headers)))))
+    (setq nnslashdot-headers (sort headers 'car-less-than-car))
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (dolist (header nnslashdot-headers)
+       (nnheader-insert-nov (cdr header))))
+    'nov))
+
+(deffoo nnslashdot-sane-retrieve-headers (articles group)
+  (let ((last (car (last articles)))
+       (did nil)
+       (start (max (1- (car articles)) 1))
+       (sid (caddr (assoc group nnslashdot-groups)))
+       headers article subject score from date lines parent point)
+    (save-excursion
+      (set-buffer nnslashdot-buffer)
+      (erase-buffer)
+      (when (= start 1)
+       (nnweb-insert (format nnslashdot-article-url sid))
+       (goto-char (point-min))
+       (search-forward "Posted by ")
+       (when (looking-at "<a[^>]+>\\([^<]+\\)")
+         (setq from (match-string 1)))
+       (search-forward " on ")
+       (setq date (nnslashdot-date-to-date
+                   (buffer-substring (point) (1- (search-forward "<")))))
+       (forward-line 2)
+       (setq lines (count-lines (point)
+                                (search-forward
+                                 "A href=http://slashdot.org/article.pl")))
+       (push
+        (cons
+         1
+         (make-full-mail-header
+          1 group from date (concat "<" sid "%1@slashdot>")
+          "" 0 lines nil nil))
+        headers))
+      (while (or (not article)
+                (and did
+                     (< article last)))
+       (when article
+         (setq start (1+ article)))
+       (setq point (goto-char (point-max)))
+       (nnweb-insert
+        (format nnslashdot-comments-url sid nnslashdot-threshold 4 start))
+       (goto-char point)
+       (while (re-search-forward
+               "<a name=\"\\([0-9]+\\)\"><b>\\([^<]+\\)</b>.*score:\\([^)]+\\))"
+               nil t)
+         (setq article (string-to-number (match-string 1))
+               subject (match-string 2)
+               score (match-string 3))
+         (when (string-match "^Re: *" subject)
+           (setq subject (concat "Re: " (substring subject (match-end 0)))))
+         (forward-line 1)
+         (if (looking-at
+              "by <a[^>]+>\\([^<]+\\)</a>[ \t\n]*.*(\\([^)]+\\))")
+             (setq from (concat (match-string 1) " <" (match-string 2) ">"))
+           (looking-at "by \\(.+\\) on ")
+           (setq from (match-string 1)))
+         (goto-char (- (match-end 0) 5))
+         (search-forward " on ")
+         (setq date
+               (nnslashdot-date-to-date
+                (buffer-substring (point) (progn (end-of-line) (point)))))
+         (setq lines (/ (abs (- (search-forward "<td ")
+                                (search-forward "</td>")))
+                        70))
+         (forward-line 2)
+         (setq parent
+               (if (looking-at ".*cid=\\([0-9]+\\)")
+                   (match-string 1)
+                 nil))
+         (setq did t)
+         (push
+          (cons
+           (1+ article)
+           (make-full-mail-header
+            (1+ article) (concat subject " (" score ")")
+            from date
+            (concat "<" sid "%"
+                    (number-to-string (1+ article)) 
+                    "@slashdot>")
+            (if parent
+                (concat "<" sid "%"
+                        (number-to-string (1+ (string-to-number parent)))
+                        "@slashdot>")
+              "")
+            0 lines nil nil))
+          headers))))
+    (setq nnslashdot-headers
+         (sort headers (lambda (s1 s2) (< (car s1) (car s2)))))
+    (save-excursion
+      (set-buffer nntp-server-buffer)
+      (erase-buffer)
+      (dolist (header nnslashdot-headers)
+       (nnheader-insert-nov (cdr header))))
+    'nov))
 
 (deffoo nnslashdot-request-group (group &optional server dont-check)
   (nnslashdot-possibly-change-server nil server)
                       (point)
                       (progn
                         (re-search-forward
-                         "^<p>.*A href=http://slashdot.org/article.pl")
+                         "<p>.*A href=http://slashdot.org/article.pl")
                         (match-beginning 0)))))
            (search-forward (format "<a name=\"%d\">" (1- article)))
            (setq contents
        (set-buffer (or buffer nntp-server-buffer))
        (erase-buffer)
        (insert contents)
-       ;;(nnweb-remove-markup)
-       ;;(nnweb-decode-entities)
+       (goto-char (point-min))
+       (while (search-forward "<br><br>" nil t)
+         (replace-match "<p>" t t))
        (goto-char (point-min))
        (insert "Content-Type: text/html\nMIME-Version: 1.0\n")
+       (insert "Newsgroups: " (caddr (assoc group nnslashdot-groups))
+               "\n")
        (let ((header (cdr (assq article nnslashdot-headers))))
          (nnheader-insert-header header))
        (nnheader-report 'nnslashdot "Fetched article %s" article)
   (nnslashdot-possibly-change-server nil server)
   (let ((number 0)
        sid elem description articles gname)
+    ;; First we do the Ultramode to get info on all the latest groups.
+    (with-temp-buffer
+      (nnweb-insert "http://slashdot.org/slashdot.xml")
+      (goto-char (point-min))
+      (while (search-forward "<story>" nil t)
+       (narrow-to-region (point) (search-forward "</story>"))
+       (goto-char (point-min))
+       (re-search-forward "<title>\\([^<]+\\)</title>")
+       (setq description (match-string 1))
+       (re-search-forward "<url>\\([^<]+\\)</url>")
+       (setq sid (match-string 1))
+       (string-match "/\\([0-9/]+\\).shtml" sid)
+       (setq sid (match-string 1 sid))
+       (re-search-forward "<comments>\\([^<]+\\)</comments>")
+       (setq articles (string-to-number (match-string 1)))
+       (setq gname (concat description " (" sid ")"))
+       (if (setq elem (assoc gname nnslashdot-groups))
+           (setcar (cdr elem) articles)
+         (push (list gname articles sid) nnslashdot-groups))
+       (goto-char (point-max))
+       (widen)))
+    ;; Then do the older groups.
     (while (> (- nnslashdot-group-number number) 0)
       (with-temp-buffer
        (let ((case-fold-search t))
   (nnslashdot-generate-active)
   t)
 
+(deffoo nnslashdot-request-post (&optional server)
+  (nnslashdot-possibly-change-server nil server)
+  (let ((sid (message-fetch-field "newsgroups"))
+       (subject (message-fetch-field "subject"))
+       (references (car (last (split-string
+                               (message-fetch-field "references")))))
+       body quoted pid)
+    (string-match "%\\([0-9]+\\)@slashdot" references)
+    (setq pid (match-string 1 references))
+    (message-goto-body)
+    (narrow-to-region (point) (progn (message-goto-signature) (point)))
+    (goto-char (point-min))
+    (while (not (eobp))
+      (if (looking-at "> ")
+         (progn
+           (delete-region (point) (+ (point) 2))
+           (unless quoted
+             (insert "<blockquote>\n"))
+           (setq quoted t))
+       (when quoted
+         (insert "</blockquote>\n")
+         (setq quoted nil)))
+      (forward-line 1))
+    (widen)
+    (when (message-goto-signature)
+      (forward-line -1)
+      (insert "<p>\n")
+      (while (not (eobp))
+       (end-of-line)
+       (insert "<br>")
+       (forward-line 1)))
+    (message-goto-body)
+    (setq body (buffer-substring (point) (point-max)))
+    (erase-buffer)
+    (nnweb-fetch-form
+     "http://slashdot.org/comments.pl"
+     `(("sid" . ,sid)
+       ("pid" . ,pid)
+       ("rlogin" . "userlogin")
+       ("unickname" . ,nnslashdot-login-name)
+       ("upasswd" . ,nnslashdot-password)
+       ("postersubj" . ,subject)
+       ("op" . "Submit")
+       ("postercomment" . ,body)
+       ("posttype" . "html")))))
+
 (nnoo-define-skeleton nnslashdot)
 
 ;;; Internal functions
             (format " *nnslashdot %s*" server))))))
 
 (defun nnslashdot-date-to-date (sdate)
-  (let ((elem (split-string sdate)))
+  (let ((elem (delete "" (split-string sdate))))
     (concat (substring (nth 0 elem) 0 3) " "
            (substring (nth 1 elem) 0 3) " "
            (substring (nth 2 elem) 0 2) " "