* mixi.el (mixi-diary-list-regexp): Fix regexp.
[elisp/mixi.git] / mixi.el
diff --git a/mixi.el b/mixi.el
index 9562a96..789ba27 100644 (file)
--- a/mixi.el
+++ b/mixi.el
@@ -41,6 +41,7 @@
 ;;  * mixi-get-new-comments
 ;;  * mixi-get-messages
 ;;  * mixi-get-introductions
+;;  * mixi-get-news
 ;;
 ;; API for posting:
 ;;
               (executable-find mixi-curl-program))
          'curl)
       (error "Cannot set `mixi-backend'."))
-  "*The function for retrieving."
-  :type '(radio (const :tag "Use w3m" w3m)
+  "*The backend for accessing to mixi."
+  :type '(radio (const :tag "Use emacs-w3m" w3m)
                (const :tag "Use url.el" url)
                (const :tag "Use curl" curl)
                (symbol :tag "The other backend"))
@@ -272,7 +273,7 @@ Increase this value when unexpected error frequently occurs."
     (mixi-retrieve url post-data)))
 
 (defmacro mixi-expand-url (url)
-  `(if (string-match (concat "^" mixi-url) ,url)
+  `(if (string-match "^http" ,url)
        ,url
      (concat mixi-url ,url)))
 
@@ -1166,14 +1167,16 @@ Increase this value when unexpected error frequently occurs."
   "Return the time of DIARY."
   (unless (mixi-diary-p diary)
     (signal 'wrong-type-argument (list 'mixi-diary-p diary)))
-  (mixi-realize-diary diary)
+  (unless (aref (cdr diary) 3)
+    (mixi-realize-diary diary))
   (aref (cdr diary) 3))
 
 (defun mixi-diary-title (diary)
   "Return the title of DIARY."
   (unless (mixi-diary-p diary)
     (signal 'wrong-type-argument (list 'mixi-diary-p diary)))
