+(defmacro mixi-post-topic-page (community)
+ `(concat "/add_bbs.pl?id=" (mixi-community-id community)))
+
+;; FIXME: Support photos.
+(defun mixi-post-topic (community title content)
+ "Post a topic to COMMUNITY."
+ (unless (mixi-community-p community)
+ (signal 'wrong-type-argument (list 'mixi-community-p community)))
+ (unless (stringp title)
+ (signal 'wrong-type-argument (list 'stringp title)))
+ (unless (stringp content)
+ (signal 'wrong-type-argument (list 'stringp content)))
+ (let ((fields `(("bbs_title" . ,title)
+ ("bbs_body" . ,content)
+ ("submit" . "main")))
+ post-key)
+ (with-mixi-post-form (mixi-post-topic-page community) fields
+ (if (string-match mixi-post-key-regexp buffer)
+ (setq post-key (match-string 1 buffer))
+ (mixi-post-error 'cannot-find-key community)))
+ (setq fields `(("post_key" . ,post-key)
+ ("bbs_title" . ,title)
+ ("bbs_body" . ,content)
+ ("submit" . "confirm")))
+ (with-mixi-post-form (mixi-post-topic-page community) fields
+ (unless (string-match mixi-post-succeed-regexp buffer)
+ (mixi-post-error 'cannot-find-succeed community)))))
+
+;; Event object.
+(defvar mixi-event-cache (make-hash-table :test 'equal))
+(defun mixi-make-event (community id &optional time title owner date place
+ detail limit members)
+ "Return a event object."
+ (mixi-make-cache (list (mixi-community-id community) id)
+ (cons 'mixi-event (vector nil community id time title owner
+ date place detail limit members))
+ mixi-event-cache))
+
+(defconst mixi-event-url-regexp
+ "/view_event\\.pl\\?id=\\([0-9]+\\)\\(&comment_count=[0-9]+\\)?&comm_id=\\([0-9]+\\)")
+
+(defun mixi-make-event-from-url (url)
+ "Return a event object from URL."
+ (when (string-match mixi-event-url-regexp url)
+ (let ((id (match-string 1 url))
+ (community-id (match-string 3 url)))
+ (mixi-make-event (mixi-make-community community-id) id))))
+
+(defmacro mixi-event-p (event)
+ `(eq (mixi-object-class ,event) 'mixi-event))
+
+(defmacro mixi-event-page (event)
+ `(concat "/view_event.pl?id=" (mixi-event-id ,event)
+ "&comm_id=" (mixi-community-id (mixi-event-community ,event))))
+
+(defconst mixi-event-community-regexp
+ "<td WIDTH=595 background=http://img\\.mixi\\.jp/img/bg_w\\.gif><b>\\[\\(.+\\)\\] ¥¤¥Ù¥ó¥È</b></td>")
+(defconst mixi-event-time-regexp
+ "<td ROWSPAN=11 \\(BGCOLOR\\|bgcolor\\)=#FFD8B0 \\(ALIGN\\|align\\)=center \\(VALIGN\\|Valign\\)=top WIDTH=110>
+?\\([0-9]+\\)ǯ\\([0-9]+\\)·î\\([0-9]+\\)Æü<br>
+?\\([0-9]+\\):\\([0-9]+\\)</td>")
+(defconst mixi-event-title-regexp
+ "<td bgcolor=#FFF4E0\\( width=410\\)?> \\([^<]+\\)</td>")
+(defconst mixi-event-owner-regexp
+ "<td \\(BGCOLOR\\|bgcolor\\)=#FDF9F2> <a href=\"show_friend\\.pl\\?id=\\([0-9]+\\)\">\\(.*\\)</a>")
+(defconst mixi-event-date-regexp
+ "<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\) \\(ALIGN\\|align\\)=center NOWRAP>³«ºÅÆü»þ</td>
+<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\)>
+ \\(.+\\)
+</td>")
+(defconst mixi-event-place-regexp
+ "<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\) \\(ALIGN\\|align\\)=center NOWRAP>³«ºÅ¾ì½ê</td>
+<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\)>
+ \\(.+\\)
+</td>")
+(defconst mixi-event-detail-regexp
+ "<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\) \\(ALIGN\\|align\\)=center NOWRAP>¾ÜºÙ</td>
+<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\)><table BORDER=0 CELLSPACING=0 CELLPADDING=5><tr><td CLASS=h120>\\(.+\\)</td></tr></table></td>")
+(defconst mixi-event-limit-regexp
+ "<td \\(BGCOLOR\\|bgcolor\\)=\"?#\\(FFFFFF\\|ffffff\\)\"? \\(ALIGN\\|align\\)=\"?center\"? NOWRAP>Ê罸´ü¸Â</td>
+?<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\)> \\([0-9]+\\)ǯ\\([0-9]+\\)·î\\([0-9]+\\)Æü</td>")
+(defconst mixi-event-members-regexp
+ "<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\) \\(ALIGN\\|align\\)=center NOWRAP>»²²Ã¼Ô</td>
+<td \\(BGCOLOR\\|bgcolor\\)=#\\(FFFFFF\\|ffffff\\)>
+
+?
+?<table BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH=100%>
+<tr>
+
+?<td> \\(.+\\)</td>")
+
+(defun mixi-realize-event (event)
+ "Realize a EVENT."
+ ;; FIXME: Check a expiration of cache?
+ (unless (mixi-object-realized-p event)
+ (with-mixi-retrieve (mixi-event-page event)
+ (if (string-match mixi-event-community-regexp buffer)
+ (mixi-community-set-name (mixi-event-community event)
+ (match-string 1 buffer))
+ (mixi-realization-error 'cannot-find-community event))
+ (if (string-match mixi-event-time-regexp buffer)
+ (mixi-event-set-time
+ event (encode-time 0 (string-to-number (match-string 8 buffer))
+ (string-to-number (match-string 7 buffer))
+ (string-to-number (match-string 6 buffer))
+ (string-to-number (match-string 5 buffer))
+ (string-to-number (match-string 4 buffer))))
+ (mixi-realization-error 'cannot-find-time event))
+ (if (string-match mixi-event-title-regexp buffer)
+ (mixi-event-set-title event (match-string 2 buffer))
+ (mixi-realization-error 'cannot-find-title event))
+ (if (string-match mixi-event-owner-regexp buffer)
+ (mixi-event-set-owner event
+ (mixi-make-friend (match-string 2 buffer)
+ (match-string 3 buffer)))
+ (mixi-realization-error 'cannot-find-owner event))
+ (if (string-match mixi-event-date-regexp buffer)
+ (mixi-event-set-date event (match-string 6 buffer))
+ (mixi-realization-error 'cannot-find-date event))
+ (if (string-match mixi-event-place-regexp buffer)
+ (mixi-event-set-place event (match-string 6 buffer))
+ (mixi-realization-error 'cannot-find-place event))
+ (if (string-match mixi-event-detail-regexp buffer)
+ (mixi-event-set-detail event (match-string 6 buffer))
+ (mixi-realization-error 'cannot-find-detail event))
+ (when (string-match mixi-event-limit-regexp buffer)
+ (mixi-event-set-limit
+ event (encode-time 0 0 0 (string-to-number (match-string 8 buffer))
+ (string-to-number (match-string 7 buffer))
+ (string-to-number (match-string 6 buffer)))))
+ (if (string-match mixi-event-members-regexp buffer)
+ (mixi-event-set-members event (match-string 6 buffer))
+ (mixi-realization-error 'cannot-find-members event)))
+ (mixi-object-touch event)))
+
+(defun mixi-event-community (event)
+ "Return the community of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aref (cdr event) 1))
+
+(defun mixi-event-id (event)
+ "Return the id of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aref (cdr event) 2))
+
+(defun mixi-event-time (event)
+ "Return the time of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (mixi-realize-event event)
+ (aref (cdr event) 3))
+
+(defun mixi-event-title (event)
+ "Return the title of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (mixi-realize-event event)
+ (aref (cdr event) 4))
+
+(defun mixi-event-owner (event)
+ "Return the owner of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (mixi-realize-event event)
+ (aref (cdr event) 5))
+
+(defun mixi-event-date (event)
+ "Return the date of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (mixi-realize-event event)
+ (aref (cdr event) 6))
+
+(defun mixi-event-place (event)
+ "Return the place of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (mixi-realize-event event)
+ (aref (cdr event) 7))
+
+(defun mixi-event-detail (event)
+ "Return the detail of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (mixi-realize-event event)
+ (aref (cdr event) 8))
+
+(defun mixi-event-limit (event)
+ "Return the limit of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (mixi-realize-event event)
+ (aref (cdr event) 9))
+
+(defun mixi-event-members (event)
+ "Return the members of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (mixi-realize-event event)
+ (aref (cdr event) 10))
+
+(defun mixi-event-set-time (event time)
+ "Set the time of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aset (cdr event) 3 time))
+
+(defun mixi-event-set-title (event title)
+ "Set the title of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aset (cdr event) 4 title))
+
+(defun mixi-event-set-owner (event owner)
+ "Set the owner of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (unless (mixi-friend-p owner)
+ (signal 'wrong-type-argument (list 'mixi-friend-p owner)))
+ (aset (cdr event) 5 owner))
+
+(defun mixi-event-set-date (event date)
+ "Set the date of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aset (cdr event) 6 date))
+
+(defun mixi-event-set-place (event place)
+ "Set the place of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aset (cdr event) 7 place))
+
+(defun mixi-event-set-detail (event detail)
+ "Set the detail of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aset (cdr event) 8 detail))
+
+(defun mixi-event-set-limit (event limit)
+ "Set the limit of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aset (cdr event) 9 limit))
+
+(defun mixi-event-set-members (event members)
+ "Set the members of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aset (cdr event) 10 members))
+
+;; Bbs object.
+(defconst mixi-bbs-list '(mixi-topic mixi-event))
+
+(defmacro mixi-bbs-p (object)
+ `(when (memq (mixi-object-class ,object) mixi-bbs-list)
+ t))
+
+(defun mixi-bbs-community (object)
+ "Return the community of OBJECT."
+ (unless (mixi-bbs-p object)
+ (signal 'wrong-type-argument (list 'mixi-bbs-p object)))
+ (let ((func (intern (concat mixi-object-prefix
+ (mixi-object-name object) "-community"))))
+ (funcall func object)))
+
+(defalias 'mixi-bbs-id 'mixi-object-id)
+(defalias 'mixi-bbs-time 'mixi-object-time)
+(defalias 'mixi-bbs-title 'mixi-object-title)
+(defalias 'mixi-bbs-owner 'mixi-object-owner)
+(defalias 'mixi-bbs-content 'mixi-object-content)
+
+(defmacro mixi-bbs-list-page (community)