;; * mixi-get-new-comments
;; * mixi-get-messages
;; * mixi-get-introductions
+;;
+;; API for posting:
+;;
+;; * mixi-post-diary
+;; * mixi-post-topic
+;; * mixi-post-comment
+;; * mixi-post-message
;;
;; Utilities:
;;
(put 'mixi-realization-error
'error-conditions '(mixi-realization-error error))
+(put 'mixi-post-error
+ 'error-message (mixi-message "Cannot post"))
+(put 'mixi-post-error
+ 'error-conditions '(mixi-post-error error))
+
(defmacro mixi-realization-error (type object)
`(let ((data (if (and (boundp 'buffer) debug-on-error)
(list ,type ,object buffer)
(list ,type ,object))))
(signal 'mixi-realization-error data)))
+(defmacro mixi-post-error (type &optional object)
+ `(let ((data (when (and (boundp 'buffer) debug-on-error)
+ (list buffer))))
+ (if ,object
+ (setq data (cons ,type (cons ,object data)))
+ (setq data (cons ,type data)))
+ (signal 'mixi-post-error data)))
+
(defconst mixi-message-adult-contents
"¤³¤Î¥Ú¡¼¥¸¤«¤éÀè¤Ï¥¢¥À¥ë¥È¡ÊÀ®¿Í¸þ¤±¡Ë¥³¥ó¥Æ¥ó¥Ä¤¬´Þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡£<br>
±ÜÍ÷¤ËƱ°Õ¤µ¤ì¤¿Êý¤Î¤ß¡¢Àè¤Ø¤ª¿Ê¤ß¤¯¤À¤µ¤¤¡£")
(defmacro mixi-retrieve (url &optional post-data)
`(funcall mixi-retrieve-function ,url ,post-data))
+;; FIXME: Change `mixi-retrieve-function' to `mixi-backend'.
+(defmacro mixi-post-form (url fields)
+ `(let ((name (symbol-name mixi-retrieve-function)))
+ (when (string-match "-\\([a-z]+\\)-" name)
+ (let ((func (intern (concat "mixi-" (match-string 1 name)
+ "-post-form"))))
+ (funcall func ,url ,fields)))))
+
(defun mixi-parse-buffer (url buffer &optional post-data)
(when (string-match mixi-message-adult-contents buffer)
(if mixi-accept-adult-contents
,url
(concat mixi-url ,url)))
-(defun mixi-url-retrieve (url &optional post-data)
+;; FIXME: Support file, checkbox and so on.
+(defun mixi-make-form-data (fields)
+ "Make form data and return (CONTENT-TYPE . FORM-DATA)."
+ (let* ((boundary (apply 'format "--_%d_%d_%d" (current-time)))
+ (content-type (concat "multipart/form-data; boundary=" boundary))
+ (form-data
+ (mapconcat
+ (lambda (field)
+ (concat "--" boundary "\r\n"
+ "Content-Disposition: form-data; name=\""
+ (car field) "\"\r\n"
+ "\r\n"
+ (encode-coding-string (cdr field) mixi-coding-system)))
+ fields "\r\n")))
+ (cons content-type (concat form-data "\r\n--" boundary "--"))))
+
+(defun mixi-url-retrieve (url &optional post-data extra-headers)
"Retrieve the URL and return gotten strings."
- (if post-data
- (progn
- (setq url-request-method "POST")
- (setq url-request-data post-data))
- (setq url-request-method "GET")
- (setq url-request-data nil))
- (let* ((url (mixi-expand-url url))
+ (let* ((url-request-method (if post-data "POST" "GET"))
+ (url-request-data post-data)
+ (url-request-extra-headers extra-headers)
+ (url (mixi-expand-url url))
(buffer (url-retrieve-synchronously url))
ret)
(unless (bufferp buffer)
(kill-buffer buffer)
(mixi-parse-buffer url ret post-data))))
+(defun mixi-url-post-form (url fields)
+ (let* ((form-data (mixi-make-form-data fields))
+ (extra-headers `(("Content-Type" . ,(car form-data)))))
+ (mixi-url-retrieve url (cdr form-data) extra-headers)))
+
(defun mixi-w3m-retrieve (url &optional post-data)
"Retrieve the URL and return gotten strings."
(let ((url (mixi-expand-url url)))
(let ((ret (buffer-substring-no-properties (point-min) (point-max))))
(mixi-parse-buffer url ret post-data))))))
+(defun mixi-w3m-post-form (url fields)
+ (let ((form-data (mixi-make-form-data fields)))
+ (mixi-w3m-retrieve url form-data)))
+
(defun mixi-curl-retrieve (url &optional post-data)
"Retrieve the URL and return gotten strings."
(with-temp-buffer
(put 'with-mixi-retrieve 'lisp-indent-function 'defun)
(put 'with-mixi-retrieve 'edebug-form-spec '(form body))
+(defmacro with-mixi-post-form (url fields &rest body)
+ `(let (buffer)
+ (when ,url
+ (setq buffer (mixi-post-form ,url ,fields))
+ (when (string-match "<form action=\"login\\.pl\" method=\"post\">"
+ buffer)
+ (mixi-login)
+ (setq buffer (mixi-post-form ,url ,fields))))
+ ,@body))
+(put 'with-mixi-post-form 'lisp-indent-function 'defun)
+(put 'with-mixi-post-form 'edebug-form-spec '(form body))
+
(defun mixi-get-matched-items (url regexp &optional range)
"Get matched items to REGEXP in URL."
(let ((page 1)
(mixi-make-diary (mixi-make-friend (nth 1 item)) (nth 0 item)))
items)))
+(defmacro mixi-post-diary-page ()
+ `(concat "/add_diary.pl"))
+
+(defconst mixi-post-key-regexp
+ "<input type=\"?hidden\"? name=\"?post_key\"? value=\"\\([a-z0-9]+\\)\">")
+(defconst mixi-post-succeed-regexp
+ "<b>\\(ºîÀ®\\|½ñ¤¹þ¤ß\\)¤¬´°Î»¤·¤Þ¤·¤¿¡£È¿±Ç¤Ë»þ´Ö¤¬¤«¤«¤ë¤³¤È¤¬¤¢¤ê¤Þ¤¹¤Î¤Ç¡¢É½¼¨¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï¾¯¡¹¤ªÂÔ¤Á¤¯¤À¤µ¤¤¡£</b>")
+
+;; FIXME: Support photos.
+(defun mixi-post-diary (title content)
+ "Post a diary."
+ (unless (stringp title)
+ (signal 'wrong-type-argument (list 'stringp title)))
+ (unless (stringp content)
+ (signal 'wrong-type-argument (list 'stringp content)))
+ (let ((fields `(("id" . ,(mixi-friend-id (mixi-make-me)))
+ ("diary_title" . ,title)
+ ("diary_body" . ,content)
+ ("submit" . "main")))
+ post-key)
+ (with-mixi-post-form (mixi-post-diary-page) fields
+ (if (string-match mixi-post-key-regexp buffer)
+ (setq post-key (match-string 1 buffer))
+ (mixi-post-error 'cannot-find-key)))
+ (setq fields `(("post_key" . ,post-key)
+ ("id" . ,(mixi-friend-id (mixi-make-me)))
+ ("diary_title" . ,title)
+ ("diary_body" . ,content)
+ ("submit" . "confirm")))
+ (with-mixi-post-form (mixi-post-diary-page) fields
+ (unless (string-match mixi-post-succeed-regexp buffer)
+ (mixi-post-error 'cannot-find-succeed)))))
+
;; Community object.
(defvar mixi-community-cache (make-hash-table :test 'equal))
(defun mixi-make-community (id &optional name birthday owner category members
(signal 'wrong-type-argument (list 'mixi-topic-p topic)))
(aset (cdr topic) 6 content))
+(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
</table>
</td>
</tr>
-<!-- ¥³¥á¥ó¥ÈËÜʸ : start -->
+<!-- [^ ]+ : start -->
<tr>
<td bgcolor=\"#ffffff\">
<table BORDER=0 CELLSPACING=0 CELLPADDING=[35] WIDTH=410>
(mixi-make-diary (mixi-make-friend (nth 1 item)) (nth 0 item)))
items)))
+(defun mixi-post-diary-comment-page (diary)
+ (concat "/add_comment.pl?&diary_id=" (mixi-diary-id diary)))
+
+(defun mixi-post-topic-comment-page (topic)
+ (concat "/add_bbs_comment.pl?id=" (mixi-topic-id topic)
+ "&comm_id=" (mixi-community-id (mixi-topic-community topic))))
+
+(defun mixi-post-event-comment-page (event)
+ (concat "/add_event_comment.pl?id=" (mixi-event-id event)
+ "&comm_id=" (mixi-community-id (mixi-event-community event))))
+
+;; FIXME: Support photos.
+(defun mixi-post-comment (parent content)
+ "Post a comment to PARENT."
+ (unless (mixi-object-p parent)
+ (signal 'wrong-type-argument (list 'mixi-object-p parent)))
+ (unless (stringp content)
+ (signal 'wrong-type-argument (list 'stringp content)))
+ (let* ((name (mixi-object-name bbs))
+ (page (intern (concat mixi-object-prefix "-post" name
+ "-comment-page")))
+ fields post-key)
+ (if (mixi-diary-p parent)
+ (setq fields
+ `(("owner_id" . ,(mixi-friend-id (mixi-diary-owner diary)))
+ ("comment_body" . ,content)))
+ (setq fields `(("comment" . ,content))))
+ (with-mixi-post-form (funcall page parent) fields
+ (if (string-match mixi-post-key-regexp buffer)
+ (setq post-key (match-string 1 buffer))
+ (mixi-post-error 'cannot-find-key bbs)))
+ (if (mixi-diary-p parent)
+ (setq fields
+ `(("post_key" . ,post-key)
+ ("owner_id" . ,(mixi-friend-id (mixi-diary-owner diary)))
+ ("comment_body" . ,content)
+ ("submit" . "confirm")))
+ (setq fields `(("post_key" . ,post-key)
+ ("comment" . ,content)
+ ("submit" . "confirm"))))
+ (with-mixi-post-form (funcall page parent) fields
+ (unless (string-match mixi-post-succeed-regexp buffer)
+ (mixi-post-error 'cannot-find-succeed bbs)))))
+
;; Message object.
(defconst mixi-message-box-list '(inbox outbox savebox thrash)) ; thrash?
(mixi-make-message (nth 0 item) (nth 1 item)))
items))))
+(defmacro mixi-post-message-page (friend)
+ `(concat "/send_message.pl?id=" (mixi-friend-id friend)))
+
+(defconst mixi-post-message-key-regexp
+ "<input name=post_key type=hidden value=\\([a-z0-9]+\\)>")
+
+(defconst mixi-post-message-succeed-regexp
+ "<b>Á÷¿®´°Î»</b>¤·¤Þ¤·¤¿¡£")
+
+(defun mixi-post-message (friend title content)
+ "Post a message to FRIEND."
+ (unless (mixi-friend-p friend)
+ (signal 'wrong-type-argument (list 'mixi-friend-p friend)))
+ (unless (stringp title)
+ (signal 'wrong-type-argument (list 'stringp title)))
+ (unless (stringp content)
+ (signal 'wrong-type-argument (list 'stringp content)))
+ (let ((fields `(("subject" . ,title)
+ ("body" . ,content)
+ ("submit" . "main")))
+ post-key)
+ (with-mixi-post-form (mixi-post-message-page friend) fields
+ (if (string-match mixi-post-message-key-regexp buffer)
+ (setq post-key (match-string 1 buffer))
+ (mixi-post-error 'cannot-find-key friend)))
+ (setq fields `(("post_key" . ,post-key)
+ ("subject" . ,title)
+ ("body" . ,content)
+ ("yes" . "¡¡Á÷¡¡¿®¡¡")
+ ("submit" . "confirm")))
+ (with-mixi-post-form (mixi-post-message-page friend) fields
+ (unless (string-match mixi-post-message-succeed-regexp buffer)
+ (mixi-post-error 'cannot-find-succeed friend)))))
+
;; Introduction object.
(defun mixi-make-introduction (parent owner content)
"Return a introduction object."