+;; FIXME: Support photos.
+;;;###autoload
+(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 (re-search-forward mixi-post-key-regexp nil t)
+ (setq post-key (match-string 1))
+ (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 (re-search-forward mixi-post-succeed-regexp nil t)
+ (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 comment-count 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 comment-count
+ 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))
+ (comment-count (match-string 3 url))
+ (community-id (match-string 4 url)))
+ (mixi-make-event (mixi-make-community community-id) id comment-count))))
+
+(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
+ "<div class=\"pageTitle communityTitle002\">
+<h2>\\(.+\\) ¥¤¥Ù¥ó¥È</h2>")
+(defconst mixi-event-title-regexp
+ "<span class=\"title\">\\([^<]+\\)</span>")
+(defconst mixi-event-time-regexp
+ "<span class=\"date\">\\([0-9]+\\)ǯ\\([0-9]+\\)·î\\([0-9]+\\)Æü \\([0-9]+\\):\\([0-9]+\\)</span>")
+(defconst mixi-event-date-regexp
+ "<dt>³«ºÅÆü»þ</dt>
+<dd>\\(.+\\)</dd>")
+(defconst mixi-event-place-regexp
+ "<dt>³«ºÅ¾ì½ê</dt>
+<dd>\\(.+\\)</dd>")
+(defconst mixi-event-owner-regexp
+ "<dt>\\((mixi Âà²ñºÑ)\\|<a href=\"show_friend\\.pl\\?id=\\([0-9]+\\)\">\\(.*\\)</a>\\)</dt>")
+(defconst mixi-event-owner-seceded-regexp
+ "(mixi Âà²ñºÑ)")
+(defconst mixi-event-detail-regexp
+ "<dd>\\(\\(.\\|\r?\n\\)*?\\)</dd>
+</dl>")
+(defconst mixi-event-limit-regexp
+ "<dt>Ê罸´ü¸Â</dt>
+<dd>\\(.+\\)</dd>")
+(defconst mixi-event-members-regexp
+ "<dt>»²²Ã¼Ô</dt>
+<dd>\\(.+\\)</dd>")
+
+(defun mixi-realize-event (event &optional page)
+ "Realize a EVENT."
+ ;; FIXME: Check a expiration of cache?
+ (unless (mixi-object-realized-p event)
+ (with-mixi-retrieve (or page (mixi-event-page event))
+ (let ((case-fold-search t))
+ (if (re-search-forward mixi-event-community-regexp nil t)
+ (mixi-community-set-name (mixi-event-community event)
+ (match-string 1))
+ (mixi-realization-error 'cannot-find-community event))
+ (if (re-search-forward mixi-event-title-regexp nil t)
+ (mixi-event-set-title event (match-string 1))
+ (mixi-realization-error 'cannot-find-title event))
+ (if (re-search-forward mixi-event-time-regexp nil t)
+ (mixi-event-set-time
+ event (encode-time 0 (string-to-number (match-string 5))
+ (string-to-number (match-string 4))
+ (string-to-number (match-string 3))
+ (string-to-number (match-string 2))
+ (string-to-number (match-string 1))))
+ (mixi-realization-error 'cannot-find-time event))
+ (if (re-search-forward mixi-event-date-regexp nil t)
+ (mixi-event-set-date event (match-string 1))
+ (mixi-realization-error 'cannot-find-date event))
+ (if (re-search-forward mixi-event-place-regexp nil t)
+ (mixi-event-set-place event (match-string 1))
+ (mixi-realization-error 'cannot-find-place event))
+ (if (re-search-forward mixi-event-owner-regexp nil t)
+ (let ((seceded-or-not (match-string 1))
+ (id (match-string 2))
+ (nick (match-string 3)))
+ (if (string= mixi-event-owner-seceded-regexp seceded-or-not)
+ (mixi-event-set-owner event
+ (mixi-make-friend nil seceded-or-not))
+ (mixi-event-set-owner event (mixi-make-friend id nick))))
+ (mixi-realization-error 'cannot-find-owner event))
+ (if (re-search-forward mixi-event-detail-regexp nil t)
+ (mixi-event-set-detail event (match-string 1))
+ (mixi-realization-error 'cannot-find-detail event))
+ (if (re-search-forward mixi-event-limit-regexp nil t)
+ (mixi-event-set-limit event (match-string 1))
+ (mixi-realization-error 'cannot-find-limit event))
+ (if (re-search-forward mixi-event-members-regexp nil t)
+ (mixi-event-set-members event (match-string 1))
+ (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-comment-count (event)
+ "Return the comment-count of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aref (cdr event) 3))
+
+(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) 4))
+
+(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) 5))
+
+(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) 6))
+
+(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) 7))
+
+(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) 8))
+
+(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) 9))
+
+(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) 10))
+
+(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) 11))
+
+(defun mixi-event-set-comment-count (event comment-count)
+ "Set the comment-count of EVENT."
+ (unless (mixi-event-p event)
+ (signal 'wrong-type-argument (list 'mixi-event-p event)))
+ (aset (cdr event) 3 comment-count))
+
+(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) 4 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) 5 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) 6 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) 7 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) 8 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) 9 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) 10 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) 11 members))
+
+;; BBS object.
+(defconst mixi-bbs-list '(mixi-topic mixi-event))
+
+(defmacro mixi-bbs-p (bbs)
+ `(memq (mixi-object-class ,bbs) mixi-bbs-list))
+
+(defun mixi-bbs-community (bbs)
+ "Return the community of BBS."
+ (unless (mixi-bbs-p bbs)
+ (signal 'wrong-type-argument (list 'mixi-bbs-p bbs)))
+ (let ((func (intern (concat mixi-object-prefix
+ (mixi-object-name bbs) "-community"))))
+ (funcall func bbs)))
+
+(defun mixi-bbs-comment-count (bbs)
+ "Return the comment-count of BBS."
+ (unless (mixi-bbs-p bbs)
+ (signal 'wrong-type-argument (list 'mixi-bbs-p bbs)))
+ (let ((func (intern (concat mixi-object-prefix
+ (mixi-object-name bbs) "-comment-count"))))
+ (funcall func bbs)))
+
+(defun mixi-bbs-set-comment-count (bbs count)
+ "Set the comment-count of BBS."
+ (unless (mixi-bbs-p bbs)
+ (signal 'wrong-type-argument (list 'mixi-bbs-p bbs)))
+ (let ((func (intern (concat mixi-object-prefix
+ (mixi-object-name bbs) "-set-comment-count"))))
+ (funcall func bbs count)))
+
+(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)