-  (mixi-realize-diary diary)
+  (unless (aref (cdr diary) 4)
+    (mixi-realize-diary diary))
   (aref (cdr diary) 4))
 
 (defun mixi-diary-content (diary)
@@ -1206,7 +1209,9 @@ Increase this value when unexpected error frequently occurs."
           (when ,friend (concat "&id=" (mixi-friend-id ,friend)))))
 
 (defconst mixi-diary-list-regexp
-  "<a href=\"view_diary\\.pl\\?id=\\([0-9]+\\)&owner_id=[0-9]+\">")
+  "<tr VALIGN=top>
+<td ALIGN=center ROWSPAN=3 NOWRAP bgcolor=#F2DDB7><font COLOR=#996600>\\([0-9]+\\)·î\\([0-9]+\\)Æü<br>\\([0-9]+\\):\\([0-9]+\\)</font>\\(<br><input type=\"checkbox\" name=\"diary_id\" value=\"[0-9]+\">\\|\\)</td>
+<td bgcolor=\"#FFF4E0\">&nbsp;<a href=\"view_diary\\.pl\\?id=\\([0-9]+\\)&owner_id=[0-9]+\">\\(.*\\)</a></td>")
 
 (defun mixi-get-diaries (&rest friend-or-range)
   "Get diaries of FRIEND."
@@ -1222,16 +1227,29 @@ Increase this value when unexpected error frequently occurs."
       (signal 'wrong-type-argument (list 'mixi-friend-p friend)))
     (let ((items (mixi-get-matched-items (mixi-diary-list-page friend)
                                         mixi-diary-list-regexp
-                                        range)))
+                                        range))
+         (year (nth 5 (decode-time (current-time))))
+         (month (nth 4 (decode-time (current-time)))))
       (mapcar (lambda (item)
-               (mixi-make-diary friend (nth 0 item)))
+               (let ((month-of-item (string-to-number (nth 0 item))))
+                 (when (> month-of-item month)
+                   (decf year))
+                 (setq month month-of-item)
+                 (mixi-make-diary friend (nth 5 item)
+                                  (encode-time
+                                   0 (string-to-number (nth 3 item))
+                                   (string-to-number (nth 2 item))
+                                   (string-to-number (nth 1 item))
+                                   month year)
+                                  (nth 6 item))))
              items))))
 
 (defmacro mixi-new-diary-list-page ()
   `(concat "/new_friend_diary.pl?page=%d"))
 
 (defconst mixi-new-diary-list-regexp
-  "<a class=\"new_link\" href=view_diary\\.pl\\?id=\\([0-9]+\\)&owner_id=\\([0-9]+\\)>")
+  "<td WIDTH=180><img src=http://img\\.mixi\\.jp/img/pen\\.gif ALIGN=left WIDTH=14 HEIGHT=16>\\([0-9]+\\)ǯ\\([0-9]+\\)·î\\([0-9]+\\)Æü \\([0-9]+\\):\\([0-9]+\\)</td>
+<td WIDTH=450><a class=\"new_link\" href=view_diary\\.pl\\?id=\\([0-9]+\\)&owner_id=\\([0-9]+\\)>\\(.+\\)</a> (\\(.*\\)) ")
 
 (defun mixi-get-new-diaries (&optional range)
   "Get new diaries."
@@ -1239,22 +1257,63 @@ Increase this value when unexpected error frequently occurs."
                                       mixi-new-diary-list-regexp
                                       range)))
     (mapcar (lambda (item)
-             (mixi-make-diary (mixi-make-friend (nth 1 item)) (nth 0 item)))
+             (mixi-make-diary (mixi-make-friend (nth 6 item) (nth 8 item))
+                              (nth 5 item)
+                              (encode-time
+                               0 (string-to-number (nth 4 item))
+                               (string-to-number (nth 3 item))
+                               (string-to-number (nth 2 item))
+                               (string-to-number (nth 1 item))
+                               (string-to-number (nth 0 item)))
+                              (nth 7 item)))
            items)))
 
 (defmacro mixi-search-diary-list-page (keyword)
   `(concat "/search_diary.pl?page=%d&submit=search&keyword="
-            (mixi-url-encode-and-quote-percent-string keyword)))
+            (mixi-url-encode-and-quote-percent-string ,keyword)))
 
 (defconst mixi-search-diary-list-regexp
-  "<a href=\"view_diary\\.pl\\?id=\\([0-9]+\\)&owner_id=\\([0-9]+\\)\">")
+  "<td BGCOLOR=#FDF9F2><font COLOR=#996600>̾&nbsp;&nbsp;Á°</font></td>
+<td COLSPAN=2 BGCOLOR=#FFFFFF>\\(.*\\)
+
+</td></tr>
+
+<tr>
+<td BGCOLOR=#FDF9F2><font COLOR=#996600>¥¿¥¤¥È¥ë</font></td>
+<td COLSPAN=2 BGCOLOR=#FFFFFF>\\(.+\\)</td></tr>
+
+<tr>
+<td BGCOLOR=#FDF9F2><font COLOR=#996600>ËÜ&nbsp;&nbsp;ʸ</font></td>
+<td COLSPAN=2 BGCOLOR=#FFFFFF>\\(.*\\)</td></tr>
+
+
+<tr>
+<td NOWRAP BGCOLOR=#FDF9F2 WIDTH=80><font COLOR=#996600>ºîÀ®Æü»þ</font></td>
+<td BGCOLOR=#FFFFFF WIDTH=220>\\([0-9]+\\)·î\\([0-9]+\\)Æü \\([0-9]+\\):\\([0-9]+\\)</td>
+<td ALIGN=center BGCOLOR=#FDF9F2 width=250><a href=\"view_diary\\.pl\\?id=\\([0-9]+\\)&owner_id=\\([0-9]+\\)\"><img src=http://img\\.mixi\\.jp/img/shbtn\\.gif ALT=¾ÜºÙ¤ò¸«¤ë BORDER=0 WIDTH=104 HEIGHT=19></a></td></tr>
+</table>
+</td></tr></table>")
 
 (defun mixi-search-diaries (keyword &optional range)
   (let ((items (mixi-get-matched-items (mixi-search-diary-list-page keyword)
                                       mixi-search-diary-list-regexp
-                                      range)))
+                                      range))
+       (year (nth 5 (decode-time (current-time))))
+       (month (nth 4 (decode-time (current-time)))))
     (mapcar (lambda (item)
-             (mixi-make-diary (mixi-make-friend (nth 1 item)) (nth 0 item)))
+               (let ((month-of-item (string-to-number (nth 3 item))))
+                 (when (> month-of-item month)
+                   (decf year))
+                 (setq month month-of-item)
+                 (mixi-make-diary (mixi-make-friend (nth 8 item) (nth 0 item))
+                                  (nth 7 item)
+                                  (encode-time
+                                   0 (string-to-number (nth 6 item))
+                                   (string-to-number (nth 5 item))
+                                   (string-to-number (nth 4 item))
+                                   month year)
+                                  (nth 1 item)
+                                  (nth 2 item))))
            items)))
 
 (defmacro mixi-post-diary-page ()
@@ -1322,29 +1381,28 @@ Increase this value when unexpected error frequently occurs."
 (defconst mixi-community-name-regexp
   "<td WIDTH=345>\\(.*\\)</td></tr>")
 (defconst mixi-community-birthday-regexp
-  "<td BGCOLOR=#F2DDB7><font COLOR=#996600>³«ÀßÆü</font></td>\r
-<td>\\([0-9]+\\)ǯ\\([0-9]+\\)·î\\([0-9]+\\)Æü</td>")
+  "<td BGCOLOR=#F2DDB7 WIDTH=80><font COLOR=#996600>³«ÀßÆü</font></td>\r
+<td WIDTH=345>\\([0-9]+\\)ǯ\\([0-9]+\\)·î\\([0-9]+\\)Æü</td>")
 ;; FIXME: Care when the owner has seceded.
 (defconst mixi-community-owner-regexp
-  "<td BGCOLOR=#F2DDB7><font COLOR=#996600>´ÉÍý¿Í</font></td>\r
-<td>\r
-\r
-<a href=\"\\(home\\.pl\\|show_friend\\.pl\\?id=\\([0-9]+\\)\\)\">\r
-\\(.*\\)</a>")
+  "<td BGCOLOR=#F2DDB7 WIDTH=80><font COLOR=#996600>´ÉÍý¿Í</font></td>\r
+<td WIDTH=345>\r
+<table style=\"width: 100%;\"><tr><td>\r
+<a href=\"\\(home\\.pl\\|show_friend\\.pl\\?id=\\([0-9]+\\)\\)\">\\(.*\\)</a>")
 (defconst mixi-community-category-regexp
-  "<td BGCOLOR=#F2DDB7><font COLOR=#996600>¥«¥Æ¥´¥ê</font></td>\r
-<td>\\([^<]+\\)</td>")
+  "<td BGCOLOR=#F2DDB7 WIDTH=80><font COLOR=#996600>¥«¥Æ¥´¥ê</font></td>\r
+<td WIDTH=345>\\([^<]+\\)</td>")
 (defconst mixi-community-members-regexp
-  "<td BGCOLOR=#F2DDB7><font COLOR=#996600>¥á¥ó¥Ð¡¼¿ô</font></td>\r
-<td>\\([0-9]+\\)¿Í</td></tr>")
+  "<td BGCOLOR=#F2DDB7 WIDTH=80><font COLOR=#996600>¥á¥ó¥Ð¡¼¿ô</font></td>\r
+<td WIDTH=345>\\([0-9]+\\)¿Í</td></tr>")
 (defconst mixi-community-open-level-regexp
-  "<td BGCOLOR=#F2DDB7><font COLOR=#996600>»²²Ã¾ò·ï¤È<br>¸ø³«¥ì¥Ù¥ë</font></td>\r
-<td>\\(.+\\)</td></tr>")
+  "<td BGCOLOR=#F2DDB7 WIDTH=80><font COLOR=#996600>»²²Ã¾ò·ï¤È<br>¸ø³«¥ì¥Ù¥ë</font></td>\r
+<td WIDTH=345>\\(.+\\)</td></tr>")
 (defconst mixi-community-authority-regexp
-  "<td BGCOLOR=#F2DDB7><font COLOR=#996600>¥È¥Ô¥Ã¥¯ºîÀ®¤Î¸¢¸Â</font></td>\r
-<td>\\(.+\\)</td></tr>")
+  "<td BGCOLOR=#F2DDB7 WIDTH=80><font COLOR=#996600>¥È¥Ô¥Ã¥¯ºîÀ®¤Î¸¢¸Â</font></td>\r
+<td WIDTH=345>\\(.+\\)</td></tr>")
 (defconst mixi-community-description-regexp
-  "<td CLASS=h120>\\(.+\\)</td>")
+  "<td CLASS=h120 WIDTH=345>\\(.+\\)</td>")
 
 (defun mixi-realize-community (community)
   "Realize a COMMUNITY."
@@ -1539,7 +1597,7 @@ Increase this value when unexpected error frequently occurs."
 
 (defmacro mixi-search-community-list-page (keyword)
   `(concat "/search_community.pl?page=%d&&sort=date&type=com&submit=main"
-          "&keyword=" (mixi-url-encode-and-quote-percent-string keyword)
+          "&keyword=" (mixi-url-encode-and-quote-percent-string ,keyword)
           "&category_id=0"))
 
 (defconst mixi-search-community-list-regexp
@@ -1592,7 +1650,7 @@ Increase this value when unexpected error frequently occurs."
 (defconst mixi-topic-owner-regexp
   "<td bgcolor=\"#fdf9f2\">&nbsp;<font color=\"#dfb479\"></font>&nbsp;<a href=\"show_friend\\.pl\\?id=\\([0-9]+\\)\">\\(.*?\\)\\(¤µ¤ó\\)?</a>")
 (defconst mixi-topic-content-regexp
-  "<table width=\"500\" border=\"0\" cellspacing=\"0\" cellpadding=\"5\"><tr><td class=\"h120\"><table><tr>\\(<td width=\"130\" height=\"140\" align=\"center\" valign=\"middle\"><a href=\"javascript:void(0)\" onClick=\"MM_openBrWindow('show_bbs_picture\\.pl\\?id=[0-9]+&number=[0-9]+','pict','width=680,height=660,toolbar=no,scrollbars=yes,left=5,top=5')\"><img src=\"http://ic[0-9]+\\.mixi\\.jp/[^.]+\\.jpg\" border=\"0\"></a></td>\n\\)*</tr></table>\\(.+\\)</td></tr></table>")
+  "<table width=\"500\" border=\"0\" cellspacing=\"0\" cellpadding=\"5\"><tr><td class=\"h120\"><table><tr>\\(<td width=\"130\" height=\"140\" align=\"center\" valign=\"middle\"><a href=\"javascript:void(0)\" onClick=\"MM_openBrWindow('show_bbs_picture\\.pl\\?id=[0-9]+&comm_id=[0-9]+&number=[0-9]+','pict','width=680,height=660,toolbar=no,scrollbars=yes,left=5,top=5')\"><img src=\"http://ic[0-9]+\\.mixi\\.jp/[^.]+\\.jpg\" border=\"0\"></a></td>\n\\)*</tr></table>\\(.+\\)</td></tr></table>")
 
 (defun mixi-realize-topic (topic)
   "Realize a TOPIC."
@@ -1953,8 +2011,7 @@ Increase this value when unexpected error frequently occurs."
 (defconst mixi-bbs-list '(mixi-topic mixi-event))
 
 (defmacro mixi-bbs-p (object)
-  `(when (memq (mixi-object-class ,object) mixi-bbs-list)
-     t))
+  `(memq (mixi-object-class ,object) mixi-bbs-list))
 
 (defun mixi-bbs-community (object)
   "Return the community of OBJECT."
@@ -2014,7 +2071,7 @@ Increase this value when unexpected error frequently occurs."
 
 (defmacro mixi-search-bbs-list-page (keyword)
   `(concat "/search_topic.pl?page=%d&type=top&submit=search"
-          "&keyword=" (mixi-url-encode-and-quote-percent-string keyword)
+          "&keyword=" (mixi-url-encode-and-quote-percent-string ,keyword)
           "&community_id=0&category_id=0"))
 
 (defconst mixi-search-bbs-list-regexp
@@ -2152,9 +2209,12 @@ Increase this value when unexpected error frequently occurs."
 <font COLOR=#F8A448><b>[^<]+</b> :</font>
 <a HREF=\"show_friend\\.pl\\?id=\\([0-9]+\\)\">\\(.*\\)</a>
 
-</td>
+\\(<font COLOR=#F2DDB7>|</font>
+<a href=\"delete_bbs_comment\\.pl\\?id=[0-9]+&comm_id=[0-9]+&comment_id=[0-9]+&type=event\">ºï½ü</a>
+
+\\|\\)</td>
 </tr>
-\\(<tr>\\)
+<tr>
 <td ALIGN=center BGCOLOR=#FFFFFF>
 <table BORDER=0 CELLSPACING=0 CELLPADDING=5 WIDTH=500>
 <tr><td CLASS=h120>\\(.+\\)</td></tr>
@@ -2229,7 +2289,7 @@ Increase this value when unexpected error frequently occurs."
   (unless (stringp content)
     (signal 'wrong-type-argument (list 'stringp content)))
   (let* ((name (mixi-object-name parent))
-        (page (intern (concat mixi-object-prefix "-post" name
+        (page (intern (concat mixi-object-prefix "post-" name
                               "-comment-page")))
         fields post-key)
     (if (mixi-diary-p parent)
@@ -2258,8 +2318,7 @@ Increase this value when unexpected error frequently occurs."
 (defconst mixi-message-box-list '(inbox outbox savebox thrash)) ; thrash?
 
 (defmacro mixi-message-box-p (box)
-  `(when (memq ,box mixi-message-box-list)
-     t))
+  `(memq ,box mixi-message-box-list))
 
 (defun mixi-message-box-name (box)
   "Return the name of BOX."
@@ -2546,6 +2605,207 @@ Increase this value when unexpected error frequently occurs."
                                        (nth 2 item)))
              items))))
 
+;; News object.
+(defvar mixi-news-cache (make-hash-table :test 'equal))
+(defun mixi-make-news (media-id id &optional media time title content)
+  "Return a news object."
+  (mixi-make-cache (list media-id id)
+                  (cons 'mixi-news (vector nil media-id id media time title
+                                           content))
+                  mixi-news-cache))
+
+(defconst mixi-news-url-regexp
+  "/view_news\\.pl\\?id=\\([0-9]+\\)&media_id=\\([0-9]+\\)")
+
+(defun mixi-make-news-from-url (url)
+  "Return a news object from URL."
+  (when (string-match mixi-news-url-regexp url)
+    (let ((id (match-string 1 url))
+         (media-id (match-string 2 url)))
+      (mixi-make-news media-id id))))
+
+(defmacro mixi-news-p (news)
+  `(eq (mixi-object-class ,news) 'mixi-news))
+
+(defmacro mixi-news-page (news)
+  `(concat "http://news.mixi.jp/view_news.pl?id=" (mixi-news-id ,news)
+          "&media_id=" (mixi-news-media-id ,news)))
+
+(defconst mixi-news-title-regexp
+  "<td HEIGHT=\"46\" STYLE=\"font-weight: bold;font-size: 14px;\" CLASS=\"h130\">\\(.+\\)</td>")
+(defconst mixi-news-media-time-regexp
+  "<td COLSPAN=\"2\" ALIGN=\"right\">(\\(.+\\)&nbsp;-&nbsp;\\([0-9]+\\)·î\\([0-9]+\\)Æü \\([0-9]+\\):\\([0-9]+\\))</td></tr>")
+(defconst mixi-news-content-regexp
+  "<td CLASS=\"h150\">
+
+\\(.+\\)
+
+?
+
+\\(</td>\\|<br>\\)")
+
+(defun mixi-realize-news (news)
+  "Realize a NEWS."
+  ;; FIXME: Check a expiration of cache?
+  (unless (mixi-object-realized-p news)
+    (with-mixi-retrieve (mixi-news-page news)
+      (if (string-match mixi-news-title-regexp buffer)
+         (mixi-news-set-title news (match-string 1 buffer))
+       (mixi-realization-error 'cannot-find-title news))
+      (if (string-match mixi-news-media-time-regexp buffer)
+         (progn
+           (mixi-news-set-media news (match-string 1 buffer))
+           (let ((year (nth 5 (decode-time (current-time))))
+                 (month (nth 4 (decode-time (current-time))))
+                 (month-of-item (string-to-number (match-string 2 buffer))))
+             (when (> month-of-item month)
+               (decf year))
+             (mixi-news-set-time
+              news (encode-time 0 (string-to-number (match-string 5 buffer))
+                                (string-to-number (match-string 4 buffer))
+                                (string-to-number (match-string 3 buffer))
+                                month year))))
+       (mixi-realization-error 'cannot-find-media-time news))
+      (if (string-match mixi-news-content-regexp buffer)
+         (mixi-news-set-content news (match-string 1 buffer))
+       (mixi-realization-error 'cannot-find-content news)))
+    (mixi-object-touch news)))
+
+(defun mixi-news-media-id (news)
+  "Return the media-id of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (aref (cdr news) 1))
+
+(defun mixi-news-id (news)
+  "Return the id of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (aref (cdr news) 2))
+
+(defun mixi-news-media (news)
+  "Return the media of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (unless (aref (cdr news) 3)
+    (mixi-realize-news news))
+  (aref (cdr news) 3))
+
+(defun mixi-news-time (news)
+  "Return the time of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (unless (aref (cdr news) 4)
+    (mixi-realize-news news))
+  (aref (cdr news) 4))
+
+(defun mixi-news-title (news)
+  "Return the title of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (unless (aref (cdr news) 5)
+    (mixi-realize-news news))
+  (aref (cdr news) 5))
+
+(defun mixi-news-content (news)
+  "Return the content of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (mixi-realize-news news)
+  (aref (cdr news) 6))
+
+(defun mixi-news-set-media (news media)
+  "Set the media of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (aset (cdr news) 3 media))
+
+(defun mixi-news-set-time (news time)
+  "Set the time of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (aset (cdr news) 4 time))
+
+(defun mixi-news-set-title (news title)
+  "Set the title of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (aset (cdr news) 5 title))
+
+(defun mixi-news-set-content (news content)
+  "Set the content of NEWS."
+  (unless (mixi-news-p news)
+    (signal 'wrong-type-argument (list 'mixi-news-p news)))
+  (aset (cdr news) 6 content))
+
+(defconst mixi-news-category-list '(domestic politics economy area abroad
+                                            sports entertainment IT))
+
+(defmacro mixi-news-category-p (category)
+  `(memq ,category mixi-news-category-list))
+
+(defun mixi-news-category-id (category)
+  "Return the id of CATEGORY."
+  (unless (mixi-news-category-p category)
+    (signal 'wrong-type-argument (list 'mixi-news-category-p category)))
+  (number-to-string
+   (1+ (- (length mixi-news-category-list)
+         (length (memq category mixi-news-category-list))))))
+
+(defconst mixi-news-sort-list '(newest pickup))
+
+(defmacro mixi-news-sort-p (sort)
+  `(memq ,sort mixi-news-sort-list))
+
+(defun mixi-news-sort-id (sort)
+  "Return the id of SORT."
+  (unless (mixi-news-sort-p sort)
+    (signal 'wrong-type-argument (list 'mixi-news-sort-p sort)))
+  (number-to-string
+   (- (length mixi-news-sort-list)
+      (length (memq sort mixi-news-sort-list)))))
+
+(defmacro mixi-news-list-page (category sort)
+  `(concat "http://news.mixi.jp/list_news_category.pl?page=%d"
+          "&sort=" (mixi-news-sort-id ,sort)
+          "&id=" (mixi-news-category-id ,category)
+          "&type=bn"))
+
+(defconst mixi-news-list-regexp
+  "<tr bgcolor=\"\\(#FCF5EB\\|#FFFFFF\\)\">
+<td WIDTH=\"1%\" valign=top CLASS=\"h120\">¡¦</td>
+<td WIDTH=\"97%\" CLASS=\"h120\"><A HREF=\"view_news\\.pl\\?id=\\([0-9]+\\)&media_id=\\([0-9]+\\)\"class=\"new_link\">\\(.+\\)</A>
+\\(<IMG SRC=\"http://img\\.mixi\\.jp/img/news_camera3\\.gif\" WIDTH=\"11\" HEIGHT=\"12\">\\|\\)
+
+</td>
+<td WIDTH=\"1%\" nowrap CLASS=\"f08\"><A HREF=\"list_news_media\\.pl\\?id=[0-9]+\">\\(.+\\)</A></td>
+<td WIDTH=\"1%\" nowrap CLASS=\"f08\">\\([0-9]+\\)·î\\([0-9]+\\)Æü \\([0-9]+\\):\\([0-9]+\\)</td></tr>")
+
+(defun mixi-get-news (category sort &optional range)
+  "Get news of CATEGORY and SORT."
+  (unless (mixi-news-category-p category)
+    (signal 'wrong-type-argument (list 'mixi-news-category-p category)))
+  (unless (mixi-news-sort-p sort)
+    (signal 'wrong-type-argument (list 'mixi-news-sort-p sort)))
+  (let ((items (mixi-get-matched-items (mixi-news-list-page category sort)
+                                      mixi-news-list-regexp
+                                      range))
+       (year (nth 5 (decode-time (current-time))))
+       (month (nth 4 (decode-time (current-time)))))
+    (mapcar (lambda (item)
+             (let ((month-of-item (string-to-number (nth 6 item))))
+               (when (> month-of-item month)
+                 (decf year))
+               (setq month month-of-item)
+               (mixi-make-news (nth 2 item) (nth 1 item) (nth 5 item)
+                               (encode-time
+                                0 (string-to-number (nth 9 item))
+                                (string-to-number (nth 8 item))
+                                (string-to-number (nth 7 item))
+                                month year)
+                               (nth 3 item))))
+           items)))
+
 (provide 'mixi)
 
 ;;; mixi.el ends